From 66e159e0bf6fc8588de6d9490dd5731c34229980 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 29 Mar 2020 18:12:43 +0200 Subject: [PATCH] Fixed SMM, now it works correctly, and is now also operating on all CPU's from 386 onwards. --- src/apm.c | 46 +-- src/apm.h | 10 +- src/apm_new.c | 121 ------- src/chipset/intel_4x0.c | 20 +- src/cpu/x86seg.c | 16 +- src/cpu_common/386.c | 8 + src/cpu_common/386_dynarec.c | 652 ++++++++++++++++++++++++---------- src/cpu_common/386_ops.h | 32 +- src/cpu_common/808x.c | 3 + src/cpu_common/cpu.h | 1 + src/cpu_common/x86_ops_misc.h | 9 +- src/cpu_new/x86seg.c | 12 +- src/intel_piix.c | 22 +- src/mem.c | 44 ++- src/mem.h | 1 + src/win/Makefile.mingw | 2 +- src/win/Makefile_ndr.mingw | 2 +- 17 files changed, 597 insertions(+), 404 deletions(-) delete mode 100644 src/apm_new.c diff --git a/src/apm.c b/src/apm.c index 82a6661f0..51dffeab3 100644 --- a/src/apm.c +++ b/src/apm.c @@ -14,6 +14,7 @@ * * Copyright 2019 Miran Grca. */ +#include #include #include #include @@ -24,13 +25,7 @@ #include "cpu.h" #include "device.h" #include "86box_io.h" - - -typedef struct -{ - uint8_t cmd, - stat; -} apm_t; +#include "apm.h" #ifdef ENABLE_APM_LOG @@ -53,6 +48,13 @@ apm_log(const char *fmt, ...) #endif +void +apm_set_do_smi(apm_t *apm, uint8_t do_smi) +{ + apm->do_smi = do_smi; +} + + static void apm_out(uint16_t port, uint8_t val, void *p) { @@ -64,34 +66,8 @@ apm_out(uint16_t port, uint8_t val, void *p) if (port == 0x0000) { apm->cmd = val; - - switch (apm->cmd) { - case 0x07: /* Set Power State */ - if (CH == 0x00) switch (CX) { - case 0x0000: -#ifdef ENABLE_APM_LOG - apm_log("APM Set Power State: APM Enabled\n"); -#endif - break; - case 0x0001: -#ifdef ENABLE_APM_LOG - apm_log("APM Set Power State: Standby\n"); -#endif - break; - case 0x0002: -#ifdef ENABLE_APM_LOG - apm_log("APM Set Power State: Suspend\n"); -#endif - break; - case 0x0003: /* Off */ -#ifdef ENABLE_APM_LOG - apm_log("APM Set Power State: Off\n"); -#endif - exit(-1); - break; - } - break; - } + if (apm->do_smi) + smi_line = 1; } else apm->stat = val; } diff --git a/src/apm.h b/src/apm.h index 5caae9468..e420ec717 100644 --- a/src/apm.h +++ b/src/apm.h @@ -29,11 +29,19 @@ extern "C" { #endif +typedef struct +{ + uint8_t cmd, + stat, do_smi; +} apm_t; + + /* Global variables. */ -extern const device_t apm_device; +extern const device_t apm_device; /* Functions. */ +extern void apm_set_do_smi(apm_t *apm, uint8_t do_smi); #ifdef __cplusplus } diff --git a/src/apm_new.c b/src/apm_new.c deleted file mode 100644 index 3f8385cc3..000000000 --- a/src/apm_new.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Advanced Power Management emulation. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cpu.h" -#include "device.h" -#include "86box_io.h" - - -typedef struct -{ - uint8_t cmd, - stat; -} apm_t; - - -#ifdef ENABLE_APM_LOG -int apm_do_log = ENABLE_APM_LOG; - - -static void -apm_log(const char *fmt, ...) -{ - va_list ap; - - if (apm_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define apm_log(fmt, ...) -#endif - - -static void -apm_out(uint16_t port, uint8_t val, void *p) -{ - apm_t *apm = (apm_t *) p; - - apm_log("[%04X:%08X] APM write: %04X = %02X (BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, BX, CX); - - port &= 0x0001; - - if (port == 0x0000) apm->cmd = val; - else apm->stat = val; - - smi_line = 1; -} - - -static uint8_t -apm_in(uint16_t port, void *p) -{ - apm_t *apm = (apm_t *) p; - - apm_log("[%04X:%08X] APM read: %04X = FF\n", CS, cpu_state.pc, port); - - port &= 0x0001; - - if (port == 0x0000) - return apm->cmd; - else - return apm->stat; -} - - -static void -apm_close(void *p) -{ - apm_t *dev = (apm_t *)p; - - free(dev); -} - - -static void -*apm_init(const device_t *info) -{ - apm_t *apm = (apm_t *) malloc(sizeof(apm_t)); - memset(apm, 0, sizeof(apm_t)); - - io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, apm); - - return apm; -} - - -const device_t apm_device = -{ - "Advanced Power Management", - 0, - 0, - apm_init, - apm_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 9bccbf235..53948b3b6 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -481,7 +481,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) break; case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430VX: - regs[addr] = val/* & 0x3f*/; + regs[addr] = val & 0x3f; break; case INTEL_430TX: regs[addr] = val & 0x7f; @@ -496,7 +496,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) #if defined(DEV_BRANCH) && defined(USE_I686) case INTEL_440FX: #endif - case INTEL_440BX: case INTEL_440ZX: + case INTEL_440BX: case INTEL_440ZX: regs[addr] = val; break; case INTEL_430VX: @@ -513,7 +513,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) #if defined(DEV_BRANCH) && defined(USE_I686) case INTEL_440FX: #endif - case INTEL_440BX: case INTEL_440ZX: + case INTEL_440BX: case INTEL_440ZX: regs[addr] = val; break; } @@ -524,7 +524,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) #if defined(DEV_BRANCH) && defined(USE_I686) case INTEL_440FX: #endif - case INTEL_440BX: case INTEL_440ZX: + case INTEL_440BX: case INTEL_440ZX: regs[addr] = val; break; case INTEL_430VX: @@ -637,9 +637,13 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) break; case 0x72: /* SMRAM */ if (dev->type >= INTEL_430FX) { - if ((regs[0x72] ^ val) & 0x48) + if ((regs[0x72] & 0x10) || (val & 0x10)) { + regs[0x72] = (val & 0x38) | 0x02; + i4x0_map(0xa0000, 0x20000, 0); + } else { + regs[0x72] = (val & 0x78) | 0x02; i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - regs[0x72] = val & 0x7f; + } } else { if ((regs[0x72] ^ val) & 0x20) i4x0_map(0xa0000, 0x20000, ((val & 0x20) == 0x20) ? 3 : 0); @@ -1006,7 +1010,7 @@ i4x0_reset(void *priv) memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t)); } - smbase = 0xa0000; + // smbase = 0xa0000; } @@ -1222,7 +1226,7 @@ static void i4x0_write(regs[0x5e], 0x5e, 0x00, dev); i4x0_write(regs[0x5f], 0x5f, 0x00, dev); - smbase = 0xa0000; + // smbase = 0xa0000; if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) { regs = (uint8_t *) dev->regs[1]; diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 01a846118..53df3770c 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -102,6 +102,7 @@ uint8_t opcode2; static void seg_reset(x86seg *s) { s->access = (0 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->limit = 0xFFFF; s->limit_low = 0; s->limit_high = 0xffff; @@ -135,6 +136,7 @@ void x86_doabrt(int x86_abrt) CS = oldcs; cpu_state.pc = cpu_state.oldpc; cpu_state.seg_cs.access = (oldcpl << 5) | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (msw & 1) pmodeint(x86_abrt, 0); @@ -247,7 +249,8 @@ void do_seg_load(x86seg *s, uint16_t *segdat) if (is386) s->base |= ((segdat[3] >> 8) << 24); s->access = segdat[2] >> 8; - + s->ar_high = segdat[3] & 0xff; + if ((segdat[2] & 0x1800) != 0x1000 || !(segdat[2] & (1 << 10))) /*expand-down*/ { s->limit_high = s->limit; @@ -278,6 +281,7 @@ void do_seg_load(x86seg *s, uint16_t *segdat) static void do_seg_v86_init(x86seg *s) { s->access = (3 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->limit = 0xffff; s->limit_low = 0; s->limit_high = 0xffff; @@ -342,8 +346,9 @@ void loadseg(uint16_t seg, x86seg *s) x86ss(NULL,0); return; } - s->seg=0; + s->seg = 0; s->access = 0x80; + s->ar_high = 0x10; s->base=-1; if (s == &cpu_state.seg_ds) cpu_cur_status |= CPU_STATUS_NOTFLATDS; @@ -463,6 +468,7 @@ void loadseg(uint16_t seg, x86seg *s) else { s->access = (3 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->base = seg << 4; s->seg = seg; s->checked = 1; @@ -593,6 +599,7 @@ void loadcs(uint16_t seg) CS=seg & 0xFFFF; if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; else cpu_state.seg_cs.access=(0<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -814,6 +821,7 @@ void loadcsjmp(uint16_t seg, uint32_t old_pc) CS=seg; if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; else cpu_state.seg_cs.access=(0<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); cycles -= timing_jmp_rm; } @@ -1281,6 +1289,7 @@ void loadcscall(uint16_t seg) CS=seg; if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; else cpu_state.seg_cs.access=(0<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); } } @@ -1903,6 +1912,7 @@ void pmodeiret(int is32) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; cpu_state.seg_cs.access |= 0x80; + cpu_state.seg_cs.ar_high = 0x10; CS=seg; cpu_state.flags=(cpu_state.flags&0x3000)|(tempflags&0xCFD5)|2; cycles -= timing_iret_rm; @@ -1973,6 +1983,7 @@ void pmodeiret(int is32) cpu_state.seg_cs.limit_high = 0xffff; CS=seg; cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high=0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); ESP=newsp; @@ -2577,4 +2588,5 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.base=base; tr.limit=limit; tr.access=segdat[2]>>8; + tr.ar_high = segdat[3] & 0xff; } diff --git a/src/cpu_common/386.c b/src/cpu_common/386.c index 416f9577e..d0f05a7b7 100644 --- a/src/cpu_common/386.c +++ b/src/cpu_common/386.c @@ -272,6 +272,14 @@ exec386(int cycs) } } + if (!in_smm && smi_line/* && is_pentium*/) { + enter_smm(); + smi_line = 0; + } else if (in_smm && smi_line/* && is_pentium*/) { + smi_latched = 1; + smi_line = 0; + } + ins_cycles -= cycles; tsc += ins_cycles; diff --git a/src/cpu_common/386_dynarec.c b/src/cpu_common/386_dynarec.c index b03f723c1..425ffc4b2 100644 --- a/src/cpu_common/386_dynarec.c +++ b/src/cpu_common/386_dynarec.c @@ -34,6 +34,80 @@ #define CPU_BLOCK_END() cpu_block_end = 1 +/* These #define's and enum have been borrowed from Bochs. */ +/* SMM feature masks */ +#define SMM_IO_INSTRUCTION_RESTART (0x00010000) +#define SMM_SMBASE_RELOCATION (0x00020000) + +/* TODO: Which CPU added SMBASE relocation? */ +#define SMM_REVISION_ID SMM_SMBASE_RELOCATION +// #define SMM_REVISION_ID 0 + +#define SMM_SAVE_STATE_MAP_SIZE 128 + + +enum SMMRAM_Fields { + SMRAM_FIELD_SMBASE_OFFSET = 0, + SMRAM_FIELD_SMM_REVISION_ID, + SMRAM_FIELD_EAX, + SMRAM_FIELD_ECX, + SMRAM_FIELD_EDX, + SMRAM_FIELD_EBX, + SMRAM_FIELD_ESP, + SMRAM_FIELD_EBP, + SMRAM_FIELD_ESI, + SMRAM_FIELD_EDI, + SMRAM_FIELD_EIP, + SMRAM_FIELD_EFLAGS, + SMRAM_FIELD_DR6, + SMRAM_FIELD_DR7, + SMRAM_FIELD_CR0, + SMRAM_FIELD_CR3, + SMRAM_FIELD_CR4, + SMRAM_FIELD_EFER, + SMRAM_FIELD_IO_INSTRUCTION_RESTART, + SMRAM_FIELD_AUTOHALT_RESTART, + SMRAM_FIELD_NMI_MASK, + SMRAM_FIELD_TR_SELECTOR, + SMRAM_FIELD_TR_BASE, + SMRAM_FIELD_TR_LIMIT, + SMRAM_FIELD_TR_SELECTOR_AR, + SMRAM_FIELD_LDTR_SELECTOR, + SMRAM_FIELD_LDTR_BASE, + SMRAM_FIELD_LDTR_LIMIT, + SMRAM_FIELD_LDTR_SELECTOR_AR, + SMRAM_FIELD_IDTR_BASE, + SMRAM_FIELD_IDTR_LIMIT, + SMRAM_FIELD_GDTR_BASE, + SMRAM_FIELD_GDTR_LIMIT, + SMRAM_FIELD_ES_SELECTOR, + SMRAM_FIELD_ES_BASE, + SMRAM_FIELD_ES_LIMIT, + SMRAM_FIELD_ES_SELECTOR_AR, + SMRAM_FIELD_CS_SELECTOR, + SMRAM_FIELD_CS_BASE, + SMRAM_FIELD_CS_LIMIT, + SMRAM_FIELD_CS_SELECTOR_AR, + SMRAM_FIELD_SS_SELECTOR, + SMRAM_FIELD_SS_BASE, + SMRAM_FIELD_SS_LIMIT, + SMRAM_FIELD_SS_SELECTOR_AR, + SMRAM_FIELD_DS_SELECTOR, + SMRAM_FIELD_DS_BASE, + SMRAM_FIELD_DS_LIMIT, + SMRAM_FIELD_DS_SELECTOR_AR, + SMRAM_FIELD_FS_SELECTOR, + SMRAM_FIELD_FS_BASE, + SMRAM_FIELD_FS_LIMIT, + SMRAM_FIELD_FS_SELECTOR_AR, + SMRAM_FIELD_GS_SELECTOR, + SMRAM_FIELD_GS_BASE, + SMRAM_FIELD_GS_LIMIT, + SMRAM_FIELD_GS_SELECTOR_AR, + SMRAM_FIELD_LAST +}; + + int inrecomp = 0, cpu_block_end = 0; int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks; int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched; @@ -262,218 +336,401 @@ static void prefetch_flush() #define PREFETCH_FLUSH() prefetch_flush() +static void set_stack32(int s) +{ + stack32 = s; + if (stack32) + cpu_cur_status |= CPU_STATUS_STACK32; + else + cpu_cur_status &= ~CPU_STATUS_STACK32; +} + + +static void set_use32(int u) +{ + if (u) + { + use32 = 0x300; + cpu_cur_status |= CPU_STATUS_USE32; + } + else + { + use32 = 0; + cpu_cur_status &= ~CPU_STATUS_USE32; + } +} + + +void smm_seg_load(x86seg *s) +{ + if (!is386) + s->base &= 0x00ffffff; + + if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) /*expand-down*/ + { + s->limit_high = s->limit; + s->limit_low = 0; + } + else + { + s->limit_high = (s->ar_high & 0x40) ? 0xffffffff : 0xffff; + s->limit_low = s->limit + 1; + } + + if ((cr0 & 1) && !(cpu_state.eflags & VM_FLAG)) + s->checked = s->seg ? 1 : 0; + else + s->checked = 1; + + if (s == &cpu_state.seg_cs) + set_use32(s->ar_high & 0x40); + if (s == &cpu_state.seg_ds) + { + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + } + if (s == &cpu_state.seg_ss) + { + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + set_stack32((s->ar_high & 0x40) ? 1 : 0); + } +} + + +void smram_save_state(uint32_t *saved_state) +{ + int n = 0; + + saved_state[SMRAM_FIELD_SMM_REVISION_ID] = SMM_REVISION_ID; + saved_state[SMRAM_FIELD_SMBASE_OFFSET] = smbase; + + for (n = 0; n < 8; n++) + saved_state[SMRAM_FIELD_EAX + n] = cpu_state.regs[n].l; + + saved_state[SMRAM_FIELD_EIP] = cpu_state.pc; + saved_state[SMRAM_FIELD_EFLAGS] = (cpu_state.eflags << 16) | (cpu_state.flags); + + saved_state[SMRAM_FIELD_CR0] = cr0; + saved_state[SMRAM_FIELD_CR3] = cr3; + if (is_pentium) { + saved_state[SMRAM_FIELD_CR4] = cr4; + /* TODO: Properly implement EFER */ + /* saved_state[SMRAM_FIELD_EFER] = efer; */ + } + saved_state[SMRAM_FIELD_DR6] = dr[6]; + saved_state[SMRAM_FIELD_DR7] = dr[7]; + + /* TR */ + saved_state[SMRAM_FIELD_TR_SELECTOR] = tr.seg; + saved_state[SMRAM_FIELD_TR_BASE] = tr.base; + saved_state[SMRAM_FIELD_TR_LIMIT] = tr.limit; + saved_state[SMRAM_FIELD_TR_SELECTOR_AR] = (tr.ar_high << 24) | (tr.access << 16) | tr.seg; + + /* LDTR */ + saved_state[SMRAM_FIELD_LDTR_SELECTOR] = ldt.seg; + saved_state[SMRAM_FIELD_LDTR_BASE] = ldt.base; + saved_state[SMRAM_FIELD_LDTR_LIMIT] = ldt.limit; + saved_state[SMRAM_FIELD_LDTR_SELECTOR_AR] = (ldt.ar_high << 24) | (ldt.access << 16) | ldt.seg; + + /* IDTR */ + saved_state[SMRAM_FIELD_IDTR_BASE] = idt.base; + saved_state[SMRAM_FIELD_IDTR_LIMIT] = idt.limit; + + /* GDTR */ + saved_state[SMRAM_FIELD_GDTR_BASE] = gdt.base; + saved_state[SMRAM_FIELD_GDTR_LIMIT] = gdt.limit; + + /* ES */ + saved_state[SMRAM_FIELD_ES_SELECTOR] = cpu_state.seg_es.seg; + saved_state[SMRAM_FIELD_ES_BASE] = cpu_state.seg_es.base; + saved_state[SMRAM_FIELD_ES_LIMIT] = cpu_state.seg_es.limit; + saved_state[SMRAM_FIELD_ES_SELECTOR_AR] = + (cpu_state.seg_es.ar_high << 24) | (cpu_state.seg_es.access << 16) | cpu_state.seg_es.seg; + + /* CS */ + saved_state[SMRAM_FIELD_CS_SELECTOR] = cpu_state.seg_cs.seg; + saved_state[SMRAM_FIELD_CS_BASE] = cpu_state.seg_cs.base; + saved_state[SMRAM_FIELD_CS_LIMIT] = cpu_state.seg_cs.limit; + saved_state[SMRAM_FIELD_CS_SELECTOR_AR] = + (cpu_state.seg_cs.ar_high << 24) | (cpu_state.seg_cs.access << 16) | cpu_state.seg_cs.seg; + + /* DS */ + saved_state[SMRAM_FIELD_DS_SELECTOR] = cpu_state.seg_ds.seg; + saved_state[SMRAM_FIELD_DS_BASE] = cpu_state.seg_ds.base; + saved_state[SMRAM_FIELD_DS_LIMIT] = cpu_state.seg_ds.limit; + saved_state[SMRAM_FIELD_DS_SELECTOR_AR] = + (cpu_state.seg_ds.ar_high << 24) | (cpu_state.seg_ds.access << 16) | cpu_state.seg_ds.seg; + + /* SS */ + saved_state[SMRAM_FIELD_SS_SELECTOR] = cpu_state.seg_ss.seg; + saved_state[SMRAM_FIELD_SS_BASE] = cpu_state.seg_ss.base; + saved_state[SMRAM_FIELD_SS_LIMIT] = cpu_state.seg_ss.limit; + saved_state[SMRAM_FIELD_SS_SELECTOR_AR] = + (cpu_state.seg_ss.ar_high << 24) | (cpu_state.seg_ss.access << 16) | cpu_state.seg_ss.seg; + + /* FS */ + saved_state[SMRAM_FIELD_FS_SELECTOR] = cpu_state.seg_fs.seg; + saved_state[SMRAM_FIELD_FS_BASE] = cpu_state.seg_fs.base; + saved_state[SMRAM_FIELD_FS_LIMIT] = cpu_state.seg_fs.limit; + saved_state[SMRAM_FIELD_FS_SELECTOR_AR] = + (cpu_state.seg_fs.ar_high << 24) | (cpu_state.seg_fs.access << 16) | cpu_state.seg_fs.seg; + + /* GS */ + saved_state[SMRAM_FIELD_GS_SELECTOR] = cpu_state.seg_gs.seg; + saved_state[SMRAM_FIELD_GS_BASE] = cpu_state.seg_gs.base; + saved_state[SMRAM_FIELD_GS_LIMIT] = cpu_state.seg_gs.limit; + saved_state[SMRAM_FIELD_GS_SELECTOR_AR] = + (cpu_state.seg_gs.ar_high << 24) | (cpu_state.seg_gs.access << 16) | cpu_state.seg_gs.seg; +} + + +void smram_restore_state(uint32_t *saved_state) +{ + int n = 0; + + for (n = 0; n < 8; n++) + cpu_state.regs[n].l = saved_state[SMRAM_FIELD_EAX + n]; + + cpu_state.pc = saved_state[SMRAM_FIELD_EIP]; + cpu_state.eflags = saved_state[SMRAM_FIELD_EFLAGS] >> 16; + cpu_state.flags = saved_state[SMRAM_FIELD_EFLAGS] & 0xffff; + + cr0 = saved_state[SMRAM_FIELD_CR0]; + cr3 = saved_state[SMRAM_FIELD_CR3]; + if (is_pentium) { + cr4 = saved_state[SMRAM_FIELD_CR4]; + /* TODO: Properly implement EFER */ + /* efer = saved_state[SMRAM_FIELD_EFER]; */ + } + dr[6] = saved_state[SMRAM_FIELD_DR6]; + dr[7] = saved_state[SMRAM_FIELD_DR7]; + + /* TR */ + tr.seg = saved_state[SMRAM_FIELD_TR_SELECTOR]; + tr.base = saved_state[SMRAM_FIELD_TR_BASE]; + tr.limit = saved_state[SMRAM_FIELD_TR_LIMIT]; + tr.access = (saved_state[SMRAM_FIELD_TR_SELECTOR_AR] >> 16) & 0xff; + tr.ar_high = (saved_state[SMRAM_FIELD_TR_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&tr); + + /* LDTR */ + ldt.seg = saved_state[SMRAM_FIELD_LDTR_SELECTOR]; + ldt.base = saved_state[SMRAM_FIELD_LDTR_BASE]; + ldt.limit = saved_state[SMRAM_FIELD_LDTR_LIMIT]; + ldt.access = (saved_state[SMRAM_FIELD_LDTR_SELECTOR_AR] >> 16) & 0xff; + ldt.ar_high = (saved_state[SMRAM_FIELD_LDTR_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&ldt); + + /* IDTR */ + idt.base = saved_state[SMRAM_FIELD_IDTR_BASE]; + idt.limit = saved_state[SMRAM_FIELD_IDTR_LIMIT]; + + /* GDTR */ + gdt.base = saved_state[SMRAM_FIELD_GDTR_BASE]; + gdt.limit = saved_state[SMRAM_FIELD_GDTR_LIMIT]; + + /* ES */ + cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_ES_SELECTOR]; + cpu_state.seg_es.base = saved_state[SMRAM_FIELD_ES_BASE]; + cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_ES_LIMIT]; + cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_ES_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_es.ar_high = (saved_state[SMRAM_FIELD_ES_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_es); + + /* CS */ + cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_CS_SELECTOR]; + cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_CS_BASE]; + cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_CS_LIMIT]; + cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_CS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_cs.ar_high = (saved_state[SMRAM_FIELD_CS_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_cs); + + /* DS */ + cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_DS_SELECTOR]; + cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_DS_BASE]; + cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_DS_LIMIT]; + cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_DS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_ds.ar_high = (saved_state[SMRAM_FIELD_DS_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_ds); + + /* SS */ + cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_SS_SELECTOR]; + cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_SS_BASE]; + cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_SS_LIMIT]; + cpu_state.seg_ss.access = (saved_state[SMRAM_FIELD_SS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_ss.ar_high = (saved_state[SMRAM_FIELD_SS_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_ss); + + /* FS */ + cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_FS_SELECTOR]; + cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_FS_BASE]; + cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_FS_LIMIT]; + cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_FS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_fs.ar_high = (saved_state[SMRAM_FIELD_FS_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_fs); + + /* GS */ + cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_GS_SELECTOR]; + cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_GS_BASE]; + cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_GS_LIMIT]; + cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_GS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_GS_SELECTOR_AR] >> 24) & 0xff; + smm_seg_load(&cpu_state.seg_gs); + + if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) + smbase = saved_state[SMRAM_FIELD_SMBASE_OFFSET]; +} + + void enter_smm() { - uint32_t smram_state = smbase + 0xfe00; - uint32_t old_cr0 = cr0; - uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16); + uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE], n; + uint32_t smram_state = smbase + 0x10000; + + x386_dynarec_log("enter_smm(): smbase = %08X\n", smbase); + x386_dynarec_log("CS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, + cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); + x386_dynarec_log("DS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, + cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); + x386_dynarec_log("ES : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, + cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); + x386_dynarec_log("FS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, + cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); + x386_dynarec_log("GS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, + cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); + x386_dynarec_log("SS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, + cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); + x386_dynarec_log("TR : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); + x386_dynarec_log("LDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); + x386_dynarec_log("GDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); + x386_dynarec_log("IDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); + x386_dynarec_log("CR0 = %08X, CR3 = %08X, CR4 = %08X, DR6 = %08X, DR7 = %08X\n", cr0, cr3, cr4, dr[6], dr[7]); + x386_dynarec_log("EIP = %08X, EFLAGS = %04X%04X\n", cpu_state.pc, cpu_state.eflags, cpu_state.flags); + x386_dynarec_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", + EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); + + memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t)); + smram_save_state(saved_state); + for (n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { + smram_state -= 4; + mem_writel_phys(smram_state, saved_state[n]); + } cr0 &= ~0x8000000d; cpu_state.flags = 2; cpu_state.eflags = 0; - in_smm = 1; - mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - smi_latched = 1; + /* Intel 4x0 chipset stuff. */ + mem_set_mem_state(0xa0000, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + flushmmucache_cr3(); - mem_writel_phys(smram_state + 0xf8, smbase); - mem_writel_phys(smram_state + 0x128, cr4); - mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit); - mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base); - mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access); - mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit); - mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base); - mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access); - mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit); - mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base); - mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access); - mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit); - mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base); - mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access); - mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit); - mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base); - mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access); - mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit); - mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base); - mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access); - mem_writel_phys(smram_state + 0x178, ldt.limit); - mem_writel_phys(smram_state + 0x17c, ldt.base); - mem_writel_phys(smram_state + 0x180, ldt.access); - mem_writel_phys(smram_state + 0x184, gdt.limit); - mem_writel_phys(smram_state + 0x188, gdt.base); - mem_writel_phys(smram_state + 0x18c, gdt.access); - mem_writel_phys(smram_state + 0x190, idt.limit); - mem_writel_phys(smram_state + 0x194, idt.base); - mem_writel_phys(smram_state + 0x198, idt.access); - mem_writel_phys(smram_state + 0x19c, tr.limit); - mem_writel_phys(smram_state + 0x1a0, tr.base); - mem_writel_phys(smram_state + 0x1a4, tr.access); - - mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg); - mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg); - mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg); - mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg); - mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg); - mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg); - mem_writel_phys(smram_state + 0x1c0, ldt.seg); - mem_writel_phys(smram_state + 0x1c4, tr.seg); - - mem_writel_phys(smram_state + 0x1c8, dr[7]); - mem_writel_phys(smram_state + 0x1cc, dr[6]); - mem_writel_phys(smram_state + 0x1d0, EAX); - mem_writel_phys(smram_state + 0x1d4, ECX); - mem_writel_phys(smram_state + 0x1d8, EDX); - mem_writel_phys(smram_state + 0x1dc, EBX); - mem_writel_phys(smram_state + 0x1e0, ESP); - mem_writel_phys(smram_state + 0x1e4, EBP); - mem_writel_phys(smram_state + 0x1e8, ESI); - mem_writel_phys(smram_state + 0x1ec, EDI); - mem_writel_phys(smram_state + 0x1f0, cpu_state.pc); - mem_writel_phys(smram_state + 0x1d0, old_flags); - mem_writel_phys(smram_state + 0x1f8, cr3); - mem_writel_phys(smram_state + 0x1fc, old_cr0); - - ds = es = fs_seg = gs = ss = 0; - - DS = ES = FS = GS = SS = 0; - - cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit - = cpu_state.seg_ss.limit = 0xffffffff; - - cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high - = cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff; - - cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low - = cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0; - - cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access - = cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked - = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; - - CS = 0x3000; - cs = smbase; - cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.access = 0x93; - cpu_state.seg_cs.checked = 1; - - cr4 = 0; + if (is_pentium) + cr4 = 0; dr[7] = 0x400; cpu_state.pc = 0x8000; + cpu_state.seg_ds.seg = 0x00000000; + cpu_state.seg_ds.base = 0x00000000; + cpu_state.seg_ds.limit = 0xffffffff; + cpu_state.seg_ds.access = 0x93; + cpu_state.seg_ds.ar_high = 0x80; + + memcpy(&cpu_state.seg_es, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_ss, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_fs, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_gs, &cpu_state.seg_ds, sizeof(x86seg)); + + CS = (smbase >> 4); + cpu_state.seg_cs.base = smbase; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.access = 0x93; + cpu_state.seg_cs.ar_high = 0x80; + cpu_state.seg_cs.checked = 1; + + smm_seg_load(&cpu_state.seg_es); + smm_seg_load(&cpu_state.seg_cs); + smm_seg_load(&cpu_state.seg_ds); + smm_seg_load(&cpu_state.seg_ss); + smm_seg_load(&cpu_state.seg_fs); + smm_seg_load(&cpu_state.seg_gs); + nmi_mask = 0; + + in_smm = 1; + CPU_BLOCK_END(); } + void leave_smm() { - uint32_t smram_state = smbase + 0xfe00; + uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE], n; + uint32_t smram_state = smbase + 0x10000; - smbase = mem_readl_phys(smram_state + 0xf8); - cr4 = mem_readl_phys(smram_state + 0x128); - - cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130); - cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134); - cpu_state.seg_es.limit_low = cpu_state.seg_es.base; - cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138); - - cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c); - cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140); - cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base; - cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144); - - cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148); - cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c); - cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base; - cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150); - - cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154); - cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158); - cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base; - cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c); - - cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160); - cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164); - cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base; - cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168); - - cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c); - cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170); - cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base; - cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174); - - ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178); - ldt.base = mem_readl_phys(smram_state + 0x17c); - ldt.limit_low = ldt.base; - ldt.access = mem_readl_phys(smram_state + 0x180); - - gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184); - gdt.base = mem_readl_phys(smram_state + 0x188); - gdt.limit_low = gdt.base; - gdt.access = mem_readl_phys(smram_state + 0x18c); - - idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190); - idt.base = mem_readl_phys(smram_state + 0x194); - idt.limit_low = idt.base; - idt.access = mem_readl_phys(smram_state + 0x198); - - tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c); - tr.base = mem_readl_phys(smram_state + 0x1a0); - tr.limit_low = tr.base; - tr.access = mem_readl_phys(smram_state + 0x1a4); - - ES = mem_readl_phys(smram_state + 0x1a8); - CS = mem_readl_phys(smram_state + 0x1ac); - SS = mem_readl_phys(smram_state + 0x1b0); - DS = mem_readl_phys(smram_state + 0x1b4); - FS = mem_readl_phys(smram_state + 0x1b8); - GS = mem_readl_phys(smram_state + 0x1bc); - ldt.seg = mem_readl_phys(smram_state + 0x1c0); - tr.seg = mem_readl_phys(smram_state + 0x1c4); - - dr[7] = mem_readl_phys(smram_state + 0x1c8); - dr[6] = mem_readl_phys(smram_state + 0x1cc); - EAX = mem_readl_phys(smram_state + 0x1d0); - ECX = mem_readl_phys(smram_state + 0x1d4); - EDX = mem_readl_phys(smram_state + 0x1d8); - EBX = mem_readl_phys(smram_state + 0x1dc); - ESP = mem_readl_phys(smram_state + 0x1e0); - EBP = mem_readl_phys(smram_state + 0x1e4); - ESI = mem_readl_phys(smram_state + 0x1e8); - EDI = mem_readl_phys(smram_state + 0x1ec); - - cpu_state.pc = mem_readl_phys(smram_state + 0x1f0); - uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4); - cpu_state.flags = new_flags & 0xffff; - cpu_state.eflags = new_flags >> 16; - cr3 = mem_readl_phys(smram_state + 0x1f8); - cr0 = mem_readl_phys(smram_state + 0x1fc); - - cpu_state.seg_cs.access &= ~0x60; - cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss - - if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG)) - { - cpu_state.seg_cs.checked = CS ? 1 : 0; - cpu_state.seg_ds.checked = DS ? 1 : 0; - cpu_state.seg_es.checked = ES ? 1 : 0; - cpu_state.seg_fs.checked = FS ? 1 : 0; - cpu_state.seg_gs.checked = GS ? 1 : 0; - cpu_state.seg_ss.checked = SS ? 1 : 0; - } - else - { - cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked - = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1; + memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t)); + for (n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { + smram_state -= 4; + saved_state[n] = mem_readl_phys(smram_state); } + smram_restore_state(saved_state); - mem_restore_mem_state(smbase, 131072); - in_smm = 0; + /* Intel 4x0 chipset stuff. */ + mem_restore_mem_state(0xa0000, 131072); + flushmmucache_cr3(); nmi_mask = 1; + + in_smm = 0; + CPU_BLOCK_END(); + + x386_dynarec_log("CS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, + cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); + x386_dynarec_log("DS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, + cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); + x386_dynarec_log("ES : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, + cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); + x386_dynarec_log("FS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, + cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); + x386_dynarec_log("GS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, + cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); + x386_dynarec_log("SS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, + cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); + x386_dynarec_log("TR : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); + x386_dynarec_log("LDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); + x386_dynarec_log("GDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); + x386_dynarec_log("IDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", + idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); + x386_dynarec_log("CR0 = %08X, CR3 = %08X, CR4 = %08X, DR6 = %08X, DR7 = %08X\n", cr0, cr3, cr4, dr[6], dr[7]); + x386_dynarec_log("EIP = %08X, EFLAGS = %04X%04X\n", cpu_state.pc, cpu_state.eflags, cpu_state.flags); + x386_dynarec_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", + EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); + x386_dynarec_log("leave_smm()\n"); } + #define OP_TABLE(name) ops_ ## name #define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) @@ -552,7 +809,7 @@ void exec386_dynarec(int cycs) if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); - if (in_smm && smi_line && is_pentium) + if (!in_smm && smi_line/* && is_pentium*/) CPU_BLOCK_END(); if (cpu_state.abrt) @@ -781,9 +1038,9 @@ void exec386_dynarec(int cycs) #endif CPU_BLOCK_END(); - if (in_smm && smi_line && is_pentium) + if (!in_smm && smi_line/* && is_pentium*/) CPU_BLOCK_END(); - + if (trap) CPU_BLOCK_END(); @@ -867,9 +1124,9 @@ void exec386_dynarec(int cycs) #endif CPU_BLOCK_END(); - if (in_smm && smi_line && is_pentium) + if (!in_smm && smi_line/* && is_pentium*/) CPU_BLOCK_END(); - + if (trap) CPU_BLOCK_END(); @@ -926,9 +1183,12 @@ void exec386_dynarec(int cycs) } } - if (in_smm && smi_line && is_pentium) - { + if (!in_smm && smi_line/* && is_pentium*/) { enter_smm(); + smi_line = 0; + } else if (in_smm && smi_line/* && is_pentium*/) { + smi_latched = 1; + smi_line = 0; } else if (trap) diff --git a/src/cpu_common/386_ops.h b/src/cpu_common/386_ops.h index 41435393b..a351689ca 100644 --- a/src/cpu_common/386_ops.h +++ b/src/cpu_common/386_ops.h @@ -379,7 +379,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, 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*/ ILLEGAL, ILLEGAL, 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, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -401,7 +401,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, 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*/ ILLEGAL, ILLEGAL, 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, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -423,7 +423,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, 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*/ ILLEGAL, ILLEGAL, 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, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -445,7 +445,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, 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*/ ILLEGAL, ILLEGAL, 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, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -470,7 +470,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -492,7 +492,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -514,7 +514,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -536,7 +536,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_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, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -561,7 +561,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_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, @@ -583,7 +583,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_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, @@ -605,7 +605,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_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, @@ -627,7 +627,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_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, @@ -652,7 +652,7 @@ const OpFn OP_TABLE(winchip2_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_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, @@ -674,7 +674,7 @@ const OpFn OP_TABLE(winchip2_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_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, @@ -696,7 +696,7 @@ const OpFn OP_TABLE(winchip2_0f)[1024] = /*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, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_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, @@ -718,7 +718,7 @@ const OpFn OP_TABLE(winchip2_0f)[1024] = /*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, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_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, diff --git a/src/cpu_common/808x.c b/src/cpu_common/808x.c index 28a96a73b..ff5f1eb7c 100644 --- a/src/cpu_common/808x.c +++ b/src/cpu_common/808x.c @@ -970,6 +970,9 @@ reset_common(int hard) cpu_ven_reset(); cpu_alu_op = 0; + + in_smm = smi_latched = 0; + smi_line = 0; } diff --git a/src/cpu_common/cpu.h b/src/cpu_common/cpu.h index 636273b75..68c4f7937 100644 --- a/src/cpu_common/cpu.h +++ b/src/cpu_common/cpu.h @@ -201,6 +201,7 @@ typedef struct { uint32_t base; uint32_t limit; uint8_t access; + uint8_t ar_high; uint16_t seg; uint32_t limit_low, limit_high; diff --git a/src/cpu_common/x86_ops_misc.h b/src/cpu_common/x86_ops_misc.h index 91994785e..8447ef9da 100644 --- a/src/cpu_common/x86_ops_misc.h +++ b/src/cpu_common/x86_ops_misc.h @@ -950,10 +950,13 @@ static int opWRMSR(uint32_t fetchdat) static int opRSM(uint32_t fetchdat) { - if(!in_smm) + if (in_smm) { - leave_smm(); - if(smi_latched) enter_smm(); + leave_smm(); + if (smi_latched) { + smi_latched = 0; + enter_smm(); + } CPU_BLOCK_END(); return 0; } diff --git a/src/cpu_new/x86seg.c b/src/cpu_new/x86seg.c index 86eaafd00..7715f44f9 100644 --- a/src/cpu_new/x86seg.c +++ b/src/cpu_new/x86seg.c @@ -105,6 +105,7 @@ uint8_t opcode2; static void seg_reset(x86seg *s) { s->access = (0 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->limit = 0xFFFF; s->limit_low = 0; s->limit_high = 0xffff; @@ -247,7 +248,8 @@ void do_seg_load(x86seg *s, uint16_t *segdat) if (is386) s->base |= ((segdat[3] >> 8) << 24); s->access = segdat[2] >> 8; - + s->ar_high = segdat[3] & 0xff; + if ((segdat[2] & 0x1800) != 0x1000 || !(segdat[2] & (1 << 10))) /*expand-down*/ { s->limit_high = s->limit; @@ -278,6 +280,7 @@ void do_seg_load(x86seg *s, uint16_t *segdat) static void do_seg_v86_init(x86seg *s) { s->access = (3 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->limit = 0xffff; s->limit_low = 0; s->limit_high = 0xffff; @@ -344,6 +347,7 @@ int loadseg(uint16_t seg, x86seg *s) } s->seg=0; s->access = 0x80; + s->ar_high = 0x10; s->base=-1; if (s == &cpu_state.seg_ds) cpu_cur_status |= CPU_STATUS_NOTFLATDS; @@ -455,6 +459,7 @@ int loadseg(uint16_t seg, x86seg *s) else { s->access = (3 << 5) | 2 | 0x80; + s->ar_high = 0x10; s->base = seg << 4; s->seg = seg; s->checked = 1; @@ -810,6 +815,7 @@ void loadcsjmp(uint16_t seg, uint32_t old_pc) CS=seg; if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; else cpu_state.seg_cs.access=(0<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); oldcpl = CPL; cycles -= timing_jmp_rm; @@ -1275,6 +1281,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc) CS=seg; if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; else cpu_state.seg_cs.access=(0<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); oldcpl = CPL; } @@ -1897,6 +1904,7 @@ void pmodeiret(int is32) cpu_state.seg_cs.limit_low = 0; cpu_state.seg_cs.limit_high = 0xffff; cpu_state.seg_cs.access |= 0x80; + cpu_state.seg_cs.ar_high = 0x10; CS=seg; cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xCFD5) | 2; cycles -= timing_iret_rm; @@ -1966,6 +1974,7 @@ void pmodeiret(int is32) cpu_state.seg_cs.limit_high = 0xffff; CS=seg; cpu_state.seg_cs.access=(3<<5) | 2 | 0x80; + cpu_state.seg_cs.ar_high = 0x10; if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); oldcpl = CPL; @@ -2576,5 +2585,6 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.base=base; tr.limit=limit; tr.access=segdat[2]>>8; + tr.ar_high = 0x10; } diff --git a/src/intel_piix.c b/src/intel_piix.c index 6ec84cfcf..b6952a9b4 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -111,6 +111,7 @@ typedef struct ddma_t ddma[2]; power_t power; piix_smbus_t smbus; + apm_t * apm; nvr_t * nvr; } piix_t; @@ -773,10 +774,18 @@ piix_write(int func, int addr, uint8_t val, void *priv) } break; case 0xa0: - if (dev->type < 4) + if (dev->type < 4) { fregs[addr] = val & 0x1f; + apm_set_do_smi(dev->apm, (val & 0x01) | (fregs[0xa2] & 0x80)); + } break; - case 0xa2: case 0xa5: case 0xa6: case 0xa8: + case 0xa2: + if (dev->type < 4) { + fregs[addr] = val & 0xff; + apm_set_do_smi(dev->apm, (fregs[0xa0] & 0x01) | (val & 0x80)); + } + break; + case 0xa5: case 0xa6: case 0xa8: case 0xaa: case 0xac: case 0xae: if (dev->type < 4) fregs[addr] = val & 0xff; @@ -924,9 +933,10 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; } else if (func == 3) switch(addr) { /* Power Management */ case 0x04: - fregs[0x04] = (val & 1); + fregs[0x04] = (val & 0x01); power_update_io_mapping(dev); smbus_update_io_mapping(dev); + apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); break; case 0x07: if (val & 0x08) @@ -989,6 +999,7 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; case 0x5b: fregs[addr] = val & 0x03; + apm_set_do_smi(dev->apm, !!(val & 0x02) && !!(fregs[0x04] & 0x01)); break; case 0x63: fregs[addr] = val & 0xf7; @@ -1237,7 +1248,7 @@ static void piix_reset_hard(dev); - device_add(&apm_device); + dev->apm = device_add(&apm_device); device_add(&port_92_pci_device); dma_alias_set(); @@ -1278,9 +1289,10 @@ static void dev->readout_regs[1] |= 0x80; io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); - io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); + // io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); dev->board_config[0] = 0xff; + dev->board_config[0] = 0x00; /* Register 0x0079: */ /* Bit 7: 0 = Keep password, 0 = Clear password. */ /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ diff --git a/src/mem.c b/src/mem.c index 281951a30..709697f16 100644 --- a/src/mem.c +++ b/src/mem.c @@ -1209,14 +1209,12 @@ mem_readl_phys(uint32_t addr) uint32_t temp; if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK]; + return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_QMASK]; else if (map && map->read_l) return map->read_l(addr, map->p); else { - temp = mem_readb_phys(addr + 3) << 24; - temp |= mem_readb_phys(addr + 2) << 16; - temp |= mem_readb_phys(addr + 1) << 8; - temp |= mem_readb_phys(addr); + temp = mem_readw_phys(addr + 2) << 16; + temp |= mem_readw_phys(addr); } return temp; @@ -1235,22 +1233,35 @@ mem_writeb_phys(uint32_t addr, uint8_t val) } +void +mem_writew_phys(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) + ((uint16_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK] = val; + else if (map && map->write_w) + map->write_w(addr, val, map->p); + else { + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, (val >> 8) & 0xff); + } +} + + void mem_writel_phys(uint32_t addr, uint32_t val) { mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; + ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_QMASK] = val; else if (map && map->write_l) map->write_l(addr, val, map->p); - else - { - mem_writeb_phys(addr, val & 0xff); - mem_writeb_phys(addr + 1, (val >> 8) & 0xff); - mem_writeb_phys(addr + 2, (val >> 16) & 0xff); - mem_writeb_phys(addr + 3, (val >> 24) & 0xff); - } + else { + mem_writew_phys(addr, val & 0xffff); + mem_writew_phys(addr + 2, (val >> 16) & 0xffff); + } } @@ -1884,6 +1895,8 @@ mem_set_mem_state(uint32_t base, uint32_t size, int state) for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { _mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state[(c + base) >> MEM_GRANULARITY_BITS]; _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = state; + // if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) + // pclog("Set mem state for block at %08X to %02X\n", c + base, state); } mem_mapping_recalc(base, size); @@ -1895,8 +1908,11 @@ mem_restore_mem_state(uint32_t base, uint32_t size) { uint32_t c; - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS]; + // if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) + // pclog("Reset mem state for block at %08X\n", c + base); + } mem_mapping_recalc(base, size); } diff --git a/src/mem.h b/src/mem.h index 015a6273c..4559514fb 100644 --- a/src/mem.h +++ b/src/mem.h @@ -268,6 +268,7 @@ extern uint8_t mem_readb_phys(uint32_t addr); extern uint16_t mem_readw_phys(uint32_t addr); extern uint32_t mem_readl_phys(uint32_t addr); extern void mem_writeb_phys(uint32_t addr, uint8_t val); +extern void mem_writew_phys(uint32_t addr, uint16_t val); extern void mem_writel_phys(uint32_t addr, uint32_t val); extern uint8_t mem_read_ram(uint32_t addr, void *priv); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 95a55517a..4f97c13f6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -558,7 +558,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ) diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index b2f6d81e8..828e90d36 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -563,7 +563,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o am.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ)