i286 - enabling 287 emulation by trapping when needed [Carl]

idectrl - Clears error status on driver initialization [Carl]
This commit is contained in:
Miodrag Milanovic 2011-05-29 08:43:52 +00:00
parent 6659e57a43
commit 5aa0cf528a
5 changed files with 65 additions and 35 deletions

View File

@ -212,8 +212,8 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
UINT32 naddr, oaddr, ldtaddr;
int i;
logerror("This program uses TSSs, how rare. Expect a crash.\n");
if (TBL(ntask)) TRAP(INVALID_TSS,IDXTBL(ntask));
if ((naddr = i80286_selector_address(cpustate,ntask)) == -1) TRAP(INVALID_TSS,IDXTBL(ntask));
if (TBL(ntask)) throw TRAP(INVALID_TSS,IDXTBL(ntask));
if ((naddr = i80286_selector_address(cpustate,ntask)) == -1) throw TRAP(INVALID_TSS,IDXTBL(ntask));
oaddr = i80286_selector_address(cpustate,cpustate->tr.sel);
ndesc[0] = ReadWord(naddr);
ndesc[1] = ReadWord(naddr+2);
@ -222,7 +222,7 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
r = RIGHTS(ndesc);
if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(ntask));
if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(ntask));
if (LIMIT(ndesc) < 44) TRAP(INVALID_TSS,IDXTBL(ntask));
if (LIMIT(ndesc) < 44) throw TRAP(INVALID_TSS,IDXTBL(ntask));
for (i = 0; i < 44; i+=2) ntss[i/2] = ReadWord(BASE(ndesc)+i);
cpustate->flags = CompressFlags();
@ -271,23 +271,28 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
cpustate->regs.w[SI] = ntss[TSS_SI];
cpustate->regs.w[DI] = ntss[TSS_DI];
if (TBL(ntss[TSS_LDT])) TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
if ((ldtaddr = i80286_selector_address(cpustate,ntss[TSS_LDT])) == -1) TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
desc[0] = ReadWord(ldtaddr);
desc[1] = ReadWord(ldtaddr+2);
desc[2] = ReadWord(ldtaddr+4);
r = RIGHTS(desc);
if (SEGDESC(r) || (GATE(r) != LDTDESC)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
if (!PRES(r)) TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
if (TBL(ntss[TSS_LDT])) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
if (IDXTBL(ntss[TSS_LDT])) {
if ((ldtaddr = i80286_selector_address(cpustate,ntss[TSS_LDT])) == -1) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
desc[0] = ReadWord(ldtaddr);
desc[1] = ReadWord(ldtaddr+2);
desc[2] = ReadWord(ldtaddr+4);
r = RIGHTS(desc);
if (SEGDESC(r) || (GATE(r) != LDTDESC)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
if (!PRES(r)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
cpustate->ldtr.sel=ntss[TSS_LDT];
cpustate->ldtr.limit=LIMIT(desc);
cpustate->ldtr.base=BASE(desc);
cpustate->ldtr.rights=RIGHTS(desc);
} else {
cpustate->ldtr.sel=0;
cpustate->ldtr.limit=0;
cpustate->ldtr.base=0;
cpustate->ldtr.rights=0;
}
if (type == CALL) cpustate->flags |= 0x4000;
cpustate->msw |= 8;
cpustate->ldtr.sel=ntss[TSS_LDT]; // docs say nothing about whether a null ldt can be in a tss
cpustate->ldtr.limit=LIMIT(desc);
cpustate->ldtr.base=BASE(desc);
cpustate->ldtr.rights=RIGHTS(desc);
i80286_data_descriptor_full(cpustate, SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_SS])));
cpustate->sregs[CS] = IDXTBL(cpustate->sregs[CS]) | RPL(ntss[TSS_CS]); // fixme
@ -823,6 +828,23 @@ static void PREFIX286(_retf)(i8086_state *cpustate)
ICOUNT -= timing.ret_far;
}
static void PREFIX286(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde */
{
if ((cpustate->msw&8) || (cpustate->msw&4)) throw TRAP(FPU_UNAVAILABLE,-1);
unsigned ModRM = FETCH;
ICOUNT -= timing.nop;
GetRMByte(ModRM);
}
static void PREFIX286(_escape_7)(i8086_state *cpustate) /* Opcode 0xdf */
{
if ((cpustate->msw&8) || (cpustate->msw&4)) throw TRAP(FPU_UNAVAILABLE,-1);
unsigned ModRM = FETCH;
ICOUNT -= timing.nop;
GetRMByte(ModRM);
if (ModRM == 0xe0) cpustate->regs.w[AX] = 0xffff; // FPU not present
}
static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT16 offset, i80286_size size, i80286_operation operation)
{
int trap = 0;

View File

@ -5,9 +5,9 @@
#define INTO_OVERFLOW 4
#define BOUND_OVERRUN 5
#define ILLEGAL_INSTRUCTION 6
#define CPU_EXT_UNAVAILABLE 7
#define FPU_UNAVAILABLE 7
#define DOUBLE_FAULT 8
#define CPU_EXT_SEG_OVERRUN 9
#define FPU_SEG_OVERRUN 9
#define INVALID_TSS 10
#define SEG_NOT_PRESENT 11
#define STACK_FAULT 12
@ -22,6 +22,7 @@ static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT1
static void i80286_data_descriptor(i80286_state *cpustate,int reg, UINT16 selector);
static void PREFIX286(_0fpre)(i80286_state *cpustate);
static void PREFIX286(_arpl)(i80286_state *cpustate);
static void PREFIX286(_escape_7)(i8086_state *cpustate);
static void i80286_pop_seg(i80286_state *cpustate,int reg);
static void i80286_load_flags(i80286_state *cpustate, UINT16 flags, int cpl);

View File

@ -1971,6 +1971,9 @@ static void PREFIX86(_call_far)(i8086_state *cpustate)
static void PREFIX86(_wait)(i8086_state *cpustate) /* Opcode 0x9b */
{
#ifdef I80286
if ((cpustate->msw&0x0a) == 0x0a) throw TRAP(FPU_UNAVAILABLE,-1);
#endif
if (cpustate->test_state)
{
ICOUNT = 0;
@ -2464,12 +2467,14 @@ static void PREFIX86(_xlat)(i8086_state *cpustate) /* Opcode 0xd7 */
cpustate->regs.b[AL] = GetMemB(DS, dest);
}
#ifndef I80286
static void PREFIX86(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
{
unsigned ModRM = FETCH;
ICOUNT -= timing.nop;
GetRMByte(ModRM);
}
#endif
static void PREFIX86(_loopne)(i8086_state *cpustate) /* Opcode 0xe0 */
{

View File

@ -221,14 +221,14 @@ static void (*const PREFIX286(_instruction)[256])(i8086_state *cpustate) =
PREFIX86(_aad), /* 0xd5 */
PREFIX286(_invalid),
PREFIX86(_xlat), /* 0xd7 */
PREFIX86(_escape), /* 0xd8 */
PREFIX86(_escape), /* 0xd9 */
PREFIX86(_escape), /* 0xda */
PREFIX86(_escape), /* 0xdb */
PREFIX86(_escape), /* 0xdc */
PREFIX86(_escape), /* 0xdd */
PREFIX86(_escape), /* 0xde */
PREFIX86(_escape), /* 0xdf */
PREFIX286(_escape), /* 0xd8 */
PREFIX286(_escape), /* 0xd9 */
PREFIX286(_escape), /* 0xda */
PREFIX286(_escape), /* 0xdb */
PREFIX286(_escape), /* 0xdc */
PREFIX286(_escape), /* 0xdd */
PREFIX286(_escape), /* 0xde */
PREFIX286(_escape_7), /* 0xdf */
PREFIX86(_loopne), /* 0xe0 */
PREFIX86(_loope), /* 0xe1 */
PREFIX86(_loop), /* 0xe2 */
@ -484,14 +484,14 @@ static void (*const PREFIX286(_instruction)[256])(i8086_state *cpustate) =
case 0xd5: PREFIX86(_aad)(cpustate); break;\
case 0xd6: PREFIX286(_invalid)(cpustate); break;\
case 0xd7: PREFIX86(_xlat)(cpustate); break;\
case 0xd8: PREFIX86(_escape)(cpustate); break;\
case 0xd9: PREFIX86(_escape)(cpustate); break;\
case 0xda: PREFIX86(_escape)(cpustate); break;\
case 0xdb: PREFIX86(_escape)(cpustate); break;\
case 0xdc: PREFIX86(_escape)(cpustate); break;\
case 0xdd: PREFIX86(_escape)(cpustate); break;\
case 0xde: PREFIX86(_escape)(cpustate); break;\
case 0xdf: PREFIX86(_escape)(cpustate); break;\
case 0xd8: PREFIX286(_escape)(cpustate); break;\
case 0xd9: PREFIX286(_escape)(cpustate); break;\
case 0xda: PREFIX286(_escape)(cpustate); break;\
case 0xdb: PREFIX286(_escape)(cpustate); break;\
case 0xdc: PREFIX286(_escape)(cpustate); break;\
case 0xdd: PREFIX286(_escape)(cpustate); break;\
case 0xde: PREFIX286(_escape)(cpustate); break;\
case 0xdf: PREFIX286(_escape_7)(cpustate); break;\
case 0xe0: PREFIX86(_loopne)(cpustate); break;\
case 0xe1: PREFIX86(_loope)(cpustate); break;\
case 0xe2: PREFIX86(_loop)(cpustate); break;\

View File

@ -1177,6 +1177,8 @@ static void handle_command(ide_state *ide, UINT8 command)
case IDE_COMMAND_SET_CONFIG:
LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", ide->cur_head + 1, ide->sector_count));
ide->status &= ~IDE_STATUS_ERROR;
ide->error = IDE_ERROR_NONE;
ide->num_sectors = ide->sector_count;
ide->num_heads = ide->cur_head + 1;