From 021a63e782c899c8d8a13ed881b3266481cdd1c2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Oct 2022 05:06:52 +0200 Subject: [PATCH] SiS 471 fixes - fixes the DTK 486 hang. --- src/chipset/sis_85c4xx.c | 46 +++++++--- src/mem/mem.c | 177 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 200 insertions(+), 23 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index ba830ef0a..9b67c4466 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -38,12 +38,25 @@ typedef struct uint8_t cur_reg, tries, reg_base, reg_last, reg_00, is_471, + force_flush, shadowed, + smram_enabled, pad, regs[39], scratch[2]; uint32_t mem_state[8]; smram_t *smram; port_92_t *port_92; } sis_85c4xx_t; +static void +sis_85c4xx_recalcremap(sis_85c4xx_t *dev) +{ + if (dev->is_471) { + if ((mem_size > 8192) || (dev->shadowed & 0x3c) || (dev->regs[0x0b] & 0x02)) + mem_remap_top(0); + else + mem_remap_top(-256); + } +} + static void sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) { @@ -52,6 +65,8 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) uint32_t readext, writeext; uint8_t romcs = 0xc0, cur_romcs; + dev->shadowed = 0x00; + shadowbios = 0; shadowbios_write = 0; @@ -73,25 +88,34 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40); shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext; shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL; - if (dev->mem_state[i] != shflags) { + if (dev->regs[0x02] & 0x80) + dev->shadowed |= (1 << i); + if (!(dev->regs[0x02] & 0x40)) + dev->shadowed |= (1 << i); + if (dev->force_flush || (dev->mem_state[i] != shflags)) { n++; - mem_set_mem_state(base, 0x8000, shflags); + mem_set_mem_state_both(base, 0x8000, shflags); if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL)) mem_invalidate_range(base, base + 0x7fff); dev->mem_state[i] = shflags; } } else { shflags = readext | writeext; - if (dev->mem_state[i] != shflags) { + if (dev->force_flush || (dev->mem_state[i] != shflags)) { n++; - mem_set_mem_state(base, 0x8000, shflags); + mem_set_mem_state_both(base, 0x8000, shflags); dev->mem_state[i] = shflags; } } } - if (n > 0) + if (dev->force_flush) { + flushmmucache(); + dev->force_flush = 0; + } else if (n > 0) flushmmucache_nopc(); + + sis_85c4xx_recalcremap(dev); } static void @@ -158,12 +182,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x0b: sis_85c4xx_sw_smi_handler(dev); - if (dev->is_471 && (valxor & 0x02)) { - if (val & 0x02) - mem_remap_top(0); - else - mem_remap_top(256); - } + if (valxor & 0x02) + sis_85c4xx_recalcremap(dev); break; case 0x13: @@ -184,8 +204,10 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) ram_base = 0x00000000; break; } + dev->smram_enabled = (ram_base != 0x00000000); if (ram_base != 0x00000000) smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1); + sis_85c4xx_recalcremap(dev); } break; @@ -289,7 +311,6 @@ sis_85c4xx_reset(void *priv) port_92_remove(dev->port_92); - mem_remap_top(256); soft_reset_mask = 0; } else { /* Bits 6 and 7 must be clear on the SiS 40x. */ @@ -309,6 +330,7 @@ sis_85c4xx_reset(void *priv) cpu_cache_ext_enabled = 0; cpu_update_waitstates(); + dev->force_flush = 1; sis_85c4xx_recalcmapping(dev); } diff --git a/src/mem/mem.c b/src/mem/mem.c index 9f292fd0e..ecda875a6 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -55,11 +55,12 @@ #endif mem_mapping_t ram_low_mapping, /* 0..640K mapping */ - ram_mid_mapping, + ram_mid_mapping, /* 640..1024K mapping */ + ram_mid_mapping2, /* 640..1024K mapping, second part, for SiS 471 in relocate mode */ ram_remapped_mapping, /* 640..1024K mapping */ + ram_remapped_mapping2,/* 640..1024K second mapping, for SiS 471 mode */ ram_high_mapping, /* 1024K+ mapping */ ram_2gb_mapping, /* 1024M+ mapping */ - ram_remapped_mapping, ram_split_mapping, bios_mapping, bios_high_mapping; @@ -71,6 +72,7 @@ uint32_t pages_sz; /* #pages in table */ uint8_t *ram, *ram2; /* the virtual RAM */ uint8_t page_ff[4096]; uint32_t rammask; +uint32_t addr_space_size; uint8_t *rom; /* the virtual ROM */ uint32_t biosmask, biosaddr; @@ -127,7 +129,7 @@ static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static mem_state_t _mem_state[MEM_MAPPINGS_NO]; -static uint32_t remap_start_addr; +static uint32_t remap_start_addr, remap_start_addr2; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) static size_t ram_size = 0, ram2_size = 0; #else @@ -157,7 +159,8 @@ mem_addr_is_ram(uint32_t addr) { mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; - return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping); + return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || + (mapping == &ram_mid_mapping2) || (mapping == &ram_remapped_mapping); } void @@ -2087,6 +2090,33 @@ mem_read_remappedl(uint32_t addr, void *priv) return *(uint32_t *) &ram[addr]; } +static uint8_t +mem_read_remapped2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + +static uint16_t +mem_read_remappedw2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; +} + +static uint32_t +mem_read_remappedl2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; +} + static void mem_write_remapped(uint32_t addr, uint8_t val, void *priv) { @@ -2123,6 +2153,42 @@ mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) *(uint32_t *) &ram[addr] = val; } +static void +mem_write_remapped2(uint32_t addr, uint8_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + } else + ram[addr] = val; +} + +static void +mem_write_remappedw2(uint32_t addr, uint16_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +static void +mem_write_remappedl2(uint32_t addr, uint32_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} + void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { @@ -2605,6 +2671,8 @@ mem_reset(void) m = 256; } + addr_space_size = m; + /* * Allocate and initialize the (new) page table. */ @@ -2687,15 +2755,26 @@ mem_reset(void) } } - if (mem_size > 768) + if (mem_size > 768) { mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); + mem_add_ram_mapping(&ram_mid_mapping2, 0xa0000, 0x60000); + mem_mapping_disable(&ram_mid_mapping2); + } + mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, mem_read_remapped, mem_read_remappedw, mem_read_remappedl, mem_write_remapped, mem_write_remappedw, mem_write_remappedl, ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_disable(&ram_remapped_mapping); + /* Mapping for SiS 471 relocation which relocates A0000-BFFFF, D0000-EFFFF, which is non-contiguous. */ + mem_mapping_add(&ram_remapped_mapping2, mem_size * 1024, 256 * 1024, + mem_read_remapped2, mem_read_remappedw2, mem_read_remappedl2, + mem_write_remapped2, mem_write_remappedw2, mem_write_remappedl2, + ram + 0xd0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping2); + mem_a20_init(); #ifdef USE_NEW_DYNAREC @@ -2729,11 +2808,19 @@ mem_remap_top(int kb) int offset, size = mem_size - 640; int set = 1; static int old_kb = 0; + int sis_mode = 0; + uint32_t start_addr = 0, addr = 0; mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); if (mem_size <= 640) return; + /* SiS 471 special mode. */ + if (kb == -256) { + kb = 256; + sis_mode = 1; + } + if (kb == 0) { kb = old_kb; set = 0; @@ -2744,27 +2831,95 @@ mem_remap_top(int kb) size = kb; remap_start_addr = start << 10; + remap_start_addr2 = (start << 10) + 0x00020000; for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { offset = c - ((start * 1024) >> 12); - pages[c].mem = set ? &ram[0xa0000 + (offset << 12)] : page_ff; + /* Use A0000-BFFFF, D0000-EFFFF instead of C0000-DFFFF, E0000-FFFFF. */ + addr = 0xa0000 + (offset << 12); + if (sis_mode) { + /* A0000-DFFFF -> A0000-BFFFF, D0000-EFFFF */ + if (addr >= 0x000c0000) + addr += 0x00010000; + } + if (start_addr != 0) + start_addr = addr; + pages[c].mem = set ? &ram[addr] : page_ff; pages[c].write_b = set ? mem_write_ramb_page : NULL; pages[c].write_w = set ? mem_write_ramw_page : NULL; pages[c].write_l = set ? mem_write_raml_page : NULL; #ifdef USE_NEW_DYNAREC pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; + pages[c].byte_dirty_mask = &byte_dirty_mask[(addr >> 12) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(addr >> 12) * 64]; #endif } mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + for (c = 0xa0; c < 0xf0; c++) { + if ((c >= 0xc0) && (c <= 0xcf)) + continue; + + if (sis_mode || ((c << 12) >= (mem_size << 10))) + pages[c].mem = page_ff; + else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif + } + if (!sis_mode && (c < addr_space_size)) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } else { + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; + } +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } + if (set) { - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + 0xa0000); - } else + if (sis_mode) { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping, ram + 0x000a0000); + mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); + mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + } else { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } + } else { mem_mapping_disable(&ram_remapped_mapping); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } flushmmucache(); }