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)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)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)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 */ }