From 5833f7c0e69df069aec918ba9f34b4a0fe0019f5 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Tue, 20 Jan 2009 21:36:39 +0000 Subject: 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 Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3880 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/devices/emulator/x86emu/debug.c | 10 +- src/devices/emulator/x86emu/debug.h | 20 +++- src/devices/emulator/x86emu/ops.c | 172 ++++++++++++++++++++++++--------- src/devices/emulator/x86emu/ops2.c | 79 +++++++++++++-- src/devices/emulator/x86emu/prim_ops.c | 17 ++-- src/devices/emulator/x86emu/sys.c | 6 +- src/include/x86emu/fpu_regs.h | 5 + src/include/x86emu/regs.h | 14 ++- src/include/x86emu/types.h | 12 +-- src/include/x86emu/x86emu.h | 6 ++ 10 files changed, 260 insertions(+), 81 deletions(-) (limited to 'src') 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 #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 @@ -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); -- cgit v1.2.3