From de38e289c9262cb055095f23bca37a57ee0afb63 Mon Sep 17 00:00:00 2001 From: cracyc Date: Sun, 23 Jun 2013 17:01:23 +0000 Subject: [PATCH] i386: preliminary cpu-side smi support (nw) --- src/emu/cpu/i386/i386.c | 143 +++++++++++++++++++++++++++++++++++- src/emu/cpu/i386/i386.h | 5 ++ src/emu/cpu/i386/i386ops.c | 6 -- src/emu/cpu/i386/i386ops.h | 2 +- src/emu/cpu/i386/i386priv.h | 76 +++++++++++++++++++ src/emu/cpu/i386/pentops.c | 92 +++++++++++++++++++++++ 6 files changed, 316 insertions(+), 8 deletions(-) diff --git a/src/emu/cpu/i386/i386.c b/src/emu/cpu/i386/i386.c index 20a8ca93558..38c367cf2cc 100644 --- a/src/emu/cpu/i386/i386.c +++ b/src/emu/cpu/i386/i386.c @@ -136,7 +136,7 @@ static void i386_load_segment_descriptor(i386_state *cpustate, int segment ) { cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; cpustate->sreg[segment].limit = 0xffff; - cpustate->sreg[segment].flags = (segment == CS) ? 0x009a : 0x0092; + cpustate->sreg[segment].flags = (segment == CS) ? 0x00fb : 0x00f3; cpustate->sreg[segment].d = 0; cpustate->sreg[segment].valid = true; } @@ -3069,7 +3069,18 @@ static void i386_common_init(legacy_cpu_device *device, device_irq_acknowledge_c device->save_item(NAME(cpustate->irq_state)); device->save_item(NAME(cpustate->performed_intersegment_jump)); device->save_item(NAME(cpustate->mxcsr)); + device->save_item(NAME(cpustate->smm)); + device->save_item(NAME(cpustate->nmi_masked)); + device->save_item(NAME(cpustate->nmi_latched)); + device->save_item(NAME(cpustate->smbase)); device->machine().save().register_postload(save_prepost_delegate(FUNC(i386_postload), cpustate)); + + i386_interface *intf = (i386_interface *) device->static_config(); + + if (intf != NULL) + cpustate->smiact.resolve(intf->smiact, *device); + else + memset(&cpustate->smiact, 0, sizeof(cpustate->smiact)); } CPU_INIT( i386 ) @@ -3159,6 +3170,9 @@ static CPU_RESET( i386 ) cpustate->idtr.base = 0; cpustate->idtr.limit = 0x3ff; + cpustate->smm = false; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; cpustate->a20_mask = ~0; @@ -3183,6 +3197,94 @@ static CPU_RESET( i386 ) CHANGE_PC(cpustate,cpustate->eip); } +static void pentium_smi(i386_state *cpustate) +{ + UINT32 smram_state = cpustate->smbase + 0xfe00; + UINT32 old_cr0 = cpustate->cr[0]; + UINT32 old_flags = get_flags(cpustate); + + if(cpustate->smm) + return; // TODO: latch + + cpustate->cr[0] &= ~(0x8000000d); + set_flags(cpustate, 2); + if(!cpustate->smiact.isnull()) + cpustate->smiact(true); + cpustate->smm = true; + + // save state + WRITE32(cpustate, cpustate->cr[4], smram_state+SMRAM_IP5_CR4); + WRITE32(cpustate, cpustate->sreg[ES].limit, smram_state+SMRAM_IP5_ESLIM); + WRITE32(cpustate, cpustate->sreg[ES].base, smram_state+SMRAM_IP5_ESBASE); + WRITE32(cpustate, cpustate->sreg[ES].flags, smram_state+SMRAM_IP5_ESACC); + WRITE32(cpustate, cpustate->sreg[CS].limit, smram_state+SMRAM_IP5_CSLIM); + WRITE32(cpustate, cpustate->sreg[CS].base, smram_state+SMRAM_IP5_CSBASE); + WRITE32(cpustate, cpustate->sreg[CS].flags, smram_state+SMRAM_IP5_CSACC); + WRITE32(cpustate, cpustate->sreg[SS].limit, smram_state+SMRAM_IP5_SSLIM); + WRITE32(cpustate, cpustate->sreg[SS].base, smram_state+SMRAM_IP5_SSBASE); + WRITE32(cpustate, cpustate->sreg[SS].flags, smram_state+SMRAM_IP5_SSACC); + WRITE32(cpustate, cpustate->sreg[DS].limit, smram_state+SMRAM_IP5_DSLIM); + WRITE32(cpustate, cpustate->sreg[DS].base, smram_state+SMRAM_IP5_DSBASE); + WRITE32(cpustate, cpustate->sreg[DS].flags, smram_state+SMRAM_IP5_DSACC); + WRITE32(cpustate, cpustate->sreg[FS].limit, smram_state+SMRAM_IP5_FSLIM); + WRITE32(cpustate, cpustate->sreg[FS].base, smram_state+SMRAM_IP5_FSBASE); + WRITE32(cpustate, cpustate->sreg[FS].flags, smram_state+SMRAM_IP5_FSACC); + WRITE32(cpustate, cpustate->sreg[GS].limit, smram_state+SMRAM_IP5_GSLIM); + WRITE32(cpustate, cpustate->sreg[GS].base, smram_state+SMRAM_IP5_GSBASE); + WRITE32(cpustate, cpustate->sreg[GS].flags, smram_state+SMRAM_IP5_GSACC); + WRITE32(cpustate, cpustate->ldtr.flags, smram_state+SMRAM_IP5_LDTACC); + WRITE32(cpustate, cpustate->ldtr.limit, smram_state+SMRAM_IP5_LDTLIM); + WRITE32(cpustate, cpustate->ldtr.base, smram_state+SMRAM_IP5_LDTBASE); + WRITE32(cpustate, cpustate->gdtr.limit, smram_state+SMRAM_IP5_GDTLIM); + WRITE32(cpustate, cpustate->gdtr.base, smram_state+SMRAM_IP5_GDTBASE); + WRITE32(cpustate, cpustate->idtr.limit, smram_state+SMRAM_IP5_IDTLIM); + WRITE32(cpustate, cpustate->idtr.base, smram_state+SMRAM_IP5_IDTBASE); + WRITE32(cpustate, cpustate->task.limit, smram_state+SMRAM_IP5_TRLIM); + WRITE32(cpustate, cpustate->task.base, smram_state+SMRAM_IP5_TRBASE); + WRITE32(cpustate, cpustate->task.flags, smram_state+SMRAM_IP5_TRACC); + + WRITE32(cpustate, cpustate->sreg[ES].selector, smram_state+SMRAM_ES); + WRITE32(cpustate, cpustate->sreg[CS].selector, smram_state+SMRAM_CS); + WRITE32(cpustate, cpustate->sreg[SS].selector, smram_state+SMRAM_SS); + WRITE32(cpustate, cpustate->sreg[DS].selector, smram_state+SMRAM_DS); + WRITE32(cpustate, cpustate->sreg[FS].selector, smram_state+SMRAM_FS); + WRITE32(cpustate, cpustate->sreg[GS].selector, smram_state+SMRAM_GS); + WRITE32(cpustate, cpustate->ldtr.segment, smram_state+SMRAM_LDTR); + WRITE32(cpustate, cpustate->task.segment, smram_state+SMRAM_TR); + + WRITE32(cpustate, cpustate->dr[7], smram_state+SMRAM_DR7); + WRITE32(cpustate, cpustate->dr[6], smram_state+SMRAM_DR6); + WRITE32(cpustate, REG32(EAX), smram_state+SMRAM_EAX); + WRITE32(cpustate, REG32(ECX), smram_state+SMRAM_ECX); + WRITE32(cpustate, REG32(EDX), smram_state+SMRAM_EDX); + WRITE32(cpustate, REG32(EBX), smram_state+SMRAM_EBX); + WRITE32(cpustate, REG32(ESP), smram_state+SMRAM_ESP); + WRITE32(cpustate, REG32(EBP), smram_state+SMRAM_EBP); + WRITE32(cpustate, REG32(ESI), smram_state+SMRAM_ESI); + WRITE32(cpustate, REG32(EDI), smram_state+SMRAM_EDI); + WRITE32(cpustate, cpustate->eip, smram_state+SMRAM_EIP); + WRITE32(cpustate, old_flags, smram_state+SMRAM_EAX); + WRITE32(cpustate, cpustate->cr[3], smram_state+SMRAM_CR3); + WRITE32(cpustate, old_cr0, smram_state+SMRAM_CR0); + + cpustate->sreg[DS].selector = cpustate->sreg[ES].selector = cpustate->sreg[FS].selector = cpustate->sreg[GS].selector = cpustate->sreg[SS].selector = 0; + cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; + cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffffffff; + cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x8093; + cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true; + cpustate->sreg[CS].selector = 0x3000; // pentium only, ppro sel = smbase >> 4 + cpustate->sreg[CS].base = cpustate->smbase; + cpustate->sreg[CS].limit = 0xffffffff; + cpustate->sreg[CS].flags = 0x809b; + cpustate->sreg[CS].valid = true; + cpustate->cr[4] = 0; + cpustate->dr[7] = 0x400; + cpustate->eip = 0x8000; + + cpustate->nmi_masked = true; + CHANGE_PC(cpustate,cpustate->eip); +} + static void i386_set_irq_line(i386_state *cpustate,int irqline, int state) { if (state != CLEAR_LINE && cpustate->halted) @@ -3193,6 +3295,11 @@ static void i386_set_irq_line(i386_state *cpustate,int irqline, int state) if ( irqline == INPUT_LINE_NMI ) { /* NMI (I do not think that this is 100% right) */ + if(cpustate->nmi_masked) + { + cpustate->nmi_latched = true; + return; + } if ( state ) i386_trap(cpustate,2, 1, 0); } @@ -3669,6 +3776,9 @@ static CPU_RESET( i486 ) cpustate->eflags = 0; cpustate->eflags_mask = 0x00077fd7; cpustate->eip = 0xfff0; + cpustate->smm = false; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -3781,6 +3891,10 @@ static CPU_RESET( pentium ) cpustate->eflags_mask = 0x003f7fd7; cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -3823,6 +3937,10 @@ static CPU_SET_INFO( pentium ) i386_state *cpustate = get_safe_token(device); switch (state) { + case CPUINFO_INT_INPUT_STATE+INPUT_LINE_SMI: + if(state) + pentium_smi(cpustate); + break; case CPUINFO_INT_REGISTER + X87_CTRL: cpustate->x87_cw = info->i; break; case CPUINFO_INT_REGISTER + X87_STATUS: cpustate->x87_sw = info->i; break; case CPUINFO_INT_REGISTER + X87_TAG: cpustate->x87_tw = info->i; break; @@ -3907,6 +4025,9 @@ static CPU_RESET( mediagx ) cpustate->eflags = 0x00200000; cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; + cpustate->smm = false; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -4027,6 +4148,10 @@ static CPU_RESET( pentium_pro ) cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -4127,6 +4252,10 @@ static CPU_RESET( pentium_mmx ) cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -4227,6 +4356,10 @@ static CPU_RESET( pentium2 ) cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -4327,6 +4460,10 @@ static CPU_RESET( pentium3 ) cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); @@ -4429,6 +4566,10 @@ static CPU_RESET( pentium4 ) cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ cpustate->eip = 0xfff0; cpustate->mxcsr = 0x1f80; + cpustate->smm = false; + cpustate->smbase = 0x30000; + cpustate->nmi_masked = false; + cpustate->nmi_latched = false; x87_reset(cpustate); diff --git a/src/emu/cpu/i386/i386.h b/src/emu/cpu/i386/i386.h index e979bf764a8..d2a1a87bbd2 100644 --- a/src/emu/cpu/i386/i386.h +++ b/src/emu/cpu/i386/i386.h @@ -4,7 +4,12 @@ #define __I386INTF_H__ #define INPUT_LINE_A20 1 +#define INPUT_LINE_SMI 2 +struct i386_interface +{ + devcb_write_line smiact; +}; // mingw has this defined for 32-bit compiles #undef i386 diff --git a/src/emu/cpu/i386/i386ops.c b/src/emu/cpu/i386/i386ops.c index b3caea8ccb1..5079bb743a1 100644 --- a/src/emu/cpu/i386/i386ops.c +++ b/src/emu/cpu/i386/i386ops.c @@ -2498,12 +2498,6 @@ static void I386OP(loadall)(i386_state *cpustate) // Opcode 0x0f 0x07 (0x0 fatalerror("i386: LOADALL unimplemented at %08X\n", cpustate->pc - 1); } -static void I386OP(rsm)(i386_state *cpustate) -{ - logerror("i386: Invalid RSM outside SMM at %08X\n", cpustate->pc - 1); - i386_trap(cpustate, 6, 0, 0); -} - static void I386OP(invalid)(i386_state *cpustate) { report_invalid_opcode(cpustate); diff --git a/src/emu/cpu/i386/i386ops.h b/src/emu/cpu/i386/i386ops.h index 9cda87acf30..35401c9b857 100644 --- a/src/emu/cpu/i386/i386ops.h +++ b/src/emu/cpu/i386/i386ops.h @@ -354,7 +354,7 @@ static const X86_OPCODE x86_opcode_table[] = { 0xA5, OP_2BYTE|OP_I386, I386OP(shld16_cl), I386OP(shld32_cl), }, { 0xA8, OP_2BYTE|OP_I386, I386OP(push_gs16), I386OP(push_gs32), }, { 0xA9, OP_2BYTE|OP_I386, I386OP(pop_gs16), I386OP(pop_gs32), }, - { 0xAA, OP_2BYTE|OP_I386, I386OP(rsm), I386OP(rsm), }, + { 0xAA, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rsm), PENTIUMOP(rsm), }, { 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), }, { 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), }, { 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), }, diff --git a/src/emu/cpu/i386/i386priv.h b/src/emu/cpu/i386/i386priv.h index 13d90af6ac9..5874f40070f 100644 --- a/src/emu/cpu/i386/i386priv.h +++ b/src/emu/cpu/i386/i386priv.h @@ -170,6 +170,76 @@ enum MMX_MM7=X87_ST7 }; +enum smram +{ + SMRAM_SMBASE = 0xF8, + SMRAM_SMREV = 0xFC, + SMRAM_IORSRT = 0x100, + SMRAM_AHALT = 0x102, + SMRAM_IOEDI = 0x104, + SMRAM_IOECX = 0x108, + SMRAM_IOESI = 0x10C, + + SMRAM_ES = 0x1A8, + SMRAM_CS = 0x1AC, + SMRAM_SS = 0x1B0, + SMRAM_DS = 0x1B4, + SMRAM_FS = 0x1B8, + SMRAM_GS = 0x1BC, + SMRAM_LDTR = 0x1C0, + SMRAM_TR = 0x1C4, + SMRAM_DR7 = 0x1C8, + SMRAM_DR6 = 0x1CC, + SMRAM_EAX = 0x1D0, + SMRAM_ECX = 0x1D4, + SMRAM_EDX = 0x1D8, + SMRAM_EBX = 0x1DC, + SMRAM_ESP = 0x1E0, + SMRAM_EBP = 0x1E4, + SMRAM_ESI = 0x1E8, + SMRAM_EDI = 0x1EC, + SMRAM_EIP = 0x1F0, + SMRAM_EFLAGS = 0x1F4, + SMRAM_CR3 = 0x1F8, + SMRAM_CR0 = 0x1FC, +}; + +enum smram_intel_p5 +{ + SMRAM_IP5_IOEIP = 0x110, + SMRAM_IP5_CR4 = 0x128, + SMRAM_IP5_ESLIM = 0x130, + SMRAM_IP5_ESBASE = 0x134, + SMRAM_IP5_ESACC = 0x138, + SMRAM_IP5_CSLIM = 0x13C, + SMRAM_IP5_CSBASE = 0x140, + SMRAM_IP5_CSACC = 0x144, + SMRAM_IP5_SSLIM = 0x148, + SMRAM_IP5_SSBASE = 0x14C, + SMRAM_IP5_SSACC = 0x150, + SMRAM_IP5_DSLIM = 0x154, + SMRAM_IP5_DSBASE = 0x158, + SMRAM_IP5_DSACC = 0x15C, + SMRAM_IP5_FSLIM = 0x160, + SMRAM_IP5_FSBASE = 0x164, + SMRAM_IP5_FSACC = 0x168, + SMRAM_IP5_GSLIM = 0x16C, + SMRAM_IP5_GSBASE = 0x170, + SMRAM_IP5_GSACC = 0x174, + SMRAM_IP5_LDTLIM = 0x178, + SMRAM_IP5_LDTBASE = 0x17C, + SMRAM_IP5_LDTACC = 0x180, + SMRAM_IP5_GDTLIM = 0x184, + SMRAM_IP5_GDTBASE = 0x188, + SMRAM_IP5_GDTACC = 0x18C, + SMRAM_IP5_IDTLIM = 0x190, + SMRAM_IP5_IDTBASE = 0x194, + SMRAM_IP5_IDTACC = 0x198, + SMRAM_IP5_TRLIM = 0x19C, + SMRAM_IP5_TRBASE = 0x1A0, + SMRAM_IP5_TRACC = 0x1A4, +}; + /* Protected mode exceptions */ #define FAULT_UD 6 // Invalid Opcode #define FAULT_NM 7 // Coprocessor not available @@ -363,6 +433,12 @@ struct i386_state vtlb_state *vtlb; + bool smm; + bool nmi_masked; + bool nmi_latched; + UINT32 smbase; + devcb_resolved_write_line smiact; + // bytes in current opcode, debug only #ifdef DEBUG_MISSING_OPCODE UINT8 opcode_bytes[16]; diff --git a/src/emu/cpu/i386/pentops.c b/src/emu/cpu/i386/pentops.c index 1f2dea8ee89..426c15ee665 100644 --- a/src/emu/cpu/i386/pentops.c +++ b/src/emu/cpu/i386/pentops.c @@ -144,6 +144,98 @@ static void PENTIUMOP(ud2)(i386_state *cpustate) // Opcode 0x0f 0b i386_trap(cpustate, 6, 0, 0); } +static void PENTIUMOP(rsm)(i386_state *cpustate) +{ + UINT32 smram_state = cpustate->smbase + 0xfe00; + if(!cpustate->smm) + { + logerror("i386: Invalid RSM outside SMM at %08X\n", cpustate->pc - 1); + i386_trap(cpustate, 6, 0, 0); + return; + } + + // load state, no sanity checks anywhere + cpustate->smbase = READ32(cpustate, smram_state+SMRAM_SMBASE); + cpustate->cr[4] = READ32(cpustate, smram_state+SMRAM_IP5_CR4); + cpustate->sreg[ES].limit = READ32(cpustate, smram_state+SMRAM_IP5_ESLIM); + cpustate->sreg[ES].base = READ32(cpustate, smram_state+SMRAM_IP5_ESBASE); + cpustate->sreg[ES].flags = READ32(cpustate, smram_state+SMRAM_IP5_ESACC); + cpustate->sreg[CS].limit = READ32(cpustate, smram_state+SMRAM_IP5_CSLIM); + cpustate->sreg[CS].base = READ32(cpustate, smram_state+SMRAM_IP5_CSBASE); + cpustate->sreg[CS].flags = READ32(cpustate, smram_state+SMRAM_IP5_CSACC); + cpustate->sreg[SS].limit = READ32(cpustate, smram_state+SMRAM_IP5_SSLIM); + cpustate->sreg[SS].base = READ32(cpustate, smram_state+SMRAM_IP5_SSBASE); + cpustate->sreg[SS].flags = READ32(cpustate, smram_state+SMRAM_IP5_SSACC); + cpustate->sreg[DS].limit = READ32(cpustate, smram_state+SMRAM_IP5_DSLIM); + cpustate->sreg[DS].base = READ32(cpustate, smram_state+SMRAM_IP5_DSBASE); + cpustate->sreg[DS].flags = READ32(cpustate, smram_state+SMRAM_IP5_DSACC); + cpustate->sreg[FS].limit = READ32(cpustate, smram_state+SMRAM_IP5_FSLIM); + cpustate->sreg[FS].base = READ32(cpustate, smram_state+SMRAM_IP5_FSBASE); + cpustate->sreg[FS].flags = READ32(cpustate, smram_state+SMRAM_IP5_FSACC); + cpustate->sreg[GS].limit = READ32(cpustate, smram_state+SMRAM_IP5_GSLIM); + cpustate->sreg[GS].base = READ32(cpustate, smram_state+SMRAM_IP5_GSBASE); + cpustate->sreg[GS].flags = READ32(cpustate, smram_state+SMRAM_IP5_GSACC); + cpustate->ldtr.flags = READ32(cpustate, smram_state+SMRAM_IP5_LDTACC); + cpustate->ldtr.limit = READ32(cpustate, smram_state+SMRAM_IP5_LDTLIM); + cpustate->ldtr.base = READ32(cpustate, smram_state+SMRAM_IP5_LDTBASE); + cpustate->gdtr.limit = READ32(cpustate, smram_state+SMRAM_IP5_GDTLIM); + cpustate->gdtr.base = READ32(cpustate, smram_state+SMRAM_IP5_GDTBASE); + cpustate->idtr.limit = READ32(cpustate, smram_state+SMRAM_IP5_IDTLIM); + cpustate->idtr.base = READ32(cpustate, smram_state+SMRAM_IP5_IDTBASE); + cpustate->task.limit = READ32(cpustate, smram_state+SMRAM_IP5_TRLIM); + cpustate->task.base = READ32(cpustate, smram_state+SMRAM_IP5_TRBASE); + cpustate->task.flags = READ32(cpustate, smram_state+SMRAM_IP5_TRACC); + + cpustate->sreg[ES].selector = READ32(cpustate, smram_state+SMRAM_ES); + cpustate->sreg[CS].selector = READ32(cpustate, smram_state+SMRAM_CS); + cpustate->sreg[SS].selector = READ32(cpustate, smram_state+SMRAM_SS); + cpustate->sreg[DS].selector = READ32(cpustate, smram_state+SMRAM_DS); + cpustate->sreg[FS].selector = READ32(cpustate, smram_state+SMRAM_FS); + cpustate->sreg[GS].selector = READ32(cpustate, smram_state+SMRAM_GS); + cpustate->ldtr.segment = READ32(cpustate, smram_state+SMRAM_LDTR); + cpustate->task.segment = READ32(cpustate, smram_state+SMRAM_TR); + + cpustate->dr[7] = READ32(cpustate, smram_state+SMRAM_DR7); + cpustate->dr[6] = READ32(cpustate, smram_state+SMRAM_DR6); + REG32(EAX) = READ32(cpustate, smram_state+SMRAM_EAX); + REG32(ECX) = READ32(cpustate, smram_state+SMRAM_ECX); + REG32(EDX) = READ32(cpustate, smram_state+SMRAM_EDX); + REG32(EBX) = READ32(cpustate, smram_state+SMRAM_EBX); + REG32(ESP) = READ32(cpustate, smram_state+SMRAM_ESP); + REG32(EBP) = READ32(cpustate, smram_state+SMRAM_EBP); + REG32(ESI) = READ32(cpustate, smram_state+SMRAM_ESI); + REG32(EDI) = READ32(cpustate, smram_state+SMRAM_EDI); + cpustate->eip = READ32(cpustate, smram_state+SMRAM_EIP); + cpustate->eflags = READ32(cpustate, smram_state+SMRAM_EAX); + cpustate->cr[3] = READ32(cpustate, smram_state+SMRAM_CR3); + cpustate->cr[0] = READ32(cpustate, smram_state+SMRAM_CR0); + + cpustate->CPL = (cpustate->sreg[SS].flags >> 13) & 3; // cpl == dpl of ss + + for(int i = 0; i < GS; i++) + { + if(PROTECTED_MODE && !V8086_MODE) + { + cpustate->sreg[i].valid = cpustate->sreg[i].selector ? true : false; + cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; + } + else + cpustate->sreg[i].valid = true; + } + + if(!cpustate->smiact.isnull()) + cpustate->smiact(false); + cpustate->smm = false; + + CHANGE_PC(cpustate,cpustate->eip); + cpustate->nmi_masked = false; + if(cpustate->nmi_latched) + { + cpustate->nmi_latched = false; + i386_trap(cpustate, 2, 1, 0); + } +} + static void SSEOP(cvttss2si)(i386_state *cpustate) // Opcode f3 0f 2c { UINT32 src;