LDS/LES/LFS/LGS/LSS: Fix segment wraparounds in 16-bit address mode.

This commit is contained in:
OBattler
2025-04-07 06:03:19 +02:00
parent 018ff46253
commit 3b5966eb46
15 changed files with 105 additions and 31 deletions

View File

@@ -248,6 +248,19 @@ int checkio(uint32_t port, int mask);
return 1; \
}
#define CHECK_READ_2OP(chseg, low, high, low2, high2) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) { \
x86gpf("Limit check (READ)", 0); \
return 1; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_READ_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \
x86gpf("Limit check (READ)", 0); \
@@ -277,6 +290,19 @@ int checkio(uint32_t port, int mask);
#define CHECK_WRITE(chseg, low, high) \
CHECK_WRITE_COMMON(chseg, low, high)
#define CHECK_WRITE_2OP(chseg, low, high, low2, high2) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) { \
x86gpf("Limit check (WRITE)", 0); \
return 1; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_WRITE_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \
x86gpf("Limit check (WRITE REP)", 0); \

View File

@@ -335,7 +335,10 @@ typedef struct {
uint8_t tag[8];
x86seg *ea_seg;
uint32_t eaaddr;
union {
uint32_t eaaddr;
uint16_t eaa16[2];
};
int flags_op;
uint32_t flags_res;

View File

@@ -272,9 +272,10 @@ opLDS_w_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2);
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1,
((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1);
addr = readmemw(easeg, cpu_state.eaa16[0]);
seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff);
if (cpu_state.abrt)
return 1;
op_loadseg(seg, &cpu_state.seg_ds);
@@ -318,9 +319,10 @@ opLDS_l_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4);
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3,
((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1);
addr = readmeml(easeg, cpu_state.eaa16[0]);
seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff);
if (cpu_state.abrt)
return 1;
op_loadseg(seg, &cpu_state.seg_ds);
@@ -365,9 +367,10 @@ opLSS_w_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2);
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1,
((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1);
addr = readmemw(easeg, cpu_state.eaa16[0]);
seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff);
if (cpu_state.abrt)
return 1;
op_loadseg(seg, &cpu_state.seg_ss);
@@ -411,9 +414,11 @@ opLSS_l_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4);
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3,
((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 5) & 0xffff));
addr = readmeml(easeg, cpu_state.eaa16[0]);
seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff);
if (cpu_state.abrt)
return 1;
op_loadseg(seg, &cpu_state.seg_ss);
@@ -457,9 +462,9 @@ opLSS_l_a32(uint32_t fetchdat)
fetch_ea_16(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \
addr = readmemw(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 2); \
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 1, ((cpu_state.eaa16[0] + 2) & 0xffff), ((cpu_state.eaa16[0] + 2) & 0xffff) + 1); \
addr = readmemw(easeg, cpu_state.eaa16[0]); \
seg = readmemw(easeg, (cpu_state.eaa16[0] + 2) & 0xffff); \
if (cpu_state.abrt) \
return 1; \
op_loadseg(seg, &sel); \
@@ -502,9 +507,9 @@ opLSS_l_a32(uint32_t fetchdat)
fetch_ea_16(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \
addr = readmeml(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 4); \
CHECK_READ_2OP(cpu_state.ea_seg, cpu_state.eaa16[0], cpu_state.eaa16[0] + 3, ((cpu_state.eaa16[0] + 4) & 0xffff), ((cpu_state.eaa16[0] + 4) & 0xffff) + 1); \
addr = readmeml(easeg, cpu_state.eaa16[0]); \
seg = readmemw(easeg, (cpu_state.eaa16[0] + 4) & 0xffff); \
if (cpu_state.abrt) \
return 1; \
op_loadseg(seg, &sel); \

View File

@@ -15,7 +15,7 @@
op_loadcs(readmemw(ss, ESP + 2)); \
} else { \
cpu_state.pc = readmemw(ss, SP); \
op_loadcs(readmemw(ss, SP + 2)); \
op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \
} \
if (cpu_state.abrt) \
return 1; \

View File

@@ -15,7 +15,7 @@
op_loadcs(readmemw(ss, ESP + 2)); \
} else { \
cpu_state.pc = readmemw(ss, SP); \
op_loadcs(readmemw(ss, SP + 2)); \
op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \
} \
if (cpu_state.abrt) \
return 1; \