Made LOCK instruction legality more accurate on 386, closes #4132.
This commit is contained in:
@@ -120,6 +120,53 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /*
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
|
||||
/* 0 = no, 1 = always, 2 = depends on second opcode, 3 = depends on mod/rm */
|
||||
int lock_legal[256] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 2, /* 0x0x */
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x1x */
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x2x */
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
|
||||
3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xax */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xbx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
|
||||
0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3 }; /* 0xfx */
|
||||
|
||||
int lock_legal_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
|
||||
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0xax */
|
||||
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, /* 0xbx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 0xfx */
|
||||
|
||||
/* (modrm >> 3) & 0x07 */
|
||||
int lock_legal_ba[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
|
||||
|
||||
/* Also applies to 81, 82, and 83 */
|
||||
int lock_legal_80[8] = { 1, 1, 1, 1, 1, 1, 1, 0 };
|
||||
|
||||
/* Also applies to F7 */
|
||||
int lock_legal_f6[8] = { 0, 0, 1, 1, 0, 0, 0, 0 };
|
||||
|
||||
/* Also applies to FF */
|
||||
int lock_legal_fe[8] = { 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
uint32_t addr64;
|
||||
uint32_t addr64_2;
|
||||
uint32_t addr64a[8];
|
||||
|
||||
@@ -763,6 +763,11 @@ void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg);
|
||||
#define SMHR_VALID (1 << 0)
|
||||
#define SMHR_ADDR_MASK (0xfffffffc)
|
||||
|
||||
typedef union {
|
||||
uint32_t fd;
|
||||
uint8_t b[4];
|
||||
} fetch_dat_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint32_t base;
|
||||
@@ -817,4 +822,11 @@ extern void prefetch_flush(void);
|
||||
|
||||
extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32);
|
||||
|
||||
extern int lock_legal[256];
|
||||
extern int lock_legal_0f[256];
|
||||
extern int lock_legal_ba[8];
|
||||
extern int lock_legal_80[8];
|
||||
extern int lock_legal_f6[8];
|
||||
extern int lock_legal_fe[8];
|
||||
|
||||
#endif /*EMU_CPU_H*/
|
||||
|
||||
@@ -730,12 +730,49 @@ opHLT(uint32_t fetchdat)
|
||||
static int
|
||||
opLOCK(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
int legal;
|
||||
fetch_dat_t fetch_dat;
|
||||
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return 0;
|
||||
cpu_state.pc++;
|
||||
|
||||
ILLEGAL_ON((fetchdat & 0xff) == 0x90);
|
||||
fetch_dat.fd = fetchdat;
|
||||
|
||||
legal = lock_legal[fetch_dat.b[0]];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
|
||||
else if (legal == 2) {
|
||||
legal = lock_legal[fetch_dat.b[1]];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,reg is illegal */
|
||||
else if (legal == 3) {
|
||||
legal = lock_legal_ba[(fetch_dat.b[2] >> 3) & 0x07];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,imm is illegal */
|
||||
}
|
||||
} else if (legal == 3) switch(fetch_dat.b[0]) {
|
||||
case 0x80 ... 0x83:
|
||||
legal = lock_legal_80[(fetch_dat.b[1] >> 3) & 0x07];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
|
||||
break;
|
||||
case 0xf6 ... 0xf7:
|
||||
legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
|
||||
break;
|
||||
case 0xfe ... 0xff:
|
||||
legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07];
|
||||
if (legal == 1)
|
||||
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
|
||||
break;
|
||||
default:
|
||||
legal = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ILLEGAL_ON(legal == 0);
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
@@ -51,7 +51,6 @@ mem_debug_check_addr(uint32_t addr, int flags)
|
||||
uint32_t len_type_pair;
|
||||
int bp_enabled;
|
||||
uint8_t match_flags[4] = { 0, 2, 0, 6 };
|
||||
char *bp_types[5] = { "N/A 0", "EXEC ", "WRITE", "N/A 3", "READ " };
|
||||
|
||||
if (cpu_state.abrt || ((flags == 1) && (cpu_state.eflags & RF_FLAG)))
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user