i286 - More protected mode fixes by Carl (no whatsnew)

This commit is contained in:
Miodrag Milanovic 2011-05-18 16:24:02 +00:00
parent 8f7dba221c
commit d96852828b
3 changed files with 66 additions and 19 deletions

View File

@ -170,6 +170,7 @@ static CPU_RESET( i80286 )
cpustate->ldtr.rights=cpustate->tr.rights=0;
cpustate->ldtr.sel=cpustate->tr.sel=0;
cpustate->rep_in_progress = FALSE;
cpustate->seg_prefix = FALSE;
CHANGE_PC(cpustate->pc);
@ -239,10 +240,12 @@ static CPU_EXECUTE( i80286 )
debugger_instruction_hook(device, cpustate->pc);
cpustate->seg_prefix=FALSE;
cpustate->prevpc = cpustate->pc;
try
{
if (PM && ((cpustate->pc-cpustate->base[CS]) > cpustate->limit[CS]))
throw TRAP(GENERAL_PROTECTION_FAULT, cpustate->sregs[CS] & ~3);
cpustate->prevpc = cpustate->pc;
TABLE286 // call instruction
}
catch (UINT32 e)

View File

@ -248,7 +248,6 @@ static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT1
if (!IDX(gatesel)||(gatesel>cpustate->gdtr.limit)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
addr = cpustate->gdtr.base+IDX(gatesel);
}
addr = cpustate->gdtr.base+IDX(gatesel);
gatedesc[0] = ReadWord(addr);
gatedesc[1] = ReadWord(addr+2);
gatedesc[2] = ReadWord(addr+4);
@ -260,8 +259,10 @@ static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT1
if (!CONF(r)&&(DPL(r)<CPL)) { // inner call
UINT16 ssdesc[3];
UINT16 tss_ss,tss_sp, oldss, oldsp;
int oldsp_phy, ssr, i;
UINT16 tss_ss, tss_sp, oldss, oldsp;
UINT32 oldstk;
UINT8 ssr;
int i;
if(gate == 1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); // can't jmp to inner
tss_ss = ReadWord(cpustate->tr.base+TSS_SS0+(DPL(r)*4));
tss_sp = ReadWord(cpustate->tr.base+TSS_SP0+(DPL(r)*4));
@ -278,19 +279,20 @@ static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT1
ssdesc[1] = ReadWord(addr+2);
ssdesc[2] = ReadWord(addr+4);
ssr = RIGHTS(ssdesc);
if ((RPL(tss_ss) != DPL(r)) || DPL(ssr) != DPL(r)) TRAP(INVALID_TSS,IDXTBL(tss_ss));
if ((RPL(tss_ss) != DPL(r)) || (DPL(ssr) != DPL(r))) TRAP(INVALID_TSS,IDXTBL(tss_ss));
if (!RW(ssr) || !PRES(ssr)) throw TRAP(INVALID_TSS,IDXTBL(tss_ss));
oldss = cpustate->sregs[SS];
oldsp = cpustate->regs.w[SP];
oldsp_phy = cpustate->base[SS]+oldsp+(GATECNT(desc)*2);
oldstk = cpustate->base[SS]+oldsp;
cpustate->sregs[SS]=tss_ss;
cpustate->limit[SS]=LIMIT(ssdesc);
cpustate->base[SS]=BASE(ssdesc);
cpustate->rights[SS]=RIGHTS(ssdesc);
cpustate->regs.w[SP] = tss_sp;
PUSH(oldss);
PUSH(oldsp);
for (i = 0; i < GATECNT(desc); i++)
PUSH(ReadWord(oldsp_phy-(i*2)));
for (i = GATECNT(desc)-1; i >= 0; i--)
PUSH(ReadWord(oldstk+(i*2)));
}
cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
cpustate->limit[CS]=LIMIT(gatedesc);
@ -384,6 +386,7 @@ static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, in
cpustate->limit[SS]=LIMIT(ssdesc);
cpustate->base[SS]=BASE(ssdesc);
cpustate->rights[SS]=RIGHTS(ssdesc);
cpustate->regs.w[SP] = tss_sp;
PUSH(oldss);
PUSH(oldsp);
}
@ -479,7 +482,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
cpustate->ZeroVal=0;
else if (CODE(r) && CONF(r))
cpustate->ZeroVal=1;
else if ((DPL(r)<CPL) || (DPL(r)<RPL(tmp)))
else if (DPL(r)<PMAX(CPL,RPL(tmp)))
cpustate->ZeroVal=0;
else cpustate->ZeroVal=1;
}
@ -498,7 +501,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
r = RIGHTS(desc);
if (!SEGDESC(r) || CODE(r))
cpustate->ZeroVal=0;
else if ((DPL(r)<CPL) || (DPL(r)<RPL(tmp)))
else if (DPL(r)<PMAX(CPL,RPL(tmp)))
cpustate->ZeroVal=0;
else cpustate->ZeroVal=1;
}
@ -539,7 +542,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
case 0x30: /* lmsw */
if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
msw = GetRMWord(ModRM);
if (!PM&(msw&1)) cpustate->sregs[CS] = IDX(cpustate->sregs[CS]); // cheat and set cpl to 0
if (!PM&&(msw&1)) cpustate->sregs[CS] = IDX(cpustate->sregs[CS]); // cheat and set cpl to 0
cpustate->msw=(cpustate->msw&1)|msw;
break;
default:
@ -619,7 +622,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
case 6: /* clts */
if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
cpustate->msw=~8;
cpustate->msw&=~8;
break;
default:
throw TRAP(ILLEGAL_INSTRUCTION,-1);

View File

@ -435,6 +435,9 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
break;
#ifndef I8086
case 0x6c: /* REP INSB */
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins8_base;
cpustate->rep_in_progress = FALSE;
@ -448,6 +451,9 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count;
break;
case 0x6d: /* REP INSW */
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins16_base;
cpustate->rep_in_progress = FALSE;
@ -461,6 +467,9 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count;
break;
case 0x6e: /* REP OUTSB */
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs8_base;
cpustate->rep_in_progress = FALSE;
@ -474,6 +483,9 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count;
break;
case 0x6f: /* REP OUTSW */
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs16_base;
cpustate->rep_in_progress = FALSE;
@ -2519,7 +2531,11 @@ static void PREFIX86(_jcxz)(i8086_state *cpustate) /* Opcode 0xe3 */
static void PREFIX86(_inal)(i8086_state *cpustate) /* Opcode 0xe4 */
{
unsigned port = FETCH;
unsigned port;
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
port = FETCH;
ICOUNT -= timing.in_imm8;
cpustate->regs.b[AL] = read_port_byte(port);
@ -2527,7 +2543,11 @@ static void PREFIX86(_inal)(i8086_state *cpustate) /* Opcode 0xe4 */
static void PREFIX86(_inax)(i8086_state *cpustate) /* Opcode 0xe5 */
{
unsigned port = FETCH;
unsigned port;
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
port = FETCH;
ICOUNT -= timing.in_imm16;
cpustate->regs.w[AX] = read_port_word(port);
@ -2535,7 +2555,11 @@ static void PREFIX86(_inax)(i8086_state *cpustate) /* Opcode 0xe5 */
static void PREFIX86(_outal)(i8086_state *cpustate) /* Opcode 0xe6 */
{
unsigned port = FETCH;
unsigned port;
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
port = FETCH;
ICOUNT -= timing.out_imm8;
write_port_byte(port, cpustate->regs.b[AL]);
@ -2543,7 +2567,11 @@ static void PREFIX86(_outal)(i8086_state *cpustate) /* Opcode 0xe6 */
static void PREFIX86(_outax)(i8086_state *cpustate) /* Opcode 0xe7 */
{
unsigned port = FETCH;
unsigned port;
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
port = FETCH;
ICOUNT -= timing.out_imm16;
write_port_word(port, cpustate->regs.w[AX]);
@ -2605,6 +2633,9 @@ static void PREFIX86(_jmp_d8)(i8086_state *cpustate) /* Opcode 0xeb */
static void PREFIX86(_inaldx)(i8086_state *cpustate) /* Opcode 0xec */
{
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
ICOUNT -= timing.in_dx8;
cpustate->regs.b[AL] = read_port_byte(cpustate->regs.w[DX]);
}
@ -2612,13 +2643,18 @@ static void PREFIX86(_inaldx)(i8086_state *cpustate) /* Opcode 0xec */
static void PREFIX86(_inaxdx)(i8086_state *cpustate) /* Opcode 0xed */
{
unsigned port = cpustate->regs.w[DX];
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
ICOUNT -= timing.in_dx16;
cpustate->regs.w[AX] = read_port_word(port);
}
static void PREFIX86(_outdxal)(i8086_state *cpustate) /* Opcode 0xee */
{
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
ICOUNT -= timing.out_dx8;
write_port_byte(cpustate->regs.w[DX], cpustate->regs.b[AL]);
}
@ -2626,7 +2662,9 @@ static void PREFIX86(_outdxal)(i8086_state *cpustate) /* Opcode 0xee */
static void PREFIX86(_outdxax)(i8086_state *cpustate) /* Opcode 0xef */
{
unsigned port = cpustate->regs.w[DX];
#ifdef I80286
if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
#endif
ICOUNT -= timing.out_dx16;
write_port_word(port, cpustate->regs.w[AX]);
}
@ -2634,6 +2672,9 @@ static void PREFIX86(_outdxax)(i8086_state *cpustate) /* Opcode 0xef */
/* I think thats not a V20 instruction...*/
static void PREFIX86(_lock)(i8086_state *cpustate) /* Opcode 0xf0 */
{
#ifdef I80286
if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
#endif
ICOUNT -= timing.nop;
PREFIX(_instruction)[FETCHOP](cpustate); /* un-interruptible */
}