536 lines
18 KiB
C
536 lines
18 KiB
C
static int
|
|
opMOV_w_seg_a16(uint32_t fetchdat)
|
|
{
|
|
fetch_ea_16(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
seteaw(ES);
|
|
break;
|
|
case 0x08: /*CS*/
|
|
seteaw(CS);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
seteaw(DS);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
seteaw(SS);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
seteaw(FS);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
seteaw(GS);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0);
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opMOV_w_seg_a32(uint32_t fetchdat)
|
|
{
|
|
fetch_ea_32(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
seteaw(ES);
|
|
break;
|
|
case 0x08: /*CS*/
|
|
seteaw(CS);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
seteaw(DS);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
seteaw(SS);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
seteaw(FS);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
seteaw(GS);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1);
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opMOV_l_seg_a16(uint32_t fetchdat)
|
|
{
|
|
fetch_ea_16(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = ES;
|
|
else
|
|
seteaw(ES);
|
|
break;
|
|
case 0x08: /*CS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = CS;
|
|
else
|
|
seteaw(CS);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = DS;
|
|
else
|
|
seteaw(DS);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = SS;
|
|
else
|
|
seteaw(SS);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = FS;
|
|
else
|
|
seteaw(FS);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = GS;
|
|
else
|
|
seteaw(GS);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0);
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opMOV_l_seg_a32(uint32_t fetchdat)
|
|
{
|
|
fetch_ea_32(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = ES;
|
|
else
|
|
seteaw(ES);
|
|
break;
|
|
case 0x08: /*CS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = CS;
|
|
else
|
|
seteaw(CS);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = DS;
|
|
else
|
|
seteaw(DS);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = SS;
|
|
else
|
|
seteaw(SS);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = FS;
|
|
else
|
|
seteaw(FS);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
if (cpu_mod == 3)
|
|
cpu_state.regs[cpu_rm].l = GS;
|
|
else
|
|
seteaw(GS);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1);
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opMOV_seg_w_a16(uint32_t fetchdat)
|
|
{
|
|
uint16_t new_seg;
|
|
|
|
fetch_ea_16(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
new_seg = geteaw();
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
loadseg(new_seg, &cpu_state.seg_es);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
loadseg(new_seg, &cpu_state.seg_ds);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
loadseg(new_seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.oldpc = cpu_state.pc;
|
|
cpu_state.op32 = use32;
|
|
cpu_state.ssegs = 0;
|
|
cpu_state.ea_seg = &cpu_state.seg_ds;
|
|
fetchdat = fastreadl(cs + cpu_state.pc);
|
|
cpu_state.pc++;
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
|
return 1;
|
|
case 0x20: /*FS*/
|
|
loadseg(new_seg, &cpu_state.seg_fs);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
loadseg(new_seg, &cpu_state.seg_gs);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0);
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opMOV_seg_w_a32(uint32_t fetchdat)
|
|
{
|
|
uint16_t new_seg;
|
|
|
|
fetch_ea_32(fetchdat);
|
|
if (cpu_mod != 3)
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
new_seg = geteaw();
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
loadseg(new_seg, &cpu_state.seg_es);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
loadseg(new_seg, &cpu_state.seg_ds);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
loadseg(new_seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.oldpc = cpu_state.pc;
|
|
cpu_state.op32 = use32;
|
|
cpu_state.ssegs = 0;
|
|
cpu_state.ea_seg = &cpu_state.seg_ds;
|
|
fetchdat = fastreadl(cs + cpu_state.pc);
|
|
cpu_state.pc++;
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
|
return 1;
|
|
case 0x20: /*FS*/
|
|
loadseg(new_seg, &cpu_state.seg_fs);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
loadseg(new_seg, &cpu_state.seg_gs);
|
|
break;
|
|
}
|
|
|
|
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
|
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1);
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opLDS_w_a16(uint32_t fetchdat)
|
|
{
|
|
uint16_t addr, seg;
|
|
|
|
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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ds);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].w = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0);
|
|
return 0;
|
|
}
|
|
static int
|
|
opLDS_w_a32(uint32_t fetchdat)
|
|
{
|
|
uint16_t addr, seg;
|
|
|
|
fetch_ea_32(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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ds);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].w = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1);
|
|
return 0;
|
|
}
|
|
static int
|
|
opLDS_l_a16(uint32_t fetchdat)
|
|
{
|
|
uint32_t addr;
|
|
uint16_t seg;
|
|
|
|
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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ds);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].l = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 0);
|
|
return 0;
|
|
}
|
|
static int
|
|
opLDS_l_a32(uint32_t fetchdat)
|
|
{
|
|
uint32_t addr;
|
|
uint16_t seg;
|
|
|
|
fetch_ea_32(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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ds);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].l = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 1);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
opLSS_w_a16(uint32_t fetchdat)
|
|
{
|
|
uint16_t addr, seg;
|
|
|
|
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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].w = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0);
|
|
return 1;
|
|
}
|
|
static int
|
|
opLSS_w_a32(uint32_t fetchdat)
|
|
{
|
|
uint16_t addr, seg;
|
|
|
|
fetch_ea_32(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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].w = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1);
|
|
return 1;
|
|
}
|
|
static int
|
|
opLSS_l_a16(uint32_t fetchdat)
|
|
{
|
|
uint32_t addr;
|
|
uint16_t seg;
|
|
|
|
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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].l = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0);
|
|
return 1;
|
|
}
|
|
static int
|
|
opLSS_l_a32(uint32_t fetchdat)
|
|
{
|
|
uint32_t addr;
|
|
uint16_t seg;
|
|
|
|
fetch_ea_32(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);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
loadseg(seg, &cpu_state.seg_ss);
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cpu_state.regs[cpu_reg].l = addr;
|
|
|
|
CLOCK_CYCLES(7);
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1);
|
|
return 1;
|
|
}
|
|
|
|
#define opLsel(name, sel) \
|
|
static int opL##name##_w_a16(uint32_t fetchdat) \
|
|
{ \
|
|
uint16_t addr, seg; \
|
|
\
|
|
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); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
loadseg(seg, &sel); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
cpu_state.regs[cpu_reg].w = addr; \
|
|
\
|
|
CLOCK_CYCLES(7); \
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
static int opL##name##_w_a32(uint32_t fetchdat) \
|
|
{ \
|
|
uint16_t addr, seg; \
|
|
\
|
|
fetch_ea_32(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); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
loadseg(seg, &sel); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
cpu_state.regs[cpu_reg].w = addr; \
|
|
\
|
|
CLOCK_CYCLES(7); \
|
|
PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
static int opL##name##_l_a16(uint32_t fetchdat) \
|
|
{ \
|
|
uint32_t addr; \
|
|
uint16_t seg; \
|
|
\
|
|
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); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
loadseg(seg, &sel); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
cpu_state.regs[cpu_reg].l = addr; \
|
|
\
|
|
CLOCK_CYCLES(7); \
|
|
PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 0); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
static int opL##name##_l_a32(uint32_t fetchdat) \
|
|
{ \
|
|
uint32_t addr; \
|
|
uint16_t seg; \
|
|
\
|
|
fetch_ea_32(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); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
loadseg(seg, &sel); \
|
|
if (cpu_state.abrt) \
|
|
return 1; \
|
|
cpu_state.regs[cpu_reg].l = addr; \
|
|
\
|
|
CLOCK_CYCLES(7); \
|
|
PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 1); \
|
|
return 0; \
|
|
}
|
|
|
|
// clang-format off
|
|
opLsel(ES, cpu_state.seg_es)
|
|
opLsel(FS, cpu_state.seg_fs)
|
|
opLsel(GS, cpu_state.seg_gs)
|
|
// clang-format on
|