From 5aa0cf528a86e8585dbea310e5b1563384c7200f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 29 May 2011 08:43:52 +0000 Subject: [PATCH] i286 - enabling 287 emulation by trapping when needed [Carl] idectrl - Clears error status on driver initialization [Carl] --- src/emu/cpu/i86/instr286.c | 56 ++++++++++++++++++++++++++------------ src/emu/cpu/i86/instr286.h | 5 ++-- src/emu/cpu/i86/instr86.c | 5 ++++ src/emu/cpu/i86/table286.h | 32 +++++++++++----------- src/emu/machine/idectrl.c | 2 ++ 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c index 104356af418..4b947b05daf 100644 --- a/src/emu/cpu/i86/instr286.c +++ b/src/emu/cpu/i86/instr286.c @@ -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; diff --git a/src/emu/cpu/i86/instr286.h b/src/emu/cpu/i86/instr286.h index 645ae141885..04c96862fbd 100644 --- a/src/emu/cpu/i86/instr286.h +++ b/src/emu/cpu/i86/instr286.h @@ -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); diff --git a/src/emu/cpu/i86/instr86.c b/src/emu/cpu/i86/instr86.c index 3ae3f72c747..e7086dd5e78 100644 --- a/src/emu/cpu/i86/instr86.c +++ b/src/emu/cpu/i86/instr86.c @@ -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 */ { diff --git a/src/emu/cpu/i86/table286.h b/src/emu/cpu/i86/table286.h index c94dcd5a4dc..24b1b05215b 100644 --- a/src/emu/cpu/i86/table286.h +++ b/src/emu/cpu/i86/table286.h @@ -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;\ diff --git a/src/emu/machine/idectrl.c b/src/emu/machine/idectrl.c index f19536c2793..e5b8675fc80 100644 --- a/src/emu/machine/idectrl.c +++ b/src/emu/machine/idectrl.c @@ -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;