message("* vm/common_vm")
-SET(THIS_LIB_VERSION 2.9.1)
+SET(THIS_LIB_VERSION 2.10.1)
#include(cotire)
set(s_vm_common_vm_srcs
// NOTE: the virtual bus interface functions for 16/32bit access invite the cpu is little endian.
// if the cpu is big endian, you need to implement them in the virtual machine memory/io classes.
+ virtual uint32_t translate_address(int segment, uint32_t offset) { /* offset must be numeric, not value */ return offset; }
// memory bus
virtual void write_data8(uint32_t addr, uint32_t data) {}
return cpustate->pc;
}
+uint32_t I286::translate_address(int segment, uint32_t offset)
+{
+ i386_state *cpustate = (i386_state *)opaque;
+ return cpustate->base[segment] + offset;
+}
+
#ifdef USE_DEBUGGER
void I286::write_debug_data8(uint32_t addr, uint32_t data)
{
int get_extra_clock();
uint32_t get_pc();
uint32_t get_next_pc();
+ uint32_t translate_address(int segment, uint32_t offset);
+
+
#ifdef USE_DEBUGGER
bool is_cpu()
{
sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
- if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
+if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
d_mem->write_data8w(addr, data, &wait);
}
+uint32_t I386::translate_address(int segment, uint32_t offset)
+{
+ i386_state *cpustate = (i386_state *)opaque;
+ return i386_translate(cpustate, segment, offset, -1, 1);
+}
+
uint32_t I386::read_debug_data8(uint32_t addr)
{
int wait;
if(cpustate->operand_size) {
my_stprintf_s(buffer, buffer_len,
- _T("MODE=%s PC=%08X PREV_PC=%08X\n")
+ _T("MODE=%s PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
_T("CR[0-4]=%08X %08X %08X %08X %08X IOPL=%d CPL=%d\n")
_T("EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESP=%08X EBP=%08X ESI=%08X EDI=%08X\n")
_T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X\n")
_T("A20_MASK=%08X EIP=%08X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
_T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
(PROTECTED_MODE != 0) ? ((V8086_MODE) ? _T("PROTECTED V8086(32bit)") : _T("PROTECTED 32bit")) : ((V8086_MODE) ? _T("V8086(32bit)") : _T("32bit")),
- cpustate->pc, cpustate->prev_pc,
+ cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
REG32(EAX), REG32(EBX), REG32(ECX), REG32(EDX), REG32(ESP), REG32(EBP), REG32(ESI), REG32(EDI),
cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
if((PROTECTED_MODE) != 0) {
if((V8086_MODE)) {
my_stprintf_s(buffer, buffer_len,
- _T("MODE=V8086 (PROTECTED) PC=%08X PREV_PC=%08X\n")
+ _T("MODE=V8086 (PROTECTED) PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
_T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
_T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
_T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
_T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
- cpustate->pc, cpustate->prev_pc,
+ cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP) & 0xffff),
cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip,
get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
} else {
my_stprintf_s(buffer, buffer_len,
- _T("MODE=PROTECTED 16bit PC=%08X PREV_PC=%08X\n")
+ _T("MODE=PROTECTED 16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
_T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
_T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
_T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
_T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
- cpustate->pc, cpustate->prev_pc,
+ cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
}
} else {
my_stprintf_s(buffer, buffer_len,
- _T("MODE=16bit PC=%08X PREV_PC=%08X\n")
+ _T("MODE=16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
_T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
_T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
_T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
_T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
- cpustate->pc, cpustate->prev_pc,
+ cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG16(SP) & 0xffff),
cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
int get_extra_clock();
uint32_t get_pc();
uint32_t get_next_pc();
+
+ uint32_t translate_address(int segment, uint32_t offset);
//#ifdef USE_DEBUGGER
bool is_cpu()
{
return cpustate->pc;
}
+uint32_t I286::translate_address(int segment, uint32_t offset)
+{
+ i386_state *cpustate = (i386_state *)opaque;
+ return cpustate->base[segment] + offset;
+}
+
#ifdef USE_DEBUGGER
void I286::write_debug_data8(uint32_t addr, uint32_t data)
{
int get_extra_clock();
uint32_t get_pc();
uint32_t get_next_pc();
+ uint32_t translate_address(int segment, uint32_t offset);
#ifdef USE_DEBUGGER
bool is_cpu()
{
// NOTE: the virtual bus interface functions for 16/32bit access invite the cpu is little endian.
// if the cpu is big endian, you need to implement them in the virtual machine memory/io classes.
-
+ virtual uint32_t translate_address(int segment, uint32_t offset) { /* offset must be numeric, not value */ return offset; }
// memory bus
virtual void write_data8(uint32_t addr, uint32_t data) {}
virtual uint32_t read_data8(uint32_t addr)
cpustate->VIF = (f & 0x80000) ? 1 : 0;
cpustate->VIP = (f & 0x100000) ? 1 : 0;
cpustate->ID = (f & 0x200000) ? 1 : 0;
- if(((cpustate->eflags & 0x3000) != (f & 0x3000)) && ((f & 0x3000) == 0)) logerror("SET IOPL to 0 PC=%08X\n", cpustate->pc);
- if(PROTECTED_MODE) {
- cpustate->eflags = f;
- } else {
- UINT32 o_e = cpustate->eflags & 0x20000;
- cpustate->eflags = (f & ~0x00020000) | o_e;
- //cpustate->eflags = f;
- }
+ //if(((cpustate->eflags & 0x3000) != (f & 0x3000)) && ((f & 0x3000) == 0)) logerror("SET IOPL to 0 PC=%08X\n", cpustate->pc);
+ //if(old_vm != cpustate->VM) logerror("Change VM flag to %d at %08X\n", cpustate->VM, cpustate->pc);
+ //if(PROTECTED_MODE) {
+ cpustate->eflags = f;
+ //} else {
+ // UINT32 o_e = cpustate->eflags & 0x20000;
+ //cpustate->eflags = (f & ~0x00020000) | o_e;
+ //cpustate->eflags = f;
+ //}
#if 0
if(old_vm != cpustate->VM) {
if((V8086_MODE) && (PROTECTED_MODE)){
{
if((selector & ~0x0007) > cpustate->ldtr.limit)
{
- logerror("SReg Load (%08x): Selector is out of LDT bounds.LDTR.limit=%4X : selector=%04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
+ logerror("SReg Load (SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%4X : selector=%04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
FAULT(FAULT_GP,selector & ~0x03)
}
}
{
if((selector & ~0x0007) > cpustate->ldtr.limit)
{
- logerror("SReg Load (%08x): Selector is out of LDT bounds.LDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
+ logerror("SReg Load (other SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
FAULT(FAULT_GP,selector & ~0x03)
}
}
segment = (v1 >> 16) & 0xffff;
type = (v2>>8) & 0x1F;
flags = (v2>>8) & 0xf0ff;
-
+ //logdebug("TRAP: #%d PC=%08X offset = %08X segment = %04X type = %d flags = %04X\n", irq, cpustate->pc, offset, segment, type, flags);
if(trap_level == 2)
{
logdebug("IRQ: Double fault. IRQ%02Xh GATE=%d PC=%08X\n", irq, irq_gate, cpustate->pc);
}
/* change CPL before accessing the stack */
UINT32 _oldCPL = cpustate->CPL;
- if(_oldCPL != DPL) logerror("TRAP/INT GATE: Privilege changed from %d to %d at %08X, INT# %d, GATE %d TYPE %d\n", _oldCPL, DPL, cpustate->pc, irq, irq_gate, type);
+ //if(_oldCPL != DPL) logerror("TRAP/INT GATE: Privilege changed from %d to %d at %08X, INT# %d, GATE %d TYPE %d\n", _oldCPL, DPL, cpustate->prev_pc, irq, irq_gate, type);
cpustate->CPL = DPL;
/* check for page fault at new stack TODO: check if stack frame crosses page boundary */
WRITE_TEST(cpustate, stack.base+newESP-1);
cpustate->sreg[FS].selector = 0;
cpustate->sreg[DS].selector = 0;
cpustate->sreg[ES].selector = 0;
- //cpustate->VM = 0;
+ cpustate->VM = 0;
//cpustate->eflags = get_flags(cpustate);
cpustate->eflags &= ~I386_EFLAGS_VM; // Clear VM flag
set_flags(cpustate, cpustate->eflags);
try
{
// this is ugly but the alternative is worse
- if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate
+ if(/*type != 0x0e && type != 0x0f*/ (type & 0x08) == 0) // if not 386 interrupt or trap gate
{
PUSH16(cpustate, oldflags & 0xffff );
PUSH16(cpustate, cpustate->sreg[CS].selector );
if(SetRPL != 0)
segment = (segment & ~0x03) | cpustate->CPL;
cpustate->sreg[CS].selector = segment;
- if(segment != o_selector) {
- i386_load_segment_descriptor(cpustate,CS);
- }
+ //if(segment != o_selector) {
+ // i386_load_segment_descriptor(cpustate,CS);
+ //}
cpustate->eip = offset;
if(type == 0x0e || type == 0x06)
i386_trap(cpustate,irq,irq_gate,trap_level);
}
- if(irq == FAULT_DF || irq == FAULT_TS || irq == FAULT_NP || irq == FAULT_SS || irq == FAULT_GP || irq == FAULT_GP || irq == FAULT_AC)
+ if(irq == FAULT_DF || irq == FAULT_TS || irq == FAULT_NP || irq == FAULT_SS || irq == FAULT_GP || irq == FAULT_PF /*|| irq == FAULT_AC */)
{
- if((irq == FAULT_AC) || (irq == FAULT_DF)) error = 0;
+ //if((irq == FAULT_AC) || (irq == FAULT_DF)) error = 0;
// for these exceptions, an error code is pushed onto the stack by the processor.
// no error code is pushed for software interrupts, either.
if(PROTECTED_MODE)
{
-// try {
UINT32 entry = irq * 8;
UINT32 v2,type;
v2 = READ32PL0(cpustate, cpustate->idtr.base + entry + 4 );
PUSH32(cpustate,error);
else
PUSH16(cpustate,error);
-// } catch(UINT64 e) {
-// logerror("Irregular exception happened %08x for protected mode in trap_with_error()_.\n", e);
-// } catch(UINT32 e) {
-// logerror("Irregular exception happened %08x for protected mode in trap_with_error()_.\n", e);
-// }
}
else {
-// try {
PUSH16(cpustate,error);
-// } catch(UINT64 e) {
-// logerror("Irregular exception happened %08x for 16bit mode in trap_with_error()_.\n", e);
-// } catch(UINT32 e) {
-// logerror("Irregular exception happened %08x for 16bit mode in trap_with_error()_.\n", e);
-// }
}
}
}
UINT32 _oldCPL = cpustate->CPL;
cpustate->CPL = (stack.flags >> 5) & 0x03;
UINT32 _newCPL = cpustate->CPL;
- if(_oldCPL != _newCPL) logerror("Privilege changed by protected mode call from %d to %d ADDR %08X\n", _oldCPL, _newCPL, cpustate->pc);
+ //if(_oldCPL != _newCPL) logerror("Privilege changed by protected mode call from %d to %d ADDR %08X\n", _oldCPL, _newCPL, cpustate->pc);
/* check for page fault at new stack */
WRITE_TEST(cpustate, stack.base+newESP-1);
/* switch to new stack */
i386_load_segment_descriptor(cpustate,FS);
i386_load_segment_descriptor(cpustate,GS);
i386_load_segment_descriptor(cpustate,SS);
- logerror("IRET: Return to V8086 MODE: old CPL=%d new CPL=3 PC=%08X\n", cpustate->CPL, cpustate->pc);
+ //logerror("IRET: Return to V8086 MODE: old CPL=%d new CPL=3 PC=%08X\n", cpustate->CPL, cpustate->pc);
cpustate->CPL = 3; // Virtual 8086 tasks are always run at CPL 3
}
else
// From ia32_initreg() of np2, i386c/ia32/interface.c
cpustate->cr[0] = I386_CR0_CD | I386_CR0_NW;
// ToDo: FPU
- //cpustate->cr[0] &= ~I386_CR0_EM;
- //cpustate->cr[0] |= I386_CR0_ET;
- cpustate->cr[0] |= (I386_CR0_EM | I386_CR0_NE);
- cpustate->cr[0] &= ~(I386_CR0_MP | I386_CR0_ET);
+ cpustate->cr[0] &= ~I386_CR0_EM;
+ cpustate->cr[0] |= I386_CR0_ET;
+ //cpustate->cr[0] |= (I386_CR0_EM | I386_CR0_NE);
+ //cpustate->cr[0] &= ~(I386_CR0_MP | I386_CR0_ET);
// Init GDTR/IDTR
cpustate->gdtr.base = 0x0000;
cpustate->gdtr.limit = 0xffff;
CYCLES(cpustate,CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
//#ifdef I386_PSEUDO_BIOS
- //if(!(V8086_MODE)) {
+ UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+ if(!(V8086_MODE) && !(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
BIOS_CALL_FAR(((ptr << 4) + offset) & cpustate->a20_mask);
- //}
+ }
//#endif
if( PROTECTED_MODE && !V8086_MODE)
selector = READ16(cpustate,ea + 2);
CYCLES(cpustate,CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
//#ifdef I386_PSEUDO_BIOS
- //if(!(V8086_MODE)) {
+ UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+ if(!(V8086_MODE) && !((PROTECTED_MODE) && (cpustate->CPL > IOPL))) {
BIOS_CALL_FAR(((selector << 4) + address) & cpustate->a20_mask);
- //}
+ }
//#endif
if(PROTECTED_MODE && !V8086_MODE)
{
// FAULT(FAULT_UD, 0);
// return;
//}
+ UINT32 oldpc = cpustate->pc;
if((PROTECTED_MODE && (/*(V8086_MODE) || */(cpustate->CPL != 0)))) {
logerror("Call from non-supervisor privilege: I386OP(mov_r32_cr)");
FAULT(FAULT_GP, 0);
}
UINT8 modrm = FETCH(cpustate);
UINT8 cr = (modrm >> 3) & 0x7;
- logdebug("MOV r32 CR%d VAL=(%08X)\n", cr, cpustate->cr[cr]);
+ logdebug("MOV r32 CR%d VAL=(%08X)\n", cr, cpustate->cr[cr], oldpc);
if(cr < 5) {
STORE_RM32(modrm, cpustate->cr[cr]);
CYCLES(cpustate,CYCLES_MOV_CR_REG);
// FAULT(FAULT_UD, 0);
// return;
//}
+ UINT32 oldpc = cpustate->pc;
if((PROTECTED_MODE && (/*(V8086_MODE) || */(cpustate->CPL != 0)))) {
logerror("Call from non-supervisor privilege: I386OP(mov_cr_r32)");
FAULT(FAULT_GP, 0);
UINT8 cr = (modrm >> 3) & 0x7;
UINT32 data = LOAD_RM32(modrm);
UINT32 data_bak;
- logdebug("MOV CR%d r32 VAL=(%08X)\n", cr, data);
+ logdebug("MOV CR%d r32 VAL=(%08X) at %08X\n", cr, data, oldpc);
switch(cr)
{
case 0:
if((data & (I386_CR0_NW | I386_CR0_CD)) == I386_CR0_NW) {
FAULT(FAULT_GP, 0);
}
-#if 0
+#if 1
data_bak = cpustate->cr[0];
data &= I386_CR0_ALL;
data &= ~I386_CR0_WP; // wp not supported on 386
//logdebug("MOV CR0,xxxxh %08x -> %08x \n", data_bak, data);
// ToDo: FPU
- //data |= I386_CR0_ET; /* FPU present */
- //data &= ~I386_CR0_EM;
- data |= I386_CR0_EM | I386_CR0_NE;
- data &= ~(I386_CR0_MP | I386_CR0_ET);
- cpustate->cr[0] = data & ~(I386_CR0_PE | I386_CR0_PG);
+ data |= I386_CR0_ET; /* FPU present */
+ data &= ~I386_CR0_EM;
+ //data |= I386_CR0_EM | I386_CR0_NE;
+ //data &= ~(I386_CR0_MP | I386_CR0_ET);
+// //cpustate->cr[0] = data & ~(I386_CR0_PE | I386_CR0_PG);
#endif
cpustate->cr[0] = data;
-#if 0
+#if 1
if((data_bak & (I386_CR0_PE | I386_CR0_PG)) != (data & (I386_CR0_PE | I386_CR0_PG))) {
// ToDo: TLB flush (paging)
vtlb_flush_dynamic(cpustate->vtlb);
if(PROTECTED_MODE && !V8086_MODE)
{
- if( modrm >= 0xc0 ) {
+ if( modrm >= 0xc0 ) {
src = LOAD_REG16(modrm);
dst = LOAD_RM16(modrm);
if( (dst&0x3) < (src&0x3) ) {
static void I386OP(int3)(i386_state *cpustate) // Opcode 0xcc
{
CYCLES(cpustate,CYCLES_INT3);
+ logerror("INT3 at %08X\n", cpustate->pc - 1);
cpustate->ext = 0; // not an external interrupt
i386_trap(cpustate,3, 1, 0);
cpustate->ext = 1;
int interrupt = FETCH(cpustate);
CYCLES(cpustate,CYCLES_INT);
if(V8086_MODE) {
- //logerror("INT %02xh @V8086(16) mode\n", interrupt);
+ //logerror("INT %02xh @V8086(16bit) mode PC=%08X\n", interrupt, cpustate->pc - 1);
if((!cpustate->IOP1 || !cpustate->IOP2))
{
logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
- //FAULT(FAULT_GP,0);
+ FAULT(FAULT_GP,0);
} else {
- BIOS_INT(interrupt);
+ //BIOS_INT(interrupt);
}
} else {
- //logerror("INT %02xh @16bit mode\n", interrupt);
- BIOS_INT(interrupt);
+ //logerror("INT %02xh @16bit mode PC=%08X\n", interrupt, cpustate->pc - 1);
+ UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+ if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
+ BIOS_INT(interrupt);
+ }
}
cpustate->ext = 0; // not an external interrupt
i386_trap(cpustate,interrupt, 1, 0);
CYCLES(cpustate,CYCLES_INT);
#if 1
if(V8086_MODE) {
- //logerror("INT %02xh @V8086(32) mode\n", interrupt);
+ //logerror("INT %02xh @V8086(32bit) mode PC=%08X\n", interrupt, cpustate->pc - 1);
if((!cpustate->IOP1 || !cpustate->IOP2))
{
- //logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
- //FAULT(FAULT_GP,0);
+ logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
+ FAULT(FAULT_GP,0);
} else {
-
- BIOS_INT(interrupt);
+ //BIOS_INT(interrupt);
}
} else {
- //logerror("INT %02xh @32bit mode\n", interrupt);
- BIOS_INT(interrupt);
+ //logerror("INT %02xh @32bit mode PC=%08X\n", interrupt, cpustate->pc - 1);
+ UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+ if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
+ BIOS_INT(interrupt);
+ }
}
#endif
cpustate->ext = 0; // not an external interrupt
#endif
#define PROTECTED_MODE (cpustate->cr[0] & 0x1)
#define STACK_32BIT (cpustate->sreg[SS].d)
-#define V8086_MODE ((cpustate->VM) && (cpustate->cr[4] & I386_CR4_VME))
+#define V8086_MODE ((cpustate->VM) /*&& (cpustate->cr[4] & I386_CR4_VME)*/)
#define NESTED_TASK (cpustate->NT)
#define WP (cpustate->cr[0] & I386_CR0_WP)
// ToDo: Cache flush for i486 or later.
#if defined(SUPPORT_32BIT_ADDRESS)
is_shadow_bank_80000h = ((data & 0xfe) == 0x08) ? true : false;
+#endif
//if(!is_shadow_bank_80000h) {
window_80000h = (data & 0xfe) << 16;
//}
-#else
window_80000h = (data & 0xfe) << 16;
-#endif
break;
#if defined(SUPPORT_HIRESO)
case 0x0093:
}
#endif
// http://www.webtech.co.jp/company/doc/undocumented_mem/io_mem.txt
-#if defined(SUPPORT_32BIT_ADDRESS)
- is_shadow_bank_a0000h = ((data & 0xfe) == 0x0a) ? true : false;
- //if(!is_shadow_bank_a0000h) {
window_a0000h = (data & 0xfe) << 16;
//}
-#else
- window_a0000h = (data & 0xfe) << 16;
-#endif
break;
#endif
case 0x0463:
// #endif
//}
#if defined(SUPPORT_32BIT_ADDRESS)
+ #if !defined(SUPPORT_HIRESO)
+ unset_memory_rw(0xa0000, 0xbffff);
+ set_memory_mapped_io_rw(0xa0000, 0xbffff, d_display);
+ #else
unset_memory_rw(0xc0000, 0xe7fff);
+ #endif
if(shadow_ram_selected) {
set_memory_rw(0xc0000, 0xe7fff, shadow_ram);
} else {
#if defined(SUPPORT_HIRESO)
set_memory_mapped_io_rw(0xe0000, 0xe4fff, d_display);
#else
+ unset_memory_rw(0xc0000, 0xe7fff);
#if defined(SUPPORT_16_COLORS)
set_memory_mapped_io_rw(0xe0000, 0xe7fff, d_display);
#endif
event_irq = -1;
}
-bool BIOS::bios_int_i86(int intnum, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag, int* cycles, uint64_t* total_cycles)
+ bool BIOS::bios_int_i86(int intnum, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag, int* cycles, uint64_t* total_cycles)
{
uint8_t *regs8 = (uint8_t *)regs;
// SASI
switch(intnum) {
case 0x1b: // SASI BIOS (INT3)
if(d_mem->is_sasi_bios_load()) return false;
+ //out_debug_log("INT 1Bh\n");
return bios_call_far_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag, cycles, total_cycles);
break;
default:
return false;
}
-bool BIOS::bios_call_far_i86(uint32_t PC, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag, int* cycles, uint64_t* total_cycles)
+ bool BIOS::bios_call_far_i86(uint32_t PC, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag, int* cycles, uint64_t* total_cycles)
{
uint8_t *regs8 = (uint8_t *)regs;
bool need_retcall = false;
// ToDo: Multi SASI
if(d_sasi->get_hdd(0) != NULL) {
if(sxsi_get_drive(AL) >= 0) {
+ out_debug_log("SASI BIOS CALL AH=%02X\n", AH);
switch(AH & 0x0f) {
case 0x01:
// Verify
}
_d.u16 = disk_equip;
d_mem->write_io8(0x043f, 0xc2); // Enable to write ram
- d_mem->write_data8(0x055c + 0, _d.b.l);
- d_mem->write_data8(0x055c + 1, _d.b.h);
+ d_mem->write_dma_data8(0x055c + 0, _d.b.l);
+ d_mem->write_dma_data8(0x055c + 1, _d.b.h);
d_mem->write_io8(0x043f, 0xc0); // Disable to write ram
#ifdef _PSEUDO_BIOS_DEBUG
out_debug_log(_T("SASI CMD: INITIALIZE STAT=%04x"), disk_equip);
uint8_t *regs8 = (uint8_t *)regs;
int size = (int)(BX & 0xffff);
if(size == 0) size = 0x10000;
- uint32_t addr = (((uint32_t)ES) << 4) + BP;
+ uint32_t addr;
+ //addr = (((uint32_t)ES) << 4) + BP;
+ try {
+ addr = d_cpu->translate_address(0, (uint32_t)BP); // ES:BP
+ } catch(...) {
+ out_debug_log("Access vioration ES:%04x\n", BP);
+ }
//out_debug_log(_T("SASI CMD: READ ADDR=%08x\n"), addr);
int drive = sxsi_get_drive(AL);
if(harddisk->read_buffer((long)position, block_size, buffer)) {
position += block_size;
for(int i = 0; i < block_size; i++) {
- d_mem->write_data8(addr++, buffer[i]);
+ d_mem->write_dma_data8(addr++, buffer[i]);
}
size -= block_size;
} else {
int size = (int)(BX & 0xffff);
if(size == 0) size = 0x10000;
uint8_t *regs8 = (uint8_t *)regs;
- uint32_t addr = (((uint32_t)ES) << 4) + BP;
+ uint32_t addr;
+ try {
+ addr = d_cpu->translate_address(0, (uint32_t)BP); // ES:BP
+ } catch(...) {
+ out_debug_log("Access vioration ES:%04x\n", BP);
+ }
+ //addr = (((uint32_t)ES) << 4) + BP;
int drive = sxsi_get_drive(AL);
if(drive < 0) { // ToDo: Multi SASI
AH = 0x80;
}
// data transfer
for(int i = 0; i < block_size; i++) {
- buffer[i] = d_mem->read_data8(addr++);
+ buffer[i] = d_mem->read_dma_data8(addr++);
}
if(harddisk->write_buffer((long)position, block_size, buffer)) {
position += block_size;
return;
}
HARDDISK* harddisk = d_hdd->get_disk_handler(drive);
-//#ifdef _PSEUDO_BIOS_DEBUG
+#ifdef _PSEUDO_BIOS_DEBUG
out_debug_log(_T("SASI CMD: FORMAT DL=%02x DH=%02x CX=%04x BX=%04x\n"), DL, DH, CX, BX);
-//#endif
+#endif
if(harddisk == NULL) {
AH = 0x60;
*CarryFlag = 1;