diff options
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 |
commit | 6b38d5156beb5f36588ba48540b194982cf343f9 (patch) | |
tree | 0f1d0d62aeb058f002818fd28914995f6224b687 | |
parent | 889162a4f3f41113637d7902f9c5baf72dead481 (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.c | 6 | ||||
-rw-r--r-- | src/emu/cpu/i386/i386op32.c | 6 | ||||
-rw-r--r-- | src/emu/cpu/i86/instr286.c | 4 |
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); } |