diff options
author | 2011-06-10 08:37:19 +0000 | |
---|---|---|
committer | 2011-06-10 08:37:19 +0000 | |
commit | 6312851a55dd96334b7408bc7142fab6c1c26a12 (patch) | |
tree | 5f986d874911fa94a8620dea24f99cfe545a993f /src/emu/cpu/i86 | |
parent | c2b740e21f3fd315c534b8a837cf1c7967479a63 (diff) |
i286 - core fixes enabling some progress on OS/2 1.1 by Carl (no whatsnew)
Diffstat (limited to 'src/emu/cpu/i86')
-rw-r--r-- | src/emu/cpu/i86/instr286.c | 60 | ||||
-rw-r--r-- | src/emu/cpu/i86/instr86.c | 4 |
2 files changed, 31 insertions, 33 deletions
diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c index f25a446ba64..82d4f566c01 100644 --- a/src/emu/cpu/i86/instr286.c +++ b/src/emu/cpu/i86/instr286.c @@ -208,10 +208,10 @@ static void i80286_data_descriptor(i80286_state *cpustate, int reg, UINT16 selec static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type) { UINT16 ndesc[3], desc[3], ntss[22], otss[22]; - UINT8 r; + UINT8 r, lr; UINT32 naddr, oaddr, ldtaddr; int i; - logerror("This program uses TSSs, how rare. Expect a crash.\n"); + logerror("This program uses TSSs, how rare. Please report this to the developers.\n"); 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); @@ -220,9 +220,9 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type) ndesc[2] = ReadWord(naddr+4); desc[2] = ReadWord(oaddr+4); r = RIGHTS(ndesc); - if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(ntask)); + if (SEGDESC(r) || ((GATE(r) & ~2) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(ntask)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(ntask)); - if (LIMIT(ndesc) < 44) throw TRAP(INVALID_TSS,IDXTBL(ntask)); + if (LIMIT(ndesc) < 43) throw TRAP(INVALID_TSS,IDXTBL(ntask)); for (i = 0; i < 44; i+=2) ntss[i/2] = ReadWord(BASE(ndesc)+i); cpustate->flags = CompressFlags(); @@ -273,13 +273,14 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type) 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])); + 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])); + lr = RIGHTS(desc); + if (SEGDESC(lr) || (GATE(lr) != LDTDESC)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); + if (!PRES(lr)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); cpustate->ldtr.sel=ntss[TSS_LDT]; cpustate->ldtr.limit=LIMIT(desc); cpustate->ldtr.base=BASE(desc); @@ -342,13 +343,14 @@ static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT } else { // systemdescriptor UINT16 gatedesc[3]={0,0,0}; UINT16 gatesel = GATESEL(desc); - if (!gate) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); // can't ret through gate + if (!gate) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); // tss cs must be segment if (DPL(r) < PMAX(CPL,RPL(selector))) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(selector)); switch (GATE(r)) { case CALLGATE: - if ((addr = i80286_selector_address(cpustate,gatesel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); + if ((addr = i80286_selector_address(cpustate,gatesel)) == -1) + throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); gatedesc[0] = ReadWord(addr); gatedesc[1] = ReadWord(addr+2); gatedesc[2] = ReadWord(addr+4); @@ -385,14 +387,14 @@ static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK; break; case TASKGATE: - gatesel = GATESEL(gatedesc); - if ((addr = i80286_selector_address(cpustate,gatesel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); - gatedesc[2] = ReadWord(addr+4); - r = RIGHTS(gatedesc); - if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); - if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(gatesel)); + selector = gatesel; + if ((addr = i80286_selector_address(cpustate,selector)) == -1) + throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); + desc[2] = ReadWord(addr+4); + r = RIGHTS(desc); + if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); case TSSDESCIDLE: - i80286_switch_task(cpustate, gatesel, gate); + i80286_switch_task(cpustate, selector, gate); i80286_load_flags(cpustate, cpustate->flags, CPL); break; default: @@ -429,8 +431,7 @@ static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, in switch (GATE(r)) { case TASKGATE: - gatesel = GATESEL(gatedesc); - i80286_switch_task(cpustate, gatesel, 2); + i80286_switch_task(cpustate, gatesel, CALL); if((hwint == 1) && (error != -1)) PUSH(error); i80286_load_flags(cpustate, cpustate->flags, CPL); break; @@ -739,6 +740,12 @@ static UINT16 i80286_far_return(i8086_state *cpustate, int iret, int bytes) { UINT16 sel, off, flags = 0; int spaddr; + + if (PM && NT && iret) { + i80286_switch_task(cpustate, ReadWord(cpustate->tr.base+TSS_BACK*2), IRET); + return cpustate->flags; + } + // must be restartable spaddr = (cpustate->base[SS] + cpustate->regs.w[SP]) & AMASK; off = ReadWord(spaddr); @@ -749,24 +756,15 @@ static UINT16 i80286_far_return(i8086_state *cpustate, int iret, int bytes) UINT16 desc[3], newsp, newss; int addr, r; - if (TBL(sel)) { /* local descriptor table */ - if (sel>cpustate->ldtr.limit) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); - addr = cpustate->ldtr.base+IDX(sel); - } else { /* global descriptor table */ - if (!IDX(sel)||(sel>cpustate->gdtr.limit)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); - addr = cpustate->gdtr.base+IDX(sel); - } + if ((addr = i80286_selector_address(cpustate,sel)) == -1) + throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); + if (RPL(sel)<CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); desc[0] = ReadWord(addr); desc[1] = ReadWord(addr+2); desc[2] = ReadWord(addr+4); r = RIGHTS(desc); - if (NT && iret) { - i80286_switch_task(cpustate, ReadWord(cpustate->tr.base+TSS_BACK*2), IRET); - return cpustate->flags; - } - if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); if (CONF(r)) { if(DPL(r)>RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); } else if (DPL(r)!=RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); diff --git a/src/emu/cpu/i86/instr86.c b/src/emu/cpu/i86/instr86.c index ed56b2cb5ad..d5f137e7461 100644 --- a/src/emu/cpu/i86/instr86.c +++ b/src/emu/cpu/i86/instr86.c @@ -2298,13 +2298,13 @@ static void PREFIX86(_les_dw)(i8086_state *cpustate) /* Opcode 0xc4 */ unsigned ModRM = FETCH; WORD tmp = GetRMWord(ModRM); - RegWord(ModRM)= tmp; #ifdef I80286 i80286_data_descriptor(cpustate,ES,GetnextRMWord); #else cpustate->sregs[ES] = GetnextRMWord; cpustate->base[ES] = SegBase(ES); #endif + RegWord(ModRM)= tmp; ICOUNT -= timing.load_ptr; } @@ -2313,13 +2313,13 @@ static void PREFIX86(_lds_dw)(i8086_state *cpustate) /* Opcode 0xc5 */ unsigned ModRM = FETCH; WORD tmp = GetRMWord(ModRM); - RegWord(ModRM)=tmp; #ifdef I80286 i80286_data_descriptor(cpustate,DS,GetnextRMWord); #else cpustate->sregs[DS] = GetnextRMWord; cpustate->base[DS] = SegBase(DS); #endif + RegWord(ModRM)=tmp; ICOUNT -= timing.load_ptr; } |