summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Reinauer <stepan@coresystems.de>2009-01-20 21:36:39 +0000
committerStefan Reinauer <stepan@openbios.org>2009-01-20 21:36:39 +0000
commit5833f7c0e69df069aec918ba9f34b4a0fe0019f5 (patch)
treebf9a13d4e152164f953ad06b5861845a011580b1 /src
parent20b261dacf56a0bf09a74931cd511537b79b6983 (diff)
Backport all x86emu fixes from Pattrick Hueper to coreboot v2 (acked in v2,
hence I consider it trivial in this case). This does not include the Yabel work. Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3880 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
-rw-r--r--src/devices/emulator/x86emu/debug.c10
-rw-r--r--src/devices/emulator/x86emu/debug.h20
-rw-r--r--src/devices/emulator/x86emu/ops.c172
-rw-r--r--src/devices/emulator/x86emu/ops2.c79
-rw-r--r--src/devices/emulator/x86emu/prim_ops.c17
-rw-r--r--src/devices/emulator/x86emu/sys.c6
-rw-r--r--src/include/x86emu/fpu_regs.h5
-rw-r--r--src/include/x86emu/regs.h14
-rw-r--r--src/include/x86emu/types.h12
-rw-r--r--src/include/x86emu/x86emu.h6
10 files changed, 260 insertions, 81 deletions
diff --git a/src/devices/emulator/x86emu/debug.c b/src/devices/emulator/x86emu/debug.c
index e25229a689..fea52bfd38 100644
--- a/src/devices/emulator/x86emu/debug.c
+++ b/src/devices/emulator/x86emu/debug.c
@@ -52,7 +52,11 @@ static int parse_line (char *s, int *ps, int *n);
void X86EMU_trace_regs (void)
{
if (DEBUG_TRACE()) {
- x86emu_dump_regs();
+ if (M.x86.mode & (SYSMODE_PREFIX_DATA | SYSMODE_PREFIX_ADDR)) {
+ x86emu_dump_xregs();
+ } else {
+ x86emu_dump_regs();
+ }
}
if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) {
printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
@@ -185,7 +189,7 @@ static void print_encoded_bytes (u16 s, u16 o)
for (i=0; i< M.x86.enc_pos; i++) {
sprintf(buf1+2*i,"%02x", fetch_data_byte_abs(s,o+i));
}
- printk("%-20s",buf1);
+ printk("%-20s ",buf1);
}
static void print_decoded_instruction (void)
@@ -355,6 +359,8 @@ static int parse_line (char *s, int *ps, int *n)
sscanf(s,"%x",&ps[*n]);
*n += 1;
}
+#else
+ return 0;
#endif
}
diff --git a/src/devices/emulator/x86emu/debug.h b/src/devices/emulator/x86emu/debug.h
index d786a3d17f..882e92dfcb 100644
--- a/src/devices/emulator/x86emu/debug.h
+++ b/src/devices/emulator/x86emu/debug.h
@@ -40,8 +40,10 @@
#ifndef __X86EMU_DEBUG_H
#define __X86EMU_DEBUG_H
-//#define DEBUG 0
+#if defined(DEBUG) && (DEBUG == 0)
#undef DEBUG
+#endif
+
/*---------------------- Macros and type definitions ----------------------*/
/* checks to be enabled for "runtime" */
@@ -78,6 +80,8 @@
# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
+# define DEBUG_TRACEJMP() (M.x86.debug & DEBUG_TRACEJMP_F)
+# define DEBUG_TRACEJMPREGS() (M.x86.debug & DEBUG_TRACEJMP_REGS_F)
# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
@@ -96,6 +100,8 @@
# define DEBUG_SYSINT() 0
# define DEBUG_TRACECALL() 0
# define DEBUG_TRACECALLREGS() 0
+# define DEBUG_TRACEJMP() 0
+# define DEBUG_TRACEJMPREGS() 0
# define DEBUG_SYS() 0
# define DEBUG_MEM_TRACE() 0
# define DEBUG_IO_TRACE() 0
@@ -169,14 +175,20 @@
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
-# define RETURN_TRACE(n,u,v) \
+# define RETURN_TRACE(u,v,w,x,s) \
if (DEBUG_TRACECALLREGS()) \
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
- printk("%04x:%04x: %s\n",u,v,n);
+ printk("%04x:%04x: RET %s %04x:%04x\n",u,v,s,w,x);
+# define JMP_TRACE(u,v,w,x,s) \
+ if (DEBUG_TRACEJMPREGS()) \
+ x86emu_dump_regs(); \
+ if (DEBUG_TRACEJMP()) \
+ printk("%04x:%04x: JMP %s%04x:%04x\n", u , v, s, w, x);
#else
# define CALL_TRACE(u,v,w,x,s)
-# define RETURN_TRACE(n,u,v)
+# define RETURN_TRACE(u,v,w,x,s)
+# define JMP_TRACE(u,v,w,x,s)
#endif
#ifdef DEBUG
diff --git a/src/devices/emulator/x86emu/ops.c b/src/devices/emulator/x86emu/ops.c
index 95f7c9e68d..ee4785a4cb 100644
--- a/src/devices/emulator/x86emu/ops.c
+++ b/src/devices/emulator/x86emu/ops.c
@@ -1061,7 +1061,11 @@ void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
imm = (s8)fetch_byte_imm();
DECODE_PRINTF2("PUSH\t%d\n", imm);
TRACE_AND_STEP();
- push_word(imm);
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(imm);
+ } else {
+ push_word(imm);
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -1256,8 +1260,10 @@ void x86emuOp_jump_near_cond(u8 op1)
target = (u16)(M.x86.R_IP + (s16)offset);
DECODE_PRINTF2("%x\n", target);
TRACE_AND_STEP();
- if (cond)
+ if (cond) {
M.x86.R_IP = target;
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -2516,9 +2522,11 @@ void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
count = 1;
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
+ /* move them until (E)CX is ZERO. */
+ count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX = 0;
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
while (count--) {
@@ -2526,6 +2534,8 @@ void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
M.x86.R_SI += inc;
M.x86.R_DI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -2559,9 +2569,11 @@ void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
count = 1;
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
+ /* move them until (E)CX is ZERO. */
+ count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX = 0;
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
while (count--) {
@@ -2574,6 +2586,8 @@ void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
}
M.x86.R_SI += inc;
M.x86.R_DI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -2598,16 +2612,21 @@ void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
val1 = fetch_data_byte(M.x86.R_SI);
val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
cmp_byte(val1, val2);
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_SI += inc;
M.x86.R_DI += inc;
if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
} else {
@@ -2644,8 +2663,8 @@ void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
TRACE_AND_STEP();
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
if (M.x86.mode & SYSMODE_PREFIX_DATA) {
val1 = fetch_data_long(M.x86.R_SI);
val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
@@ -2655,11 +2674,16 @@ void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
cmp_word((u16)val1, (u16)val2);
}
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_SI += inc;
M.x86.R_DI += inc;
if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
} else {
@@ -2741,11 +2765,16 @@ void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
TRACE_AND_STEP();
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_DI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
} else {
@@ -2783,9 +2812,11 @@ void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
count = 1;
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
+ /* move them until (E)CX is ZERO. */
+ count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX = 0;
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
while (count--) {
@@ -2795,6 +2826,8 @@ void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
}
M.x86.R_DI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -2817,11 +2850,16 @@ void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
inc = 1;
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_SI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
} else {
@@ -2859,9 +2897,11 @@ void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
count = 1;
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
+ /* move them until (E)CX is ZERO. */
+ count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX = 0;
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
}
while (count--) {
@@ -2871,6 +2911,8 @@ void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
M.x86.R_AX = fetch_data_word(M.x86.R_SI);
}
M.x86.R_SI += inc;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -2894,26 +2936,36 @@ void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
inc = 1;
if (M.x86.mode & SYSMODE_PREFIX_REPE) {
/* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
cmp_byte(M.x86.R_AL, val2);
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_DI += inc;
if (ACCESS_FLAG(F_ZF) == 0)
break;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~SYSMODE_PREFIX_REPE;
} else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
/* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
cmp_byte(M.x86.R_AL, val2);
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_DI += inc;
if (ACCESS_FLAG(F_ZF))
break; /* zero flag set means equal */
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
} else {
@@ -2951,8 +3003,8 @@ void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
TRACE_AND_STEP();
if (M.x86.mode & SYSMODE_PREFIX_REPE) {
/* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
if (M.x86.mode & SYSMODE_PREFIX_DATA) {
val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
cmp_long(M.x86.R_EAX, val);
@@ -2960,16 +3012,21 @@ void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
cmp_word(M.x86.R_AX, (u16)val);
}
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_DI += inc;
if (ACCESS_FLAG(F_ZF) == 0)
break;
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~SYSMODE_PREFIX_REPE;
} else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
/* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
+ /* move them until (E)CX is ZERO. */
+ while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
if (M.x86.mode & SYSMODE_PREFIX_DATA) {
val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
cmp_long(M.x86.R_EAX, val);
@@ -2977,10 +3034,15 @@ void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
cmp_word(M.x86.R_AX, (u16)val);
}
- M.x86.R_CX -= 1;
+ if (M.x86.mode & SYSMODE_32BIT_REP)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
M.x86.R_DI += inc;
if (ACCESS_FLAG(F_ZF))
break; /* zero flag set means equal */
+ if (M.x86.intr & INTR_HALTED)
+ break;
}
M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
} else {
@@ -3238,9 +3300,9 @@ void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
DECODE_PRINTF("RET\t");
imm = fetch_word_imm();
DECODE_PRINTF2("%x\n", imm);
- RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
TRACE_AND_STEP();
M.x86.R_IP = pop_word();
+ RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
M.x86.R_SP += imm;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -3254,9 +3316,9 @@ void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
{
START_OF_INSTR();
DECODE_PRINTF("RET\n");
- RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
TRACE_AND_STEP();
M.x86.R_IP = pop_word();
+ RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -3471,10 +3533,10 @@ void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
DECODE_PRINTF("RETF\t");
imm = fetch_word_imm();
DECODE_PRINTF2("%x\n", imm);
- RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
TRACE_AND_STEP();
M.x86.R_IP = pop_word();
M.x86.R_CS = pop_word();
+ RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
M.x86.R_SP += imm;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -3488,10 +3550,10 @@ void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
{
START_OF_INSTR();
DECODE_PRINTF("RETF\n");
- RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
TRACE_AND_STEP();
M.x86.R_IP = pop_word();
M.x86.R_CS = pop_word();
+ RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -4020,8 +4082,11 @@ void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
ip += (s16) M.x86.R_IP;
DECODE_PRINTF2("%04x\n", ip);
TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
+ if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && !ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and !ZF */
M.x86.R_IP = ip;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -4041,8 +4106,11 @@ void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
ip += (s16) M.x86.R_IP;
DECODE_PRINTF2("%04x\n", ip);
TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
+ if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and ZF */
M.x86.R_IP = ip;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -4062,8 +4130,11 @@ void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
ip += (s16) M.x86.R_IP;
DECODE_PRINTF2("%04x\n", ip);
TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0)
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+ M.x86.R_ECX -= 1;
+ else
+ M.x86.R_CX -= 1;
+ if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0) /* (E)CX != 0 */
M.x86.R_IP = ip;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
@@ -4085,8 +4156,10 @@ void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
target = (u16)(M.x86.R_IP + offset);
DECODE_PRINTF2("%x\n", target);
TRACE_AND_STEP();
- if (M.x86.R_CX == 0)
+ if (M.x86.R_CX == 0) {
M.x86.R_IP = target;
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " CXZ ");
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -4213,6 +4286,7 @@ void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
ip = (s16)fetch_word_imm();
ip += (s16)M.x86.R_IP;
DECODE_PRINTF2("%04x\n", ip);
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
TRACE_AND_STEP();
M.x86.R_IP = (u16)ip;
DECODE_CLEAR_SEGOVR();
@@ -4233,6 +4307,7 @@ void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
cs = fetch_word_imm();
DECODE_PRINTF2("%04x:", cs);
DECODE_PRINTF2("%04x\n", ip);
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, cs, ip, " FAR ");
TRACE_AND_STEP();
M.x86.R_IP = ip;
M.x86.R_CS = cs;
@@ -4254,6 +4329,7 @@ void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
offset = (s8)fetch_byte_imm();
target = (u16)(M.x86.R_IP + offset);
DECODE_PRINTF2("%x\n", target);
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, target, " BYTE ");
TRACE_AND_STEP();
M.x86.R_IP = target;
DECODE_CLEAR_SEGOVR();
@@ -4357,6 +4433,8 @@ void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
DECODE_PRINTF("REPNE\n");
TRACE_AND_STEP();
M.x86.mode |= SYSMODE_PREFIX_REPNE;
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+ M.x86.mode |= SYSMODE_32BIT_REP;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -4371,6 +4449,8 @@ void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
DECODE_PRINTF("REPE\n");
TRACE_AND_STEP();
M.x86.mode |= SYSMODE_PREFIX_REPE;
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR)
+ M.x86.mode |= SYSMODE_32BIT_REP;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -5013,12 +5093,14 @@ void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
break;
case 4: /* jmp word ptr ... */
destval = fetch_data_word(destoffset);
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, destval, " WORD ");
TRACE_AND_STEP();
M.x86.R_IP = destval;
break;
case 5: /* jmp far ptr ... */
destval = fetch_data_word(destoffset);
destval2 = fetch_data_word(destoffset + 2);
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, destval2, destval, " FAR ");
TRACE_AND_STEP();
M.x86.R_IP = destval;
M.x86.R_CS = destval2;
diff --git a/src/devices/emulator/x86emu/ops2.c b/src/devices/emulator/x86emu/ops2.c
index 448d968570..acefc304c8 100644
--- a/src/devices/emulator/x86emu/ops2.c
+++ b/src/devices/emulator/x86emu/ops2.c
@@ -149,8 +149,10 @@ void x86emuOp2_long_jump(u8 op2)
target += (s16) M.x86.R_IP;
DECODE_PRINTF2("%04x\n", target);
TRACE_AND_STEP();
- if (cond)
+ if (cond) {
M.x86.R_IP = (u16)target;
+ JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " LONG COND ");
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -1485,6 +1487,65 @@ void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
END_OF_INSTR();
}
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xC8-0xCF
+****************************************************************************/
+s32 x86emu_bswap(s32 reg)
+{
+ // perform the byte swap
+ s32 temp = reg;
+ reg = (temp & 0xFF000000) >> 24;
+ reg |= (temp & 0xFF0000) >> 8;
+ reg |= (temp & 0xFF00) << 8;
+ reg |= (temp & 0xFF) << 24;
+ return reg;
+}
+
+void x86emuOp2_bswap(u8 op2)
+{
+ /* byte swap 32 bit register */
+ START_OF_INSTR();
+ DECODE_PRINTF("BSWAP\t");
+ switch (op2) {
+ case 0xc8:
+ DECODE_PRINTF("EAX\n");
+ M.x86.R_EAX = x86emu_bswap(M.x86.R_EAX);
+ break;
+ case 0xc9:
+ DECODE_PRINTF("ECX\n");
+ M.x86.R_ECX = x86emu_bswap(M.x86.R_ECX);
+ break;
+ case 0xca:
+ DECODE_PRINTF("EDX\n");
+ M.x86.R_EDX = x86emu_bswap(M.x86.R_EDX);
+ break;
+ case 0xcb:
+ DECODE_PRINTF("EBX\n");
+ M.x86.R_EBX = x86emu_bswap(M.x86.R_EBX);
+ break;
+ case 0xcc:
+ DECODE_PRINTF("ESP\n");
+ M.x86.R_ESP = x86emu_bswap(M.x86.R_ESP);
+ break;
+ case 0xcd:
+ DECODE_PRINTF("EBP\n");
+ M.x86.R_EBP = x86emu_bswap(M.x86.R_EBP);
+ break;
+ case 0xce:
+ DECODE_PRINTF("ESI\n");
+ M.x86.R_ESI = x86emu_bswap(M.x86.R_ESI);
+ break;
+ case 0xcf:
+ DECODE_PRINTF("EDI\n");
+ M.x86.R_EDI = x86emu_bswap(M.x86.R_EDI);
+ break;
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
/***************************************************************************
* Double byte operation code table:
**************************************************************************/
@@ -1702,14 +1763,14 @@ void (*x86emu_optab2[256])(u8) =
/* 0xc5 */ x86emuOp2_illegal_op,
/* 0xc6 */ x86emuOp2_illegal_op,
/* 0xc7 */ x86emuOp2_illegal_op,
-/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
-/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xc8 */ x86emuOp2_bswap,
+/* 0xc9 */ x86emuOp2_bswap,
+/* 0xca */ x86emuOp2_bswap,
+/* 0xcb */ x86emuOp2_bswap,
+/* 0xcc */ x86emuOp2_bswap,
+/* 0xcd */ x86emuOp2_bswap,
+/* 0xce */ x86emuOp2_bswap,
+/* 0xcf */ x86emuOp2_bswap,
/* 0xd0 */ x86emuOp2_illegal_op,
/* 0xd1 */ x86emuOp2_illegal_op,
diff --git a/src/devices/emulator/x86emu/prim_ops.c b/src/devices/emulator/x86emu/prim_ops.c
index fa19cb4844..a4a46a20ee 100644
--- a/src/devices/emulator/x86emu/prim_ops.c
+++ b/src/devices/emulator/x86emu/prim_ops.c
@@ -1921,7 +1921,7 @@ Implements the IMUL instruction and side effects.
void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
{
#ifdef __HAS_LONG_LONG__
- s64 res = (s64)d * (s64)s;
+ s64 res = (s64)(s32)d * (s64)(s32)s;
*res_lo = (u32)res;
*res_hi = (u32)(res >> 32);
@@ -2013,7 +2013,7 @@ Implements the MUL instruction and side effects.
void mul_long(u32 s)
{
#ifdef __HAS_LONG_LONG__
- u64 res = (u32)M.x86.R_EAX * (u32)s;
+ u64 res = (u64)M.x86.R_EAX * s;
M.x86.R_EAX = (u32)res;
M.x86.R_EDX = (u32)(res >> 32);
@@ -2312,16 +2312,15 @@ void ins(int size)
}
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* in until CX is ZERO. */
- u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ /* in until (E)CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_32BIT_REP) ?
M.x86.R_ECX : M.x86.R_CX);
-
while (count--) {
single_in(size);
M.x86.R_DI += inc;
}
M.x86.R_CX = 0;
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.mode & SYSMODE_32BIT_REP) {
M.x86.R_ECX = 0;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
@@ -2355,15 +2354,15 @@ void outs(int size)
}
if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
/* dont care whether REPE or REPNE */
- /* out until CX is ZERO. */
- u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ /* out until (E)CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_32BIT_REP) ?
M.x86.R_ECX : M.x86.R_CX);
while (count--) {
single_out(size);
M.x86.R_SI += inc;
}
M.x86.R_CX = 0;
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.mode & SYSMODE_32BIT_REP) {
M.x86.R_ECX = 0;
}
M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
diff --git a/src/devices/emulator/x86emu/sys.c b/src/devices/emulator/x86emu/sys.c
index 6ff268674a..6f5a3d29c9 100644
--- a/src/devices/emulator/x86emu/sys.c
+++ b/src/devices/emulator/x86emu/sys.c
@@ -45,7 +45,7 @@
#include <x86emu/regs.h>
#include "debug.h"
#include "prim_ops.h"
-#ifdef COREBOOT_VERSION
+#ifdef COREBOOT_VERSION /* Coreboot needs to map printf to printk. */
#include "arch/io.h"
#else
#include <sys/io.h>
@@ -69,7 +69,7 @@ u8 *mem_ptr(u32 addr, int size)
u8 *retaddr = 0;
if (addr > M.mem_size - size) {
- DB(printk("mem_ptr: address %#lx out of range!\n", addr);)
+ DB(printk("mem_ptr: address %#x out of range!\n", addr);)
HALT_SYS();
}
if (addr < 0x200) {
@@ -405,6 +405,6 @@ void X86EMU_prepareForInt(int num)
void X86EMU_setMemBase(void *base, size_t size)
{
- M.mem_base = (int) base;
+ M.mem_base = (unsigned long) base;
M.mem_size = size;
}
diff --git a/src/include/x86emu/fpu_regs.h b/src/include/x86emu/fpu_regs.h
index 56e9a04d75..67a82d8a05 100644
--- a/src/include/x86emu/fpu_regs.h
+++ b/src/include/x86emu/fpu_regs.h
@@ -39,6 +39,11 @@
#ifndef __X86EMU_FPU_REGS_H
#define __X86EMU_FPU_REGS_H
+
+#if defined(DEBUG) && (DEBUG == 0)
+#undef DEBUG
+#endif
+
#ifdef X86_FPU_SUPPORT
#pragma pack(1)
diff --git a/src/include/x86emu/regs.h b/src/include/x86emu/regs.h
index 718d22fc86..8f89b22c53 100644
--- a/src/include/x86emu/regs.h
+++ b/src/include/x86emu/regs.h
@@ -40,6 +40,10 @@
#ifndef __X86EMU_REGS_H
#define __X86EMU_REGS_H
+#if defined(DEBUG) && (DEBUG == 0)
+#undef DEBUG
+#endif
+
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
@@ -231,6 +235,9 @@ struct i386_segment_regs {
#define SYSMODE_PREFIX_REPNE 0x00000100
#define SYSMODE_PREFIX_DATA 0x00000200
#define SYSMODE_PREFIX_ADDR 0x00000400
+// for REP(E|NE) Instructions, we need to decide wether it should be using
+// the 32bit ECX register as or the 16bit CX register as count register
+#define SYSMODE_32BIT_REP 0x00000800
#define SYSMODE_INTR_PENDING 0x10000000
#define SYSMODE_EXTRN_INTR 0x20000000
#define SYSMODE_HALTED 0x40000000
@@ -250,7 +257,8 @@ struct i386_segment_regs {
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS | \
SYSMODE_PREFIX_DATA | \
- SYSMODE_PREFIX_ADDR)
+ SYSMODE_PREFIX_ADDR | \
+ SYSMODE_32BIT_REP)
#define INTR_SYNCH 0x1
#define INTR_ASYNCH 0x2
@@ -274,9 +282,9 @@ typedef struct {
*/
u32 mode;
volatile int intr; /* mask of pending interrupts */
- int debug;
+ volatile int debug;
#ifdef DEBUG
- int check;
+ int check;
u16 saved_ip;
u16 saved_cs;
int enc_pos;
diff --git a/src/include/x86emu/types.h b/src/include/x86emu/types.h
index c347181100..5bd595e997 100644
--- a/src/include/x86emu/types.h
+++ b/src/include/x86emu/types.h
@@ -74,15 +74,15 @@ typedef unsigned int u32;
typedef unsigned long long u64;
#endif
-typedef char s8;
-typedef short s16;
-typedef int s32;
+typedef signed char s8;
+typedef signed short s16;
+typedef signed int s32;
#ifdef __HAS_LONG_LONG__
-typedef long long s64;
+typedef signed long long s64;
#endif
-typedef unsigned int uint;
-typedef int sint;
+typedef unsigned int uint;
+typedef signed int sint;
typedef u16 X86EMU_pioAddr;
diff --git a/src/include/x86emu/x86emu.h b/src/include/x86emu/x86emu.h
index bd45fea423..e5614ea183 100644
--- a/src/include/x86emu/x86emu.h
+++ b/src/include/x86emu/x86emu.h
@@ -42,6 +42,10 @@
#ifndef __X86EMU_X86EMU_H
#define __X86EMU_X86EMU_H
+#if defined(DEBUG) && (DEBUG == 0)
+#undef DEBUG
+#endif
+
/* FIXME: undefine printk for the moment */
#ifdef COREBOOT_VERSION
#include "console/console.h"
@@ -187,6 +191,8 @@ void X86EMU_halt_sys(void);
#define DEBUG_TRACECALL_REGS_F 0x004000
#define DEBUG_DECODE_NOPRINT_F 0x008000
#define DEBUG_SAVE_IP_CS_F 0x010000
+#define DEBUG_TRACEJMP_F 0x020000
+#define DEBUG_TRACEJMP_REGS_F 0x040000
#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
void X86EMU_trace_regs(void);