From c0bc163eaf69e4d79c6ee352133ed32214ac6b30 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 8 Nov 2020 20:46:42 +0000 Subject: [PATCH] Implement Cyrix SMM mode. --- src/386_ops.h | 110 +++++++++++- src/codegen_ops_mmx_loadstore.c | 3 + src/cpu.c | 41 ++++- src/x86.h | 18 +- src/x86_ops.h | 2 + src/x86_ops_cyrix.h | 274 +++++++++++++++++++++++++++++ src/x86_ops_mmx_mov.h | 48 +++++- src/x86_ops_pmode.h | 6 +- src/x86seg.c | 293 ++++++++++++++++++++++---------- 9 files changed, 688 insertions(+), 107 deletions(-) create mode 100644 src/x86_ops_cyrix.h diff --git a/src/386_ops.h b/src/386_ops.h index 79ea171..d59132a 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -119,6 +119,7 @@ static int ILLEGAL(uint32_t fetchdat) #include "x86_ops_bit.h" #include "x86_ops_bitscan.h" #include "x86_ops_call.h" +#include "x86_ops_cyrix.h" #include "x86_ops_flag.h" #include "x86_ops_fpu.h" #include "x86_ops_inc_dec.h" @@ -638,7 +639,98 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(pentiummmx_0f)[1024] = +OpFn OP_TABLE(c6x86_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(pentiummmx_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -736,12 +828,12 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, @@ -758,12 +850,12 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, @@ -780,12 +872,12 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, @@ -802,12 +894,12 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c index ac591e8..a376f9b 100644 --- a/src/codegen_ops_mmx_loadstore.c +++ b/src/codegen_ops_mmx_loadstore.c @@ -38,6 +38,9 @@ uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t { int src_reg = (fetchdat >> 3) & 7; + if (cpu_iscyrix && (cpu_cur_status & CPU_STATUS_SMM)) + return 0; + uop_MMX_ENTER(ir); codegen_mark_code_present(block, cs+op_pc, 1); if ((fetchdat & 0xc0) == 0xc0) diff --git a/src/cpu.c b/src/cpu.c index fb9a042..e381931 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -787,7 +787,7 @@ void cpu_set() break; case CPU_Cx6x86: - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -2003,6 +2003,13 @@ void cpu_WRMSR() static int cyrix_addr; +#define CCR1_USE_SMI (1 << 1) +#define CCR1_SMAC (1 << 2) +#define CCR1_SM3 (1 << 7) + +#define CCR3_SMI_LOCK (1 << 0) +#define CCR3_NMI_EN (1 << 1) + void cyrix_write(uint16_t addr, uint8_t val, void *priv) { if (!(addr & 1)) @@ -2013,14 +2020,46 @@ void cyrix_write(uint16_t addr, uint8_t val, void *priv) ccr0 = val; break; case 0xc1: /*CCR1*/ + if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM)) + val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); ccr1 = val; break; case 0xc2: /*CCR2*/ ccr2 = val; break; case 0xc3: /*CCR3*/ + if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM)) + val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; ccr3 = val; break; + case 0xcd: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xce: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xcf: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); + if ((val & 0xf) == 0xf) + cyrix.arr[3].size = 1ull << 32; /*4 GB*/ + else if (val & 0xf) + cyrix.arr[3].size = 2048 << (val & 0xf); + else + cyrix.arr[3].size = 0; /*Disabled*/ + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xe8: /*CCR4*/ if ((ccr3 & 0xf0) == 0x10) { diff --git a/src/x86.h b/src/x86.h index 12125e4..f0f2238 100644 --- a/src/x86.h +++ b/src/x86.h @@ -39,7 +39,7 @@ typedef union typedef struct { uint32_t base; - uint32_t limit; + uint32_t limit, limit_raw; uint8_t access, access2; uint16_t seg; uint32_t limit_low, limit_high; @@ -325,4 +325,20 @@ void x86_smi_trigger(void); void x86_smi_enter(void); void x86_smi_leave(void); +void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg); +void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); + +#define SMHR_VALID (1 << 0) +#define SMHR_ADDR_MASK (0xfffffffc) + +struct +{ + struct + { + uint32_t base; + uint64_t size; + } arr[8]; + uint32_t smhr; +} cyrix; + #endif diff --git a/src/x86_ops.h b/src/x86_ops.h index 8cdd4e7..578b7cf 100644 --- a/src/x86_ops.h +++ b/src/x86_ops.h @@ -41,6 +41,7 @@ extern OpFn dynarec_ops_pentiummmx_0f[1024]; extern OpFn dynarec_ops_pentiumpro_0f[1024]; extern OpFn dynarec_ops_pentium2_0f[1024]; +extern OpFn dynarec_ops_c6x86_0f[1024]; extern OpFn dynarec_ops_c6x86mx_0f[1024]; extern OpFn dynarec_ops_fpu_d8_a16[32]; @@ -110,6 +111,7 @@ extern OpFn ops_pentiummmx_0f[1024]; extern OpFn ops_pentiumpro_0f[1024]; extern OpFn ops_pentium2_0f[1024]; +extern OpFn ops_c6x86_0f[1024]; extern OpFn ops_c6x86mx_0f[1024]; extern OpFn ops_fpu_d8_a16[32]; diff --git a/src/x86_ops_cyrix.h b/src/x86_ops_cyrix.h new file mode 100644 index 0000000..e6464ce --- /dev/null +++ b/src/x86_ops_cyrix.h @@ -0,0 +1,274 @@ +/*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: + 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; +} diff --git a/src/x86_ops_mmx_mov.h b/src/x86_ops_mmx_mov.h index 133d48d..548b6c4 100644 --- a/src/x86_ops_mmx_mov.h +++ b/src/x86_ops_mmx_mov.h @@ -50,7 +50,7 @@ static int opMOVD_l_mm_a32(uint32_t fetchdat) static int opMOVD_mm_l_a16(uint32_t fetchdat) { MMX_ENTER(); - + fetch_ea_16(fetchdat); if (cpu_mod == 3) { @@ -69,6 +69,52 @@ static int opMOVD_mm_l_a16(uint32_t fetchdat) static int opMOVD_mm_l_a32(uint32_t fetchdat) { MMX_ENTER(); + + fetch_ea_32(fetchdat); + if (cpu_mod == 3) + { + cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + return 0; +} + +/*Cyrix maps both MOVD and SMINT to the same opcode*/ +static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + return opSMINT(fetchdat); + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + if (cpu_mod == 3) + { + cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + return 0; +} +static int opMOVD_mm_l_a32_cx(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + return opSMINT(fetchdat); + + MMX_ENTER(); fetch_ea_32(fetchdat); if (cpu_mod == 3) diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h index a93cfa7..5ad244f 100644 --- a/src/x86_ops_pmode.h +++ b/src/x86_ops_pmode.h @@ -165,7 +165,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) int dpl, valid, granularity; uint32_t addr, base, limit; uint16_t desc, sel; - uint8_t access; + uint8_t access, access2; // pclog("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); switch (rmdat & 0x38) @@ -198,10 +198,12 @@ static int op0F00_common(uint32_t fetchdat, int ea32) limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); access = readmemb(0, addr + 5); + access2 = readmemb(0, addr + 6); granularity = readmemb(0, addr + 6) & 0x80; if (cpu_state.abrt) return 1; ldt.limit = limit; ldt.access = access; + ldt.access2 = access2; if (granularity) { ldt.limit <<= 12; @@ -226,6 +228,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); access = readmemb(0, addr + 5); + access2 = readmemb(0, addr + 6); granularity = readmemb(0, addr + 6) & 0x80; if (cpu_state.abrt) return 1; access |= 2; @@ -234,6 +237,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) tr.seg = sel; tr.limit = limit; tr.access = access; + tr.access2 = access2; if (granularity) { tr.limit <<= 12; diff --git a/src/x86seg.c b/src/x86seg.c index 669001e..6703f8f 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -219,6 +219,7 @@ static void set_use32(int u) static void do_seg_load(x86seg *s, uint16_t *segdat) { s->limit = segdat[0] | ((segdat[3] & 0xF) << 16); + s->limit_raw = s->limit; if (segdat[3] & 0x80) s->limit = (s->limit << 12) | 0xFFF; s->base = segdat[1] | ((segdat[2] & 0xFF) << 16); @@ -2996,6 +2997,51 @@ static void smi_load_smi_selector(x86seg *seg) seg->access2 = 0; } +void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg) +{ + writememl(0, addr, (seg->limit_raw & 0xffff) | (seg->base << 16)); + writememl(0, addr+4, ((seg->base >> 16) & 0xff) | + (seg->access << 8) | + (seg->limit_raw & 0xf0000) | + (seg->access2 << 16) | + (seg->base & 0xff000000)); +} + +void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg) +{ + uint16_t segdat[4], selector; + + segdat[0] = readmemw(0, addr); + segdat[1] = readmemw(0, addr+2); + segdat[2] = readmemw(0, addr+4); + segdat[3] = readmemw(0, addr+6); + selector = readmemw(0, addr+8); + + if (!cpu_state.abrt) + { + do_seg_load(seg, segdat); + seg->seg = selector; + seg->checked = 0; + if (seg == &cpu_state.seg_ds) + { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + codegen_flat_ds = 0; + } + if (seg == &cpu_state.seg_ss) + { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + set_stack32((segdat[3] & 0x40) ? 1 : 0); + codegen_flat_ss = 0; + } + } +} + void x86_smi_enter(void) { uint32_t old_cr0 = cr0; @@ -3007,63 +3053,102 @@ void x86_smi_enter(void) cpu_386_flags_rebuild(); cpl_override = 1; cr0 = 0; /*Disable MMU*/ - writememl(0, cpu_state.smbase + 0x8000 + 0x7ffc, old_cr0); - writememl(0, cpu_state.smbase + 0x8000 + 0x7ff8, cr3); - writememl(0, cpu_state.smbase + 0x8000 + 0x7ff4, cpu_state.flags | (cpu_state.eflags << 16)); - writememl(0, cpu_state.smbase + 0x8000 + 0x7ff0, cpu_state.pc); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fec, EDI); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fe8, ESI); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fe4, EBP); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fe0, ESP); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fdc, EBX); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fd8, EDX); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fd4, ECX); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fd0, EAX); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fcc, dr[6]); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fc8, dr[7]); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fc4, tr.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fc0, ldt.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fbc, cpu_state.seg_gs.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fb8, cpu_state.seg_fs.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fb4, cpu_state.seg_ds.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fb0, cpu_state.seg_ss.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fac, cpu_state.seg_cs.seg); - writememl(0, cpu_state.smbase + 0x8000 + 0x7fa8, cpu_state.seg_es.seg); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); - smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); - writememl(0, cpu_state.smbase + 0x8000 + 0x7f28, cr4); - writememl(0, cpu_state.smbase + 0x8000 + 0x7ef8, cpu_state.smbase); - writememl(0, cpu_state.smbase + 0x8000 + 0x7efc, 0x00020000); - cpl_override = 0; - cpu_cur_status = CPU_STATUS_SMM; - cpu_state.flags = 2; - cpu_state.eflags = 0; - cpu_state.pc = 0x8000; - cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31)); - dr[7] = 0x400; - smi_load_smi_selector(&cpu_state.seg_ds); - smi_load_smi_selector(&cpu_state.seg_es); - smi_load_smi_selector(&cpu_state.seg_fs); - smi_load_smi_selector(&cpu_state.seg_gs); - smi_load_smi_selector(&cpu_state.seg_ss); - cpu_state.seg_cs.seg = 0x3000; - cpu_state.seg_cs.base = cpu_state.smbase; - cpu_state.seg_cs.limit = 0xffffffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.access = (0 << 5) | 2; + if (cpu_iscyrix) + { + uint32_t base; - use32 = 0; - stack32 = 0; + if (!cyrix.smhr & SMHR_VALID) + cyrix.smhr = (cyrix.arr[3].base + cyrix.arr[3].size) | SMHR_VALID; + base = cyrix.smhr & SMHR_ADDR_MASK; + + writememl(0, base-4, dr[7]); + writememl(0, base-8, cpu_state.flags | (cpu_state.eflags << 16)); + writememl(0, base-0xc, old_cr0); + writememl(0, base-0x10, cpu_state.oldpc); + writememl(0, base-0x14, cpu_state.pc); + writememl(0, base-0x18, CS | (CPL << 21)); + cyrix_write_seg_descriptor(base-0x20, &cpu_state.seg_cs); + writememl(0, base-0x24, 0); + + cpl_override = 0; + + cpu_cur_status = CPU_STATUS_SMM; + cpu_state.flags = 2; + cpu_state.eflags = 0; + cpu_state.pc = 0; + cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31)); + dr[7] = 0x400; + cpu_state.seg_cs.seg = cyrix.arr[3].base >> 4; /*Guess*/ + cpu_state.seg_cs.base = cyrix.arr[3].base; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = (0 << 5) | 2; + + use32 = 0; + stack32 = 0; + } + else + { + writememl(0, cpu_state.smbase + 0x8000 + 0x7ffc, old_cr0); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff8, cr3); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff4, cpu_state.flags | (cpu_state.eflags << 16)); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff0, cpu_state.pc); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fec, EDI); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe8, ESI); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe4, EBP); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe0, ESP); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fdc, EBX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd8, EDX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd4, ECX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd0, EAX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fcc, dr[6]); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc8, dr[7]); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc4, tr.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc0, ldt.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fbc, cpu_state.seg_gs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb8, cpu_state.seg_fs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb4, cpu_state.seg_ds.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb0, cpu_state.seg_ss.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fac, cpu_state.seg_cs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fa8, cpu_state.seg_es.seg); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); + writememl(0, cpu_state.smbase + 0x8000 + 0x7f28, cr4); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ef8, cpu_state.smbase); + writememl(0, cpu_state.smbase + 0x8000 + 0x7efc, 0x00020000); + cpl_override = 0; + + cpu_cur_status = CPU_STATUS_SMM; + cpu_state.flags = 2; + cpu_state.eflags = 0; + cpu_state.pc = 0x8000; + cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31)); + dr[7] = 0x400; + smi_load_smi_selector(&cpu_state.seg_ds); + smi_load_smi_selector(&cpu_state.seg_es); + smi_load_smi_selector(&cpu_state.seg_fs); + smi_load_smi_selector(&cpu_state.seg_gs); + smi_load_smi_selector(&cpu_state.seg_ss); + cpu_state.seg_cs.seg = 0x3000; + cpu_state.seg_cs.base = cpu_state.smbase; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = (0 << 5) | 2; + + use32 = 0; + stack32 = 0; + } // pclog("x86_smi_enter\n"); } @@ -3073,47 +3158,67 @@ void x86_smi_leave(void) uint32_t temp; uint32_t new_cr0; - cpl_override = 1; - new_cr0 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ffc); - cr3 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff8); - temp = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff4); - cpu_state.flags = temp & 0xffff; - cpu_state.eflags = temp >> 16; - cpu_state.pc = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff0); - EDI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fec); - ESI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe8); - EBP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe4); - ESP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe0); - EBX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fdc); - EDX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd8); - ECX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd4); - EAX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd0); - dr[6] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fcc); - dr[7] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc8); - tr.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc4); - ldt.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc0); - cpu_state.seg_gs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fbc); - cpu_state.seg_fs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb8); - cpu_state.seg_ds.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb4); - cpu_state.seg_ss.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb0); - cpu_state.seg_cs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fac); - cpu_state.seg_es.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fa8); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); - smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); - cr4 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7f28); - cpu_state.smbase = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ef8); - cpl_override = 0; + if (cpu_iscyrix) + { + uint32_t base = cyrix.smhr & SMHR_ADDR_MASK; - cr0 = new_cr0; + cpl_override = 1; + dr[7] = readmeml(0, base-4); + temp = readmeml(0, base-8); + cpu_state.flags = temp & 0xffff; + cpu_state.eflags = temp >> 16; + new_cr0 = readmeml(0, base-0xc); + cpu_state.pc = readmeml(0, base-0x14); + cyrix_load_seg_descriptor(base-0x20, &cpu_state.seg_cs); + cpl_override = 0; + cr0 = new_cr0; + } + else + { + cpl_override = 1; + new_cr0 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ffc); + cr3 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff8); + temp = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff4); + cpu_state.flags = temp & 0xffff; + cpu_state.eflags = temp >> 16; + cpu_state.pc = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff0); + EDI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fec); + ESI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe8); + EBP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe4); + ESP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe0); + EBX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fdc); + EDX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd8); + ECX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd4); + EAX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd0); + dr[6] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fcc); + dr[7] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc8); + tr.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc4); + ldt.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc0); + cpu_state.seg_gs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fbc); + cpu_state.seg_fs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb8); + cpu_state.seg_ds.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb4); + cpu_state.seg_ss.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb0); + cpu_state.seg_cs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fac); + cpu_state.seg_es.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fa8); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); + cr4 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7f28); + cpu_state.smbase = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ef8); + cpl_override = 0; + + cr0 = new_cr0; + } + + cpu_386_flags_extract(); cpu_cur_status = 0; use32 = stack32 = 0; if (cr0 & 1)