#ifdef I386_PSEUDO_BIOS
#define BIOS_INT(num) if(cpustate->bios != NULL) { \
- uint16_t regs[8], sregs[4]; \
+ uint16_t regs[10], sregs[4]; \
regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
+ regs[8] = 0x0000; regs[9] = 0x0000; \
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; \
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; \
+ CYCLES(CYCLES_IRET); \
+ if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
+ uint32_t hi = regs[9]; \
+ uint32_t lo = regs[8]; \
+ uint32_t addr = (hi << 16) | lo; \
+ cpustate->eip = addr; \
+ } \
return; \
} \
}
-#define BIOS_CALL(address) if(cpustate->bios != NULL) { \
- uint16_t regs[8], sregs[4]; \
+
+#define BIOS_CALL_FAR(address) if(cpustate->bios != NULL) { \
+ uint16_t regs[10], sregs[4]; \
regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
+ regs[8] = 0x0000; regs[9] = 0x0000; \
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_call_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
+ if(cpustate->bios->bios_call_far_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
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; \
- return; \
+ CYCLES(CYCLES_RET_INTERSEG); \
+ if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
+ uint32_t hi = regs[9]; \
+ uint32_t lo = regs[8]; \
+ uint32_t addr = (hi << 16) | lo; \
+ cpustate->eip = addr; \
+ } \
+ return; \
} \
}
#endif
{
UINT16 offset = FETCH16();
UINT16 ptr = FETCH16();
+ CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
+
#ifdef I386_PSEUDO_BIOS
- BIOS_CALL(((ptr << 4) + offset) & cpustate->a20_mask)
+ BIOS_CALL_FAR(((ptr << 4) + offset) & cpustate->a20_mask)
#endif
//printf(" \n");
cpustate->eip = offset;
i386_load_segment_descriptor(CS);
}
- CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
CHANGE_PC(cpustate->eip);
}
{
INT16 disp = FETCH16();
-#ifdef I386_PSEUDO_BIOS
- BIOS_CALL((cpustate->pc + disp) & cpustate->a20_mask)
-#endif
-
PUSH16( cpustate->eip );
if (cpustate->sreg[CS].d)
{
STORE_RM16(modrm, dst);
CYCLES(CYCLES_INC_REG);
} else {
- UINT32 ea = GetEA(modrm,1);
+ UINT32 ea = GetEA(modrm,1, 2);
UINT16 dst = READ16(ea);
dst = INC16(dst);
WRITE16(ea, dst);
STORE_RM16(modrm, dst);
CYCLES(CYCLES_DEC_REG);
} else {
- UINT32 ea = GetEA(modrm,1);
+ UINT32 ea = GetEA(modrm,1, 2);
UINT16 dst = READ16(ea);
dst = DEC16(dst);
WRITE16(ea, dst);
address = LOAD_RM16(modrm);
CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
} else {
- UINT32 ea = GetEA(modrm,0);
+ UINT32 ea = GetEA(modrm,0, 2);
address = READ16(ea);
CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
}
-#ifdef I386_PSEUDO_BIOS
- BIOS_CALL(((cpustate->sreg[CS].selector << 4) + address) & cpustate->a20_mask)
-#endif
PUSH16( cpustate->eip );
cpustate->eip = address;
CHANGE_PC(cpustate->eip);
}
else
{
- UINT32 ea = GetEA(modrm,0);
+ UINT32 ea = GetEA(modrm,0, 4);
address = READ16(ea + 0);
selector = READ16(ea + 2);
CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
#ifdef I386_PSEUDO_BIOS
- BIOS_CALL(((selector << 4) + address) & cpustate->a20_mask)
+ BIOS_CALL_FAR(((selector << 4) + address) & cpustate->a20_mask)
#endif
if(PROTECTED_MODE && !V8086_MODE)
{
address = LOAD_RM16(modrm);
CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
} else {
- UINT32 ea = GetEA(modrm,0);
+ UINT32 ea = GetEA(modrm,0, 2);
address = READ16(ea);
CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
}
}
else
{
- UINT32 ea = GetEA(modrm,0);
+ UINT32 ea = GetEA(modrm,0, 4);
address = READ16(ea + 0);
selector = READ16(ea + 2);
CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
if( modrm >= 0xc0 ) {
value = LOAD_RM16(modrm);
} else {
- UINT32 ea = GetEA(modrm,0);
+ UINT32 ea = GetEA(modrm,0, 2);
value = READ16(ea);
}
PUSH16(value);
break;
}
}
+
+void I386_OPS::i386__int() // Opcode 0xcd
+{
+ int interrupt = FETCH();
+ CYCLES(CYCLES_INT);
+
+#ifdef I386_PSEUDO_BIOS
+ BIOS_INT(interrupt)
+#endif
+ cpustate->ext = 0; // not an external interrupt
+ i386_trap(interrupt, 1, 0);
+ cpustate->ext = 1;
+}