/*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_ */
