Implement special selector pushing behavior and improve the opcode length heuristic for CS limit checks, fixes #4552.
This commit is contained in:
@@ -212,11 +212,11 @@ fetch_ea_16_long(uint32_t rmdat)
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#define CHECK_READ_CS(size) \
|
||||
if ((cpu_state.pc < cpu_state.seg_cs.limit_low) || \
|
||||
((cpu_state.pc + size - 1) > cpu_state.seg_cs.limit_high)) \
|
||||
x86gpf("Limit check (READ)", 0); \
|
||||
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !(cpu_state.seg_cs.access & 0x80)) \
|
||||
x86np("Read from seg not present", cpu_state.seg_cs.seg & 0xfffc); \
|
||||
else if ((cpu_state.pc < cpu_state.seg_cs.limit_low) || \
|
||||
((cpu_state.pc + size - 1) > cpu_state.seg_cs.limit_high)) \
|
||||
x86gpf("Limit check (READ CS)", 0);
|
||||
|
||||
#include "386_ops.h"
|
||||
|
||||
@@ -261,7 +261,13 @@ exec386_2386(int32_t cycs)
|
||||
|
||||
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
|
||||
ol = opcode_length[fetchdat & 0xff];
|
||||
CHECK_READ_CS(MIN(ol, 4));
|
||||
if ((ol == 3) && opcode_has_modrm[fetchdat & 0xff] && (((fetchdat >> 14) & 0x03) == 0x03))
|
||||
ol = 2;
|
||||
if (cpu_16bitbus) {
|
||||
CHECK_READ_CS(MIN(ol, 2));
|
||||
} else {
|
||||
CHECK_READ_CS(MIN(ol, 4));
|
||||
}
|
||||
ins_fetch_fault = cpu_386_check_instruction_fault();
|
||||
|
||||
/* Breakpoint fault has priority over other faults. */
|
||||
|
@@ -106,6 +106,28 @@ uint32_t backupregs[16];
|
||||
|
||||
x86seg _oldds;
|
||||
|
||||
int opcode_has_modrm[256] = {
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
|
||||
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/
|
||||
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/
|
||||
|
||||
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/
|
||||
};
|
||||
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
|
||||
|
@@ -449,6 +449,7 @@ get_ram_ptr(uint32_t a)
|
||||
}
|
||||
}
|
||||
|
||||
extern int opcode_has_modrm[256];
|
||||
extern int opcode_length[256];
|
||||
|
||||
#ifdef OPS_286_386
|
||||
|
@@ -798,6 +798,27 @@ PUSHL(uint32_t v)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PUSHL_SEL(uint32_t v)
|
||||
{
|
||||
if (cpu_16bitbus) {
|
||||
PUSHW(v >> 16);
|
||||
PUSHW(v & 0xffff);
|
||||
} else {
|
||||
if (stack32) {
|
||||
writememw(ss, ESP - 4, v);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
ESP -= 4;
|
||||
} else {
|
||||
writememw(ss, ((SP - 4) & 0xffff), v);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
SP -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
POPW(void)
|
||||
{
|
||||
@@ -1092,7 +1113,7 @@ loadcscall(uint16_t seg)
|
||||
|
||||
x86seg_log("Type %04X\n", type);
|
||||
if (type == 0x0c00) {
|
||||
PUSHL(oldss);
|
||||
PUSHL_SEL(oldss);
|
||||
PUSHL(oldsp2);
|
||||
if (cpu_state.abrt) {
|
||||
SS = oldss;
|
||||
@@ -1622,10 +1643,10 @@ pmodeint(int num, int soft)
|
||||
cpl_override = 1;
|
||||
if (type >= 0x0800) {
|
||||
if (cpu_state.eflags & VM_FLAG) {
|
||||
PUSHL(GS);
|
||||
PUSHL(FS);
|
||||
PUSHL(DS);
|
||||
PUSHL(ES);
|
||||
PUSHL_SEL(GS);
|
||||
PUSHL_SEL(FS);
|
||||
PUSHL_SEL(DS);
|
||||
PUSHL_SEL(ES);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
op_loadseg(0, &cpu_state.seg_ds);
|
||||
@@ -1633,10 +1654,10 @@ pmodeint(int num, int soft)
|
||||
op_loadseg(0, &cpu_state.seg_fs);
|
||||
op_loadseg(0, &cpu_state.seg_gs);
|
||||
}
|
||||
PUSHL(oldss);
|
||||
PUSHL_SEL(oldss);
|
||||
PUSHL(oldsp);
|
||||
PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
|
||||
PUSHL(CS);
|
||||
PUSHL_SEL(CS);
|
||||
PUSHL(cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
@@ -1672,7 +1693,7 @@ pmodeint(int num, int soft)
|
||||
}
|
||||
if (type > 0x0800) {
|
||||
PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
|
||||
PUSHL(CS);
|
||||
PUSHL_SEL(CS);
|
||||
PUSHL(cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
|
Reference in New Issue
Block a user