/*Cyrix-only instructions*/
/*System Management Mode*/

#ifndef _X86_OPS_CYRIX_H_
#define _X86_OPS_CYRIX_H_
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:
                pclog("opSVDC: unknown rmdat %02x\n", rmdat);
                x86illegal();
        }
}
static int opSVDC_a16(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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);
                break;
        case 0x18: /*DS*/
                cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds);
                break;
        case 0x10: /*SS*/
                cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss);
                break;
        case 0x20: /*FS*/
                cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs);
                break;
        case 0x28: /*GS*/
                cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs);
                break;
        default:
                pclog("opRSDC: unknown rmdat %02x\n", rmdat);
                x86illegal();
        }
}
static int opRSDC_a16(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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) {
        if (cpu_cur_status & CPU_STATUS_SMM) {
                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(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM)
                fatal("opSMINT\n");
        else
                x86illegal();

        return 1;
}

static int opRDSHR_a16(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM)
                fatal("opRDSHR_a16\n");
        else
                x86illegal();

        return 1;
}
static int opRDSHR_a32(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM)
                fatal("opRDSHR_a32\n");
        else
                x86illegal();

        return 1;
}

static int opWRSHR_a16(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM)
                fatal("opWRSHR_a16\n");
        else
                x86illegal();

        return 1;
}
static int opWRSHR_a32(uint32_t fetchdat) {
        if (cpu_cur_status & CPU_STATUS_SMM)
                fatal("opWRSHR_a32\n");
        else
                x86illegal();

        return 1;
}

#endif /* _X86_OPS_CYRIX_H_ */
