(cpu64) Merged 4 more files.

This commit is contained in:
Kevin Lawton 2002-09-14 17:29:47 +00:00
parent 55510b1e17
commit 6d4b3e0e4d
6 changed files with 473 additions and 142 deletions

View File

@ -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

View File

@ -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

View File

@ -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--;
}
}

View File

@ -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 */

View File

@ -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"));

View File

@ -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<CPL ) {
Bit16u old_SS, old_CS;
Bit64u RSP_for_cpl_x, old_RIP, old_RSP;
bx_descriptor_t ss_descriptor;
bx_selector_t ss_selector;
int bytes;
BX_DEBUG(("interrupt(): INTERRUPT TO INNER PRIVILEGE"));
// check selector and descriptor for new stack in current TSS
get_RSP_from_TSS(cs_descriptor.dpl,&RSP_for_cpl_x);
// set up a null descriptor
parse_selector(0,&ss_selector);
parse_descriptor(0,0,&ss_descriptor);
// 386 int/trap gate
// new stack must have room for 40|48 bytes, else #SS(0)
//if ( is_error_code )
// bytes = 48;
//else
// bytes = 40;
old_RSP = RSP;
// load new RSP values from TSS
load_ss_null(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
RSP = RSP_for_cpl_x;
// load new CS:IP values from gate
// set CPL to new code segment DPL
// set RPL of CS to CPL
// push long pointer to old stack onto new stack
// align ESP
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
push_64(old_RSP);
// push EFLAGS
push_64(read_eflags());
// push long pointer to return address onto new stack
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
push_64(RIP);
if ( is_error_code )
push_64(error_code);
load_cs(&cs_selector, &cs_descriptor, cs_descriptor.dpl);
RIP = gate_dest_offset;
// if INTERRUPT GATE set IF to 0
if ( !(gate_descriptor.type & 1) ) // even is int-gate
BX_CPU_THIS_PTR clear_IF ();
BX_CPU_THIS_PTR clear_TF ();
BX_CPU_THIS_PTR clear_VM ();
BX_CPU_THIS_PTR clear_RF ();
BX_CPU_THIS_PTR clear_NT ();
return;
}
// if code segment is conforming OR code segment DPL = CPL then
// INTERRUPT TO SAME PRIVILEGE LEVEL:
if ( cs_descriptor.u.segment.c_ed==1 || cs_descriptor.dpl==CPL ) {
Bit64u old_RSP;
BX_DEBUG(("int_trap_gate286(): INTERRUPT TO SAME PRIVILEGE"));
old_RSP = RSP;
// align stack
RSP = RSP & BX_CONST64(0xfffffffffffffff0);
// push flags onto stack
// push current CS selector onto stack
// push return offset onto stack
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
push_64(old_RSP);
push_64(read_eflags());
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
push_64(RIP);
if ( is_error_code )
push_64(error_code);
// load CS:IP from gate
// load CS descriptor
// set the RPL field of CS to CPL
load_cs(&cs_selector, &cs_descriptor, CPL);
RIP = gate_dest_offset;
// if interrupt gate then set IF to 0
if ( !(gate_descriptor.type & 1) ) // even is int-gate
BX_CPU_THIS_PTR clear_IF ();
BX_CPU_THIS_PTR clear_TF ();
BX_CPU_THIS_PTR clear_VM ();
BX_CPU_THIS_PTR clear_RF ();
BX_CPU_THIS_PTR clear_NT ();
return;
}
// else #GP(CS selector + ext)
BX_DEBUG(("interrupt: bad descriptor"));
BX_DEBUG(("c_ed=%u, descriptor.dpl=%u, CPL=%u",
(unsigned) cs_descriptor.u.segment.c_ed,
(unsigned) cs_descriptor.dpl,
(unsigned) CPL));
BX_DEBUG(("cs.segment = %u", (unsigned) cs_descriptor.segment));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc, 0);
}
else
#endif // #if BX_SUPPORT_X86_64
if(!real_mode()) {
Bit32u dword1, dword2;
bx_descriptor_t gate_descriptor, cs_descriptor;
@ -583,7 +817,11 @@ BX_CPU_C::exception(unsigned vector, Bit16u error_code, Boolean is_INT)
}
#endif
//BX_DEBUG(( "::exception(%u)", vector ));
//BX_DEBUG (("Exception(%u) code=%08x @%08x%08x", vector, error_code,(Bit32u)(BX_CPU_THIS_PTR prev_eip >>32),(Bit32u)(BX_CPU_THIS_PTR prev_eip)));
#if BX_EXTERNAL_DEBUGGER
// trap_debugger(1);
#endif
BX_INSTR_EXCEPTION(vector);
invalidate_prefetch_q();