427 lines
13 KiB
C
427 lines
13 KiB
C
/*Cyrix-only instructions*/
|
|
/*System Management Mode*/
|
|
static void
|
|
opSVDC_common(uint32_t fetchdat)
|
|
{
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, ES);
|
|
break;
|
|
case 0x08: /*CS*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_cs);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, CS);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, DS);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, SS);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, FS);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, GS);
|
|
break;
|
|
default:
|
|
x86illegal();
|
|
}
|
|
}
|
|
static int
|
|
opSVDC_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
opSVDC_common(fetchdat);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opSVDC_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
opSVDC_common(fetchdat);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static void
|
|
opRSDC_common(uint32_t fetchdat)
|
|
{
|
|
switch (rmdat & 0x38) {
|
|
case 0x00: /*ES*/
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es);
|
|
ES = readmemw(0, easeg + cpu_state.eaaddr + 8);
|
|
break;
|
|
case 0x18: /*DS*/
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds);
|
|
DS = readmemw(0, easeg + cpu_state.eaaddr + 8);
|
|
break;
|
|
case 0x10: /*SS*/
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss);
|
|
SS = readmemw(0, easeg + cpu_state.eaaddr + 8);
|
|
break;
|
|
case 0x20: /*FS*/
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs);
|
|
FS = readmemw(0, easeg + cpu_state.eaaddr + 8);
|
|
break;
|
|
case 0x28: /*GS*/
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs);
|
|
GS = readmemw(0, easeg + cpu_state.eaaddr + 8);
|
|
break;
|
|
default:
|
|
x86illegal();
|
|
}
|
|
}
|
|
static int
|
|
opRSDC_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
opRSDC_common(fetchdat);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opRSDC_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
opRSDC_common(fetchdat);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opSVLDT_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, ldt.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opSVLDT_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, ldt.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opRSLDT_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opRSLDT_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opSVTS_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opSVTS_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opRSTS_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
static int
|
|
opRSTS_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
|
|
writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg);
|
|
} else
|
|
x86illegal();
|
|
|
|
return cpu_state.abrt;
|
|
}
|
|
|
|
static int
|
|
opSMINT(UNUSED(uint32_t fetchdat))
|
|
{
|
|
uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) &&
|
|
(cyrix.arr[3].size > 0);
|
|
|
|
if (in_smm)
|
|
fatal("opSMINT\n");
|
|
else if (ccr1_check) {
|
|
is_smint = 1;
|
|
enter_smm(0);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
opRDSHR_a16(UNUSED(uint32_t fetchdat))
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
if (cpu_mod == 3) {
|
|
cpu_state.regs[cpu_rm].l = cyrix.smhr;
|
|
CLOCK_CYCLES(timing_rr);
|
|
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0);
|
|
} else {
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
seteal(cyrix.smhr);
|
|
CLOCK_CYCLES(is486 ? 1 : 2);
|
|
PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 0);
|
|
}
|
|
return cpu_state.abrt;
|
|
} else
|
|
x86illegal();
|
|
|
|
return 1;
|
|
}
|
|
static int
|
|
opRDSHR_a32(UNUSED(uint32_t fetchdat))
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
if (cpu_mod == 3) {
|
|
cpu_state.regs[cpu_rm].l = cyrix.smhr;
|
|
CLOCK_CYCLES(timing_rr);
|
|
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1);
|
|
} else {
|
|
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
|
seteal(cyrix.smhr);
|
|
CLOCK_CYCLES(is486 ? 1 : 2);
|
|
PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 1);
|
|
}
|
|
return cpu_state.abrt;
|
|
} else
|
|
x86illegal();
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
opWRSHR_a16(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_16(fetchdat);
|
|
if (cpu_mod == 3) {
|
|
cyrix.smhr = cpu_state.regs[cpu_rm].l;
|
|
CLOCK_CYCLES(timing_rr);
|
|
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0);
|
|
} else {
|
|
uint32_t temp;
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
|
|
temp = geteal();
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cyrix.smhr = temp;
|
|
CLOCK_CYCLES(is486 ? 1 : 4);
|
|
PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 0);
|
|
}
|
|
return 0;
|
|
} else
|
|
x86illegal();
|
|
|
|
return 1;
|
|
}
|
|
static int
|
|
opWRSHR_a32(uint32_t fetchdat)
|
|
{
|
|
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
|
|
(CCR1_USE_SMI | CCR1_SM3)) &&
|
|
((ccr1 & CCR1_SMAC) || in_smm) &&
|
|
(cyrix.arr[3].size > 0) &&
|
|
(CPL == 0);
|
|
|
|
if (ins_check) {
|
|
fetch_ea_32(fetchdat);
|
|
if (cpu_mod == 3) {
|
|
cyrix.smhr = cpu_state.regs[cpu_rm].l;
|
|
CLOCK_CYCLES(timing_rr);
|
|
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1);
|
|
} else {
|
|
uint32_t temp;
|
|
SEG_CHECK_READ(cpu_state.ea_seg);
|
|
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
|
|
temp = geteal();
|
|
if (cpu_state.abrt)
|
|
return 1;
|
|
cyrix.smhr = temp;
|
|
CLOCK_CYCLES(is486 ? 1 : 4);
|
|
PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 1);
|
|
}
|
|
return 0;
|
|
} else
|
|
x86illegal();
|
|
|
|
return 1;
|
|
}
|