summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author cracyc <cracyc@users.noreply.github.com>2013-04-05 19:59:17 +0000
committer cracyc <cracyc@users.noreply.github.com>2013-04-05 19:59:17 +0000
commit6b38d5156beb5f36588ba48540b194982cf343f9 (patch)
tree0f1d0d62aeb058f002818fd28914995f6224b687
parent889162a4f3f41113637d7902f9c5baf72dead481 (diff)
i386: RPL must be not be greater than DPL in LSL and LAR (nw)
i286: Conforming code segments are always permitted in LSL and LAR (nw)
-rw-r--r--src/emu/cpu/i386/i386op16.c6
-rw-r--r--src/emu/cpu/i386/i386op32.c6
-rw-r--r--src/emu/cpu/i86/instr286.c4
3 files changed, 10 insertions, 6 deletions
diff --git a/src/emu/cpu/i386/i386op16.c b/src/emu/cpu/i386/i386op16.c
index db2814fc24c..35b0e9571a7 100644
--- a/src/emu/cpu/i386/i386op16.c
+++ b/src/emu/cpu/i386/i386op16.c
@@ -3494,7 +3494,8 @@ static void I386OP(lar_r16_rm16)(i386_state *cpustate) // Opcode 0x0f 0x02
SetZF(0);
return;
}
- if((((seg.flags >> 5) & 3) < cpustate->CPL) && ((seg.flags & 0x1c) != 0x1c))
+ UINT8 DPL = (seg.flags >> 5) & 3;
+ if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
{
SetZF(0);
return;
@@ -3558,7 +3559,8 @@ static void I386OP(lsl_r16_rm16)(i386_state *cpustate) // Opcode 0x0f 0x03
SetZF(0);
return;
}
- if((((seg.flags >> 5) & 3) < cpustate->CPL) && ((seg.flags & 0x1c) != 0x1c))
+ UINT8 DPL = (seg.flags >> 5) & 3;
+ if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
{
SetZF(0);
return;
diff --git a/src/emu/cpu/i386/i386op32.c b/src/emu/cpu/i386/i386op32.c
index 502f875a3e5..a11702cb316 100644
--- a/src/emu/cpu/i386/i386op32.c
+++ b/src/emu/cpu/i386/i386op32.c
@@ -3298,7 +3298,8 @@ static void I386OP(lar_r32_rm32)(i386_state *cpustate) // Opcode 0x0f 0x02
SetZF(0);
return;
}
- if((((seg.flags >> 5) & 3) < cpustate->CPL) && ((seg.flags & 0x1c) != 0x1c))
+ UINT8 DPL = (seg.flags >> 5) & 3;
+ if((DPL < cpustate->CPL) && (DPL < (seg.selector & 3)) && ((seg.flags & 0x1c) != 0x1c))
{
SetZF(0);
return;
@@ -3362,7 +3363,8 @@ static void I386OP(lsl_r32_rm32)(i386_state *cpustate) // Opcode 0x0f 0x03
SetZF(0);
return;
}
- if((((seg.flags >> 5) & 3) < cpustate->CPL) && ((seg.flags & 0x1c) != 0x1c))
+ UINT8 DPL = (seg.flags >> 5) & 3;
+ if((DPL < cpustate->CPL) && (DPL < (seg.selector & 3)) && ((seg.flags & 0x1c) != 0x1c))
{
SetZF(0);
return;
diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c
index 4b2a33f5097..de98a5f7517 100644
--- a/src/emu/cpu/i86/instr286.c
+++ b/src/emu/cpu/i86/instr286.c
@@ -618,7 +618,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
else {
desc[2] = ReadWord(addr+4);
r = RIGHTS(desc);
- if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
+ if (DPL(r)>=PMAX(RPL(tmp),CPL) || (SEGDESC(r) && CODE(r) && CONF(r))) {
cpustate->ZeroVal = 0;
// rights are expected to be in upper byte
RegWord(ModRM) = r << 8;
@@ -636,7 +636,7 @@ static void PREFIX286(_0fpre)(i8086_state *cpustate)
desc[2] = ReadWord(addr+4);
r = RIGHTS(desc);
if (!SEGDESC(r) && (GATE(r) >= CALLGATE)) cpustate->ZeroVal = 1; // not valid for gates
- else if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
+ else if (DPL(r)>=PMAX(RPL(tmp),CPL) || (SEGDESC(r) && CODE(r) && CONF(r))) {
cpustate->ZeroVal = 0;
RegWord(ModRM) = ReadWord(addr);
}