diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index d74b181bf..77d984048 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -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]; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index db11b6135..1456d2ee8 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -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*/ diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index 87dddefd8..419ee7dc2 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.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(); diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 7c286b605..abc34ff96 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -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;