diff --git a/bochs/cpu/Makefile.in b/bochs/cpu/Makefile.in index 811a0e510..f65a3b29f 100644 --- a/bochs/cpu/Makefile.in +++ b/bochs/cpu/Makefile.in @@ -50,7 +50,6 @@ EXT_DEBUG_OBJS = @EXT_DEBUG_OBJS@ # are not used for the x86-64 compile because they have not # been synced yet. OBJS32 = \ - exception.o \ ctrl_xfer_pro.o \ flag_ctrl_pro.o \ segment_ctrl_pro.o \ @@ -60,10 +59,7 @@ OBJS32 = \ debugstuff.o \ arith32.o \ mult32.o \ - data_xfer32.o \ stack32.o \ - ctrl_xfer8.o \ - data_xfer16.o \ bit.o \ flag_ctrl.o \ io.o \ @@ -104,6 +100,10 @@ OBJSXX = \ logical32.o \ arith16.o \ segment_ctrl.o \ + ctrl_xfer8.o \ + data_xfer16.o \ + data_xfer32.o \ + exception.o \ # Objects which are only used for x86-64 code, but which have been diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index a39989285..c8f922cbc 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.51 2002-09-13 21:08:54 kevinlawton Exp $ +// $Id: cpu.h,v 1.52 2002-09-14 17:29:47 kevinlawton Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -668,6 +668,9 @@ typedef struct BxInstruction_tag { Bit64u Iq; // for MOV Rx,imm64 unsigned os_64, as_64; // OperandSize/AddressSize is 64bit (overrides os_32/as_32) unsigned extend8bit; +#else + static const unsigned os_64=0, as_64=0; // x86-32: hardcode to 0. + //static const unsigned extend8bit=0; // x86-32: hardcode to 0. #endif unsigned ilen; // instruction length unsigned flags_in, flags_out; // flags needed, flags modified diff --git a/bochs/cpu/ctrl_xfer8.cc b/bochs/cpu/ctrl_xfer8.cc index 50fe50b5d..fbe8975ed 100644 --- a/bochs/cpu/ctrl_xfer8.cc +++ b/bochs/cpu/ctrl_xfer8.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: ctrl_xfer8.cc,v 1.7 2002-09-13 00:15:23 kevinlawton Exp $ +// $Id: ctrl_xfer8.cc,v 1.8 2002-09-14 17:29:47 kevinlawton Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -32,41 +32,61 @@ +#if BX_SUPPORT_X86_64==0 +// Make life a little easier for the 64/32-bit merge. +#define RCX ECX +#define RIP EIP +#endif void BX_CPU_C::JCXZ_Jb(BxInstruction_t *i) { - Bit32u temp_ECX; - if (i->as_32) - temp_ECX = ECX; - else - temp_ECX = CX; - - if ( temp_ECX == 0 ) { - Bit32u new_EIP; - - new_EIP = EIP + (Bit32s) i->Id; - if (i->os_32==0) - new_EIP &= 0x0000ffff; -#if BX_CPU_LEVEL >= 2 - if (protected_mode()) { - if ( new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) { - BX_PANIC(("jcxz_jb: offset outside of CS limits")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (i->as_64) { + if ( RCX == 0 ) { + RIP += (Bit32s) i->Id; + BX_INSTR_CNEAR_BRANCH_TAKEN(new_RIP); + revalidate_prefetch_q(); + } +#if BX_INSTRUMENTATION + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); } #endif - EIP = new_EIP; - BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); - revalidate_prefetch_q(); } -#if BX_INSTRUMENTATION else { - BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); - } + Bit32u temp_ECX; + + if (i->as_32) + temp_ECX = ECX; + else + temp_ECX = CX; + + if ( temp_ECX == 0 ) { + Bit32u new_EIP; + + new_EIP = EIP + (Bit32s) i->Id; + if (i->os_32==0) + new_EIP &= 0x0000ffff; +#if BX_CPU_LEVEL >= 2 + if (protected_mode()) { + if ( new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled ) { + BX_PANIC(("jcxz_jb: offset outside of CS limits")); + exception(BX_GP_EXCEPTION, 0, 0); + } + } #endif + EIP = new_EIP; + BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); + revalidate_prefetch_q(); + } +#if BX_INSTRUMENTATION + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } +#endif + } } @@ -74,119 +94,167 @@ BX_CPU_C::JCXZ_Jb(BxInstruction_t *i) void BX_CPU_C::LOOPNE_Jb(BxInstruction_t *i) { - Bit32u count, new_EIP; + if (i->as_64) { + + if ( ((--RCX)!=0) && (get_ZF()==0) ) { + + RIP += (Bit32s) i->Id; + BX_INSTR_CNEAR_BRANCH_TAKEN(RIP); + revalidate_prefetch_q(); + } +#if BX_INSTRUMENTATION + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } +#endif + } + else { + Bit32u count, new_EIP; #if BX_CPU_LEVEL >= 3 - if (i->as_32) - count = ECX; - else + if (i->as_32) + count = ECX; + else #endif /* BX_CPU_LEVEL >= 3 */ - count = CX; + count = CX; - count--; - if ( (count!=0) && (get_ZF()==0) ) { + count--; + if ( (count!=0) && (get_ZF()==0) ) { - new_EIP = EIP + (Bit32s) i->Id; - if (i->os_32==0) - new_EIP &= 0x0000ffff; - if (protected_mode()) { - if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { - BX_PANIC(("loopne_jb: offset outside of CS limits")); - exception(BX_GP_EXCEPTION, 0, 0); + new_EIP = EIP + (Bit32s) i->Id; + if (i->os_32==0) + new_EIP &= 0x0000ffff; + if (protected_mode()) { + if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { + BX_PANIC(("loopne_jb: offset outside of CS limits")); + exception(BX_GP_EXCEPTION, 0, 0); + } } + EIP = new_EIP; + BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); + revalidate_prefetch_q(); } - EIP = new_EIP; - BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); - revalidate_prefetch_q(); - } #if BX_INSTRUMENTATION - else { - BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); - } + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } #endif - if (i->as_32) - ECX--; - else - CX--; + if (i->as_32) + RCX = ECX - 1; // zero extend + else + CX--; + } } void BX_CPU_C::LOOPE_Jb(BxInstruction_t *i) { - Bit32u count, new_EIP; + if (i->as_64) { + + if ( ((--RCX)!=0) && (get_ZF()) ) { + + RIP += (Bit32s) i->Id; + BX_INSTR_CNEAR_BRANCH_TAKEN(RIP); + revalidate_prefetch_q(); + } +#if BX_INSTRUMENTATION + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } +#endif + } + else { + Bit32u count, new_EIP; #if BX_CPU_LEVEL >= 3 - if (i->as_32) - count = ECX; - else + if (i->as_32) + count = ECX; + else #endif /* BX_CPU_LEVEL >= 3 */ - count = CX; + count = CX; - count--; - if ( (count!=0) && get_ZF()) { + count--; + if ( (count!=0) && get_ZF()) { - new_EIP = EIP + (Bit32s) i->Id; - if (i->os_32==0) - new_EIP &= 0x0000ffff; - if (protected_mode()) { - if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { - BX_PANIC(("loope_jb: offset outside of CS limits")); - exception(BX_GP_EXCEPTION, 0, 0); + new_EIP = EIP + (Bit32s) i->Id; + if (i->os_32==0) + new_EIP &= 0x0000ffff; + if (protected_mode()) { + if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { + BX_PANIC(("loope_jb: offset outside of CS limits")); + exception(BX_GP_EXCEPTION, 0, 0); + } } + EIP = new_EIP; + BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); + revalidate_prefetch_q(); } - EIP = new_EIP; - BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); - revalidate_prefetch_q(); - } #if BX_INSTRUMENTATION - else { - BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); - } + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } #endif - if (i->as_32) - ECX--; - else - CX--; + if (i->as_32) + RCX = ECX - 1; // zero extend + else + CX--; + } } void BX_CPU_C::LOOP_Jb(BxInstruction_t *i) { - Bit32u count, new_EIP; + if (i->as_64) { + + if ( ((--RCX)!=0) ) { + + RIP += (Bit32s) i->Id; + BX_INSTR_CNEAR_BRANCH_TAKEN(RIP); + revalidate_prefetch_q(); + } +#if BX_INSTRUMENTATION + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } +#endif + } + else { + Bit32u count, new_EIP; #if BX_CPU_LEVEL >= 3 - if (i->as_32) - count = ECX; - else + if (i->as_32) + count = ECX; + else #endif /* BX_CPU_LEVEL >= 3 */ - count = CX; + count = CX; - count--; - if (count != 0) { + count--; + if (count != 0) { - new_EIP = EIP + (Bit32s) i->Id; - if (i->os_32==0) - new_EIP &= 0x0000ffff; - if (protected_mode()) { - if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { - BX_PANIC(("loop_jb: offset outside of CS limits")); - exception(BX_GP_EXCEPTION, 0, 0); + new_EIP = EIP + (Bit32s) i->Id; + if (i->os_32==0) + new_EIP &= 0x0000ffff; + if (protected_mode()) { + if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { + BX_PANIC(("loop_jb: offset outside of CS limits")); + exception(BX_GP_EXCEPTION, 0, 0); + } } + EIP = new_EIP; + BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); + revalidate_prefetch_q(); } - EIP = new_EIP; - BX_INSTR_CNEAR_BRANCH_TAKEN(new_EIP); - revalidate_prefetch_q(); - } #if BX_INSTRUMENTATION - else { - BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); - } + else { + BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(); + } #endif - if (i->as_32) - ECX--; - else - CX--; + if (i->as_32) + RCX = ECX - 1; // zero extend + else + CX--; + } } diff --git a/bochs/cpu/data_xfer16.cc b/bochs/cpu/data_xfer16.cc index cbcb1d43f..4c86a2c1e 100644 --- a/bochs/cpu/data_xfer16.cc +++ b/bochs/cpu/data_xfer16.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: data_xfer16.cc,v 1.8 2002-09-06 21:54:57 kevinlawton Exp $ +// $Id: data_xfer16.cc,v 1.9 2002-09-14 17:29:47 kevinlawton Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -37,7 +37,11 @@ void BX_CPU_C::MOV_RXIw(BxInstruction_t *i) { +#if BX_SUPPORT_X86_64 + BX_CPU_THIS_PTR gen_reg[i->nnn].word.rx = i->Iw; +#else BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].word.rx = i->Iw; +#endif } void @@ -46,8 +50,13 @@ BX_CPU_C::XCHG_RXAX(BxInstruction_t *i) Bit16u temp16; temp16 = AX; +#if BX_SUPPORT_X86_64 + AX = BX_CPU_THIS_PTR gen_reg[i->nnn].word.rx; + BX_CPU_THIS_PTR gen_reg[i->nnn].word.rx = temp16; +#else AX = BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].word.rx; BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].word.rx = temp16; +#endif } @@ -100,7 +109,7 @@ BX_CPU_C::MOV_EwSw(BxInstruction_t *i) if (i->mod == 0xc0) { // ??? BX_WRITE_16BIT_REG(mem_addr, seg_reg); if ( i->os_32 ) { - BX_WRITE_32BIT_REG(i->rm, seg_reg); + BX_WRITE_32BIT_REGZ(i->rm, seg_reg); } else { BX_WRITE_16BIT_REG(i->rm, seg_reg); @@ -157,17 +166,17 @@ BX_CPU_C::LEA_GwM(BxInstruction_t *i) BX_CPU_C::MOV_AXOw(BxInstruction_t *i) { Bit16u temp_16; - Bit32u addr_32; + bx_address addr; - addr_32 = i->Id; + addr = i->Id; /* read from memory address */ if (!BX_NULL_SEG_REG(i->seg)) { - read_virtual_word(i->seg, addr_32, &temp_16); + read_virtual_word(i->seg, addr, &temp_16); } else { - read_virtual_word(BX_SEG_REG_DS, addr_32, &temp_16); + read_virtual_word(BX_SEG_REG_DS, addr, &temp_16); } /* write to register */ @@ -179,19 +188,19 @@ BX_CPU_C::MOV_AXOw(BxInstruction_t *i) BX_CPU_C::MOV_OwAX(BxInstruction_t *i) { Bit16u temp_16; - Bit32u addr_32; + bx_address addr; - addr_32 = i->Id; + addr = i->Id; /* read from register */ temp_16 = AX; /* write to memory address */ if (!BX_NULL_SEG_REG(i->seg)) { - write_virtual_word(i->seg, addr_32, &temp_16); + write_virtual_word(i->seg, addr, &temp_16); } else { - write_virtual_word(BX_SEG_REG_DS, addr_32, &temp_16); + write_virtual_word(BX_SEG_REG_DS, addr, &temp_16); } } @@ -223,7 +232,7 @@ BX_CPU_C::MOVZX_GwEb(BxInstruction_t *i) Bit8u op2_8; if (i->mod == 0xc0) { - op2_8 = BX_READ_8BIT_REG(i->rm); + op2_8 = BX_READ_8BIT_REGx(i->rm,i->extend8bit); } else { /* pointer, segment address pair */ @@ -265,7 +274,7 @@ BX_CPU_C::MOVSX_GwEb(BxInstruction_t *i) Bit8u op2_8; if (i->mod == 0xc0) { - op2_8 = BX_READ_8BIT_REG(i->rm); + op2_8 = BX_READ_8BIT_REGx(i->rm,i->extend8bit); } else { /* pointer, segment address pair */ diff --git a/bochs/cpu/data_xfer32.cc b/bochs/cpu/data_xfer32.cc index 4ccde6196..44d9b887c 100644 --- a/bochs/cpu/data_xfer32.cc +++ b/bochs/cpu/data_xfer32.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: data_xfer32.cc,v 1.9 2002-09-13 00:15:23 kevinlawton Exp $ +// $Id: data_xfer32.cc,v 1.10 2002-09-14 17:29:47 kevinlawton Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -41,14 +41,23 @@ BX_CPU_C::XCHG_ERXEAX(BxInstruction_t *i) Bit32u temp32; temp32 = EAX; +#if BX_SUPPORT_X86_64 + RAX = BX_CPU_THIS_PTR gen_reg[i->nnn].dword.erx; + BX_CPU_THIS_PTR gen_reg[i->nnn].dword.erx = temp32; +#else EAX = BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].dword.erx; BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].dword.erx = temp32; +#endif } void BX_CPU_C::MOV_ERXId(BxInstruction_t *i) { +#if BX_SUPPORT_X86_64 + BX_CPU_THIS_PTR gen_reg[i->nnn].rrx = i->Id; +#else BX_CPU_THIS_PTR gen_reg[i->b1 & 0x07].dword.erx = i->Id; +#endif } void @@ -62,7 +71,7 @@ BX_CPU_C::MOV_EdGd(BxInstruction_t *i) /* op1_32 is a register or memory reference */ /* now write op2 to op1 */ if (i->mod == 0xc0) { - BX_WRITE_32BIT_REG(i->rm, op2_32); + BX_WRITE_32BIT_REGZ(i->rm, op2_32); } else { write_virtual_dword(i->seg, i->rm_addr, &op2_32); @@ -83,7 +92,7 @@ BX_CPU_C::MOV_GdEd(BxInstruction_t *i) read_virtual_dword(i->seg, i->rm_addr, &op2_32); } - BX_WRITE_32BIT_REG(i->nnn, op2_32); + BX_WRITE_32BIT_REGZ(i->nnn, op2_32); } @@ -97,7 +106,7 @@ BX_CPU_C::LEA_GdM(BxInstruction_t *i) } /* write effective address of op2 in op1 */ - BX_WRITE_32BIT_REG(i->nnn, i->rm_addr); + BX_WRITE_32BIT_REGZ(i->nnn, i->rm_addr); } @@ -105,21 +114,25 @@ BX_CPU_C::LEA_GdM(BxInstruction_t *i) BX_CPU_C::MOV_EAXOd(BxInstruction_t *i) { Bit32u temp_32; - Bit32u addr_32; + bx_address addr; - addr_32 = i->Id; + addr = i->Id; /* read from memory address */ if (!BX_NULL_SEG_REG(i->seg)) { - read_virtual_dword(i->seg, addr_32, &temp_32); + read_virtual_dword(i->seg, addr, &temp_32); } else { - read_virtual_dword(BX_SEG_REG_DS, addr_32, &temp_32); + read_virtual_dword(BX_SEG_REG_DS, addr, &temp_32); } /* write to register */ +#if BX_SUPPORT_X86_64 + RAX = temp_32; +#else EAX = temp_32; +#endif } @@ -127,19 +140,19 @@ BX_CPU_C::MOV_EAXOd(BxInstruction_t *i) BX_CPU_C::MOV_OdEAX(BxInstruction_t *i) { Bit32u temp_32; - Bit32u addr_32; + bx_address addr; - addr_32 = i->Id; + addr = i->Id; /* read from register */ temp_32 = EAX; /* write to memory address */ if (!BX_NULL_SEG_REG(i->seg)) { - write_virtual_dword(i->seg, addr_32, &temp_32); + write_virtual_dword(i->seg, addr, &temp_32); } else { - write_virtual_dword(BX_SEG_REG_DS, addr_32, &temp_32); + write_virtual_dword(BX_SEG_REG_DS, addr, &temp_32); } } @@ -154,7 +167,7 @@ BX_CPU_C::MOV_EdId(BxInstruction_t *i) /* now write sum back to destination */ if (i->mod == 0xc0) { - BX_WRITE_32BIT_REG(i->rm, op2_32); + BX_WRITE_32BIT_REGZ(i->rm, op2_32); } else { write_virtual_dword(i->seg, i->rm_addr, &op2_32); @@ -171,7 +184,7 @@ BX_CPU_C::MOVZX_GdEb(BxInstruction_t *i) Bit8u op2_8; if (i->mod == 0xc0) { - op2_8 = BX_READ_8BIT_REG(i->rm); + op2_8 = BX_READ_8BIT_REGx(i->rm,i->extend8bit); } else { /* pointer, segment address pair */ @@ -179,7 +192,7 @@ BX_CPU_C::MOVZX_GdEb(BxInstruction_t *i) } /* zero extend byte op2 into dword op1 */ - BX_WRITE_32BIT_REG(i->nnn, (Bit32u) op2_8); + BX_WRITE_32BIT_REGZ(i->nnn, (Bit32u) op2_8); #endif /* BX_CPU_LEVEL < 3 */ } @@ -200,7 +213,7 @@ BX_CPU_C::MOVZX_GdEw(BxInstruction_t *i) } /* zero extend word op2 into dword op1 */ - BX_WRITE_32BIT_REG(i->nnn, (Bit32u) op2_16); + BX_WRITE_32BIT_REGZ(i->nnn, (Bit32u) op2_16); #endif /* BX_CPU_LEVEL < 3 */ } @@ -213,7 +226,7 @@ BX_CPU_C::MOVSX_GdEb(BxInstruction_t *i) Bit8u op2_8; if (i->mod == 0xc0) { - op2_8 = BX_READ_8BIT_REG(i->rm); + op2_8 = BX_READ_8BIT_REGx(i->rm,i->extend8bit); } else { /* pointer, segment address pair */ @@ -221,7 +234,7 @@ BX_CPU_C::MOVSX_GdEb(BxInstruction_t *i) } /* sign extend byte op2 into dword op1 */ - BX_WRITE_32BIT_REG(i->nnn, (Bit8s) op2_8); + BX_WRITE_32BIT_REGZ(i->nnn, (Bit8s) op2_8); #endif /* BX_CPU_LEVEL < 3 */ } @@ -242,7 +255,7 @@ BX_CPU_C::MOVSX_GdEw(BxInstruction_t *i) } /* sign extend word op2 into dword op1 */ - BX_WRITE_32BIT_REG(i->nnn, (Bit16s) op2_16); + BX_WRITE_32BIT_REGZ(i->nnn, (Bit16s) op2_16); #endif /* BX_CPU_LEVEL < 3 */ } @@ -258,7 +271,7 @@ BX_CPU_C::XCHG_EdGd(BxInstruction_t *i) /* op1_32 is a register or memory reference */ if (i->mod == 0xc0) { op1_32 = BX_READ_32BIT_REG(i->rm); - BX_WRITE_32BIT_REG(i->rm, op2_32); + BX_WRITE_32BIT_REGZ(i->rm, op2_32); } else { /* pointer, segment address pair */ @@ -266,7 +279,7 @@ BX_CPU_C::XCHG_EdGd(BxInstruction_t *i) Write_RMW_virtual_dword(op2_32); } - BX_WRITE_32BIT_REG(i->nnn, op1_32); + BX_WRITE_32BIT_REGZ(i->nnn, op1_32); } @@ -314,7 +327,7 @@ BX_CPU_C::CMOV_GdEd(BxInstruction_t *i) } if (condition) { - BX_WRITE_32BIT_REG(i->nnn, op2_32); + BX_WRITE_32BIT_REGZ(i->nnn, op2_32); } #else BX_INFO(("cmov_gded called")); diff --git a/bochs/cpu/exception.cc b/bochs/cpu/exception.cc index 52ccb3ea5..7460894bf 100644 --- a/bochs/cpu/exception.cc +++ b/bochs/cpu/exception.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: exception.cc,v 1.15 2002-09-13 00:15:23 kevinlawton Exp $ +// $Id: exception.cc,v 1.16 2002-09-14 17:29:47 kevinlawton Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -30,7 +30,9 @@ #include "bochs.h" #define LOG_THIS BX_CPU_THIS_PTR - +#if BX_EXTERNAL_DEBUGGER +#include "cpu/extdb.h" +#endif /* Exception classes. These are used as indexes into the 'is_exception_OK' @@ -90,6 +92,238 @@ BX_CPU_THIS_PTR save_esp = ESP; // prev_errno = BX_CPU_THIS_PTR errorno; +#if BX_SUPPORT_X86_64 + if (BX_CPU_THIS_PTR msr.lma) { + // long mode interrupt + + Bit64u idtindex; + Bit32u save_upper; + Bit32u dword1, dword2, dword3; + + bx_descriptor_t gate_descriptor, cs_descriptor; + bx_selector_t cs_selector; + + Bit16u gate_dest_selector; + Bit64u gate_dest_offset; + + // interrupt vector must be within IDT table limits, + // else #GP(vector number*16 + 2 + EXT) + idtindex = vector*16; + if ( (idtindex + 15) > BX_CPU_THIS_PTR idtr.limit) { + BX_DEBUG(("IDT.limit = %04x", (unsigned) BX_CPU_THIS_PTR idtr.limit)); + BX_DEBUG(("IDT.base = %06x", (unsigned) BX_CPU_THIS_PTR idtr.base)); + BX_DEBUG(("interrupt vector must be within IDT table limits")); + BX_DEBUG(("bailing")); + BX_DEBUG(("interrupt(): vector > idtr.limit")); + + exception(BX_GP_EXCEPTION, vector*16 + 2, 0); + } + // descriptor AR byte must indicate interrupt gate, trap gate, + // or task gate, else #GP(vector*8 + 2 + EXT) + + idtindex += BX_CPU_THIS_PTR idtr.base; + + access_linear(idtindex, 4, 0, + BX_READ, &dword1); + access_linear(idtindex + 4, 4, 0, + BX_READ, &dword2); + access_linear(idtindex + 8, 4, 0, + BX_READ, &dword3); + + parse_descriptor(dword1, dword2, &gate_descriptor); + + if ( (gate_descriptor.valid==0) || gate_descriptor.segment) { + BX_DEBUG(("interrupt(): gate descriptor is not valid sys seg")); + exception(BX_GP_EXCEPTION, vector*8 + 2, 0); + } + switch (gate_descriptor.type) { + //case 5: // task gate + //case 6: // 286 interrupt gate + //case 7: // 286 trap gate + case 14: // 386 interrupt gate + case 15: // 386 trap gate + break; + default: + BX_DEBUG(("interrupt(): gate.type(%u) != {5,6,7,14,15}", + (unsigned) gate_descriptor.type)); + exception(BX_GP_EXCEPTION, vector*8 + 2, 0); + return; + } + + // if software interrupt, then gate descripor DPL must be >= CPL, + // else #GP(vector * 8 + 2 + EXT) + if (is_INT && (gate_descriptor.dpl < CPL)) { +/* ??? */ + BX_DEBUG(("interrupt(): is_INT && (dpl < CPL)")); + exception(BX_GP_EXCEPTION, vector*8 + 2, 0); + return; + } + + // Gate must be present, else #NP(vector * 8 + 2 + EXT) + if (gate_descriptor.p == 0) { + BX_DEBUG(("interrupt(): p == 0")); + exception(BX_NP_EXCEPTION, vector*8 + 2, 0); + } + gate_dest_selector = gate_descriptor.u.gate386.dest_selector; + gate_dest_offset = ((Bit64u)dword3 << 32) + + gate_descriptor.u.gate386.dest_offset; + + // examine CS selector and descriptor given in gate descriptor + // selector must be non-null else #GP(EXT) + if ( (gate_dest_selector & 0xfffc) == 0 ) { + BX_PANIC(("int_trap_gate(): selector null")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + parse_selector(gate_dest_selector, &cs_selector); + + // selector must be within its descriptor table limits + // else #GP(selector+EXT) + fetch_raw_descriptor(&cs_selector, &dword1, &dword2, + BX_GP_EXCEPTION); + parse_descriptor(dword1, dword2, &cs_descriptor); + + // descriptor AR byte must indicate code seg + // and code segment descriptor DPL<=CPL, else #GP(selector+EXT) + if ( cs_descriptor.valid==0 || + cs_descriptor.segment==0 || + cs_descriptor.u.segment.executable==0 || + cs_descriptor.dpl>CPL + ) { + BX_DEBUG(("interrupt(): not code segment")); + exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc, 0); + } + // check that it's a 64 bit segment + if ( cs_descriptor.u.segment.l == 0 || + cs_descriptor.u.segment.d_b == 1) { + BX_DEBUG(("interrupt(): must be 64 bit segment")); + exception(BX_GP_EXCEPTION, vector, 0); + } + + // segment must be present, else #NP(selector + EXT) + if ( cs_descriptor.p==0 ) { + BX_DEBUG(("interrupt(): segment not present")); + exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc, 0); + } + + // if code segment is non-conforming and DPL < CPL then + // INTERRUPT TO INNER PRIVILEGE: + if ( cs_descriptor.u.segment.c_ed==0 && cs_descriptor.dpl>32),(Bit32u)(BX_CPU_THIS_PTR prev_eip))); +#if BX_EXTERNAL_DEBUGGER +// trap_debugger(1); +#endif + BX_INSTR_EXCEPTION(vector); invalidate_prefetch_q();