summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2011-05-18 16:24:02 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2011-05-18 16:24:02 +0000
commitd96852828bfe9368712de3cb6ac1d5bebae9e247 (patch)
treef36a0ad5e337217e1bac2b7d0522f4c6d29b0114 /src
parent8f7dba221cc1666ca3c18653191ce900f592fa06 (diff)
i286 - More protected mode fixes by Carl (no whatsnew)
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/i86/i286.c7
-rw-r--r--src/emu/cpu/i86/instr286.c25
-rw-r--r--src/emu/cpu/i86/instr86.c53
3 files changed, 66 insertions, 19 deletions
diff --git a/src/emu/cpu/i86/i286.c b/src/emu/cpu/i86/i286.c
index 2765070e70c..085a1628470 100644
--- a/src/emu/cpu/i86/i286.c
+++ b/src/emu/cpu/i86/i286.c
@@ -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)
diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c
index dba92252483..2cb3fbf1d4f 100644
--- a/src/emu/cpu/i86/instr286.c
+++ b/src/emu/cpu/i86/instr286.c
@@ -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);
diff --git a/src/emu/cpu/i86/instr86.c b/src/emu/cpu/i86/instr86.c
index 5fee9ef6f1e..2e892d319c8 100644
--- a/src/emu/cpu/i86/instr86.c
+++ b/src/emu/cpu/i86/instr86.c
@@ -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 */
}