diff --git a/src/acpi.c b/src/acpi.c index 17c9fe40b..91dc44eae 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -125,8 +125,10 @@ acpi_reg_read_intel(int size, uint16_t addr, void *p) case 0x08: case 0x09: case 0x0a: case 0x0b: /* PMTMR - Power Management Timer Register (IO) */ ret = (dev->regs.timer_val >> shift32) & 0xff; +#ifdef USE_DYNAREC if (cpu_use_dynarec) update_tsc(); +#endif break; case 0x0c: case 0x0d: /* GPSTS - General Purpose Status Register (IO) */ @@ -213,8 +215,10 @@ acpi_reg_read_via(int size, uint16_t addr, void *p) case 0x08: case 0x09: case 0x0a: case 0x0b: /* PMTMR - Power Management Timer Register (IO) */ ret = (dev->regs.timer_val >> shift32) & 0xff; +#ifdef USE_DYNAREC if (cpu_use_dynarec) update_tsc(); +#endif break; case 0x10: case 0x11: case 0x12: case 0x13: /* PCNTRL - Processor Control Register (IO) */ diff --git a/src/chipset/rabbit.c b/src/chipset/sis_85c310.c similarity index 95% rename from src/chipset/rabbit.c rename to src/chipset/sis_85c310.c index ec8e7e87b..2a11f9654 100644 --- a/src/chipset/rabbit.c +++ b/src/chipset/sis_85c310.c @@ -1,150 +1,150 @@ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/chipset.h> - - -typedef struct -{ - uint8_t cur_reg, tries, - regs[258]; -} rabbit_t; - - -static void -rabbit_recalcmapping(rabbit_t *dev) -{ - uint32_t shread, shwrite; - uint32_t shflags = 0; - - shread = !!(dev->regs[0x101] & 0x40); - shwrite = !!(dev->regs[0x100] & 0x02); - - shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - - shadowbios = !!shread; - shadowbios_write = !!shwrite; - -#ifdef USE_SHADOW_C0000 - mem_set_mem_state(0x000c0000, 0x00040000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); -#else - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); -#endif - - switch (dev->regs[0x100] & 0x09) { - case 0x01: -/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow, - no idea what. */ -#ifdef USE_SHADOW_C0000 - /* 64K at 0C0000-0CFFFF */ - mem_set_mem_state(0x000c0000, 0x00010000, shflags); - /* FALLTHROUGH */ -#endif - case 0x00: - /* 64K at 0F0000-0FFFFF */ - mem_set_mem_state(0x000f0000, 0x00010000, shflags); - break; - - case 0x09: -#ifdef USE_SHADOW_C0000 - /* 128K at 0C0000-0DFFFF */ - mem_set_mem_state(0x000c0000, 0x00020000, shflags); - /* FALLTHROUGH */ -#endif - case 0x08: - /* 128K at 0E0000-0FFFFF */ - mem_set_mem_state(0x000e0000, 0x00020000, shflags); - break; - } - - flushmmucache(); -} - - -static void -rabbit_write(uint16_t addr, uint8_t val, void *priv) -{ - rabbit_t *dev = (rabbit_t *) priv; - - switch (addr) { - case 0x22: - dev->cur_reg = val; - dev->tries = 0; - break; - case 0x23: - if (dev->cur_reg == 0x83) { - if (dev->tries < 0x02) { - dev->regs[dev->tries++ | 0x100] = val; - if (dev->tries == 0x02) - rabbit_recalcmapping(dev); - } - } else - dev->regs[dev->cur_reg] = val; - break; - } -} - - -static uint8_t -rabbit_read(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - rabbit_t *dev = (rabbit_t *) priv; - - switch (addr) { - case 0x23: - if (dev->cur_reg == 0x83) { - if (dev->tries < 0x02) - ret = dev->regs[dev->tries++ | 0x100]; - } else - ret = dev->regs[dev->cur_reg]; - break; - } - - return ret; -} - - -static void -rabbit_close(void *priv) -{ - rabbit_t *dev = (rabbit_t *) priv; - - free(dev); -} - - -static void * -rabbit_init(const device_t *info) -{ - rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t)); - memset(dev, 0, sizeof(rabbit_t)); - - io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev); - - return dev; -} - - -const device_t rabbit_device = { - "SiS Rabbit", - 0, - 0, - rabbit_init, rabbit_close, NULL, - NULL, NULL, NULL, - NULL +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/chipset.h> + + +typedef struct +{ + uint8_t cur_reg, tries, + regs[258]; +} rabbit_t; + + +static void +rabbit_recalcmapping(rabbit_t *dev) +{ + uint32_t shread, shwrite; + uint32_t shflags = 0; + + shread = !!(dev->regs[0x101] & 0x40); + shwrite = !!(dev->regs[0x100] & 0x02); + + shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + + shadowbios = !!shread; + shadowbios_write = !!shwrite; + +#ifdef USE_SHADOW_C0000 + mem_set_mem_state(0x000c0000, 0x00040000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); +#else + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); +#endif + + switch (dev->regs[0x100] & 0x09) { + case 0x01: +/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow, + no idea what. */ +#ifdef USE_SHADOW_C0000 + /* 64K at 0C0000-0CFFFF */ + mem_set_mem_state(0x000c0000, 0x00010000, shflags); + /* FALLTHROUGH */ +#endif + case 0x00: + /* 64K at 0F0000-0FFFFF */ + mem_set_mem_state(0x000f0000, 0x00010000, shflags); + break; + + case 0x09: +#ifdef USE_SHADOW_C0000 + /* 128K at 0C0000-0DFFFF */ + mem_set_mem_state(0x000c0000, 0x00020000, shflags); + /* FALLTHROUGH */ +#endif + case 0x08: + /* 128K at 0E0000-0FFFFF */ + mem_set_mem_state(0x000e0000, 0x00020000, shflags); + break; + } + + flushmmucache(); +} + + +static void +rabbit_write(uint16_t addr, uint8_t val, void *priv) +{ + rabbit_t *dev = (rabbit_t *) priv; + + switch (addr) { + case 0x22: + dev->cur_reg = val; + dev->tries = 0; + break; + case 0x23: + if (dev->cur_reg == 0x83) { + if (dev->tries < 0x02) { + dev->regs[dev->tries++ | 0x100] = val; + if (dev->tries == 0x02) + rabbit_recalcmapping(dev); + } + } else + dev->regs[dev->cur_reg] = val; + break; + } +} + + +static uint8_t +rabbit_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + rabbit_t *dev = (rabbit_t *) priv; + + switch (addr) { + case 0x23: + if (dev->cur_reg == 0x83) { + if (dev->tries < 0x02) + ret = dev->regs[dev->tries++ | 0x100]; + } else + ret = dev->regs[dev->cur_reg]; + break; + } + + return ret; +} + + +static void +rabbit_close(void *priv) +{ + rabbit_t *dev = (rabbit_t *) priv; + + free(dev); +} + + +static void * +rabbit_init(const device_t *info) +{ + rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t)); + memset(dev, 0, sizeof(rabbit_t)); + + io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev); + + return dev; +} + + +const device_t rabbit_device = { + "SiS Rabbit", + 0, + 0, + rabbit_init, rabbit_close, NULL, + NULL, NULL, NULL, + NULL }; \ No newline at end of file diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 47db7c5db..1e541edd8 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -24,10 +24,13 @@ #include "386_common.h" #include "x86_flags.h" #include "x86seg.h" + +#ifdef USE_DYNAREC #include "codegen.h" - - #define CPU_BLOCK_END() cpu_block_end = 1 +#else +#define CPU_BLOCK_END() +#endif x86seg gdt, ldt, idt, tr; @@ -1564,7 +1567,9 @@ sysenter(uint32_t fetchdat) return 1; do_seg_load(&cpu_state.seg_ss, seg_data); cpu_state.seg_ss.checked = 0; +#ifdef USE_DYNAREC codegen_flat_ss = 0; +#endif if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -1657,7 +1662,9 @@ sysexit(uint32_t fetchdat) return 1; do_seg_load(&cpu_state.seg_ss, seg_data); cpu_state.seg_ss.checked = 0; +#ifdef USE_DYNAREC codegen_flat_ss = 0; +#endif if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -1725,7 +1732,9 @@ syscall(uint32_t fetchdat) return 1; do_seg_load(&cpu_state.seg_ss, seg_data); cpu_state.seg_ss.checked = 0; +#ifdef USE_DYNAREC codegen_flat_ss = 0; +#endif if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -1782,7 +1791,9 @@ sysret(uint32_t fetchdat) return 1; do_seg_load(&cpu_state.seg_ss, seg_data); cpu_state.seg_ss.checked = 0; +#ifdef USE_DYNAREC codegen_flat_ss = 0; +#endif if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; @@ -1797,3 +1808,13 @@ sysret(uint32_t fetchdat) return 1; } + + +#ifndef USE_DYNAREC +/* This is for compatibility with new x87 code. */ +void codegen_set_rounding_mode(int mode) +{ + /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */ + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); +} +#endif diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 6bc896753..a712e6830 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -953,7 +953,6 @@ reset_common(int hard) makeznptable(); resetreadlookup(); makemod1table(); - resetmcr(); pfq_clear(); cpu_set_edx(); mmu_perm = 4; @@ -984,6 +983,8 @@ reset_common(int hard) ppi_reset(); } in_sys = 0; + + shadowbios = shadowbios_write = 0; } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 099658875..879e02a97 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1398,7 +1398,9 @@ cpu_set(void) cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX | CPU_FEATURE_3DNOW; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_k6); +#endif break; case CPU_PENTIUMPRO: diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index 0d9db70a7..68f1bac2a 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -99,7 +99,7 @@ static int opSAHF(uint32_t fetchdat) CLOCK_CYCLES(3); PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); -#ifdef USE_NEW_DYNAREC +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_flags_changed = 0; #endif @@ -182,7 +182,7 @@ static int opPOPF_286(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); -#ifdef USE_NEW_DYNAREC +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_flags_changed = 0; #endif @@ -242,7 +242,7 @@ static int opPOPF(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); -#ifdef USE_NEW_DYNAREC +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_flags_changed = 0; #endif @@ -276,7 +276,7 @@ static int opPOPFD(uint32_t fetchdat) CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); -#ifdef USE_NEW_DYNAREC +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_flags_changed = 0; #endif diff --git a/src/cpu/x86_ops_msr.h b/src/cpu/x86_ops_msr.h index 4c9fd9fe5..6624218e4 100644 --- a/src/cpu/x86_ops_msr.h +++ b/src/cpu/x86_ops_msr.h @@ -14,8 +14,10 @@ static int opRDTSC(uint32_t fetchdat) EAX = tsc & 0xffffffff; EDX = tsc >> 32; CLOCK_CYCLES(1); +#ifdef USE_DYNAREC if (cpu_use_dynarec) update_tsc(); +#endif return 0; } diff --git a/src/bugger.c b/src/device/bugger.c similarity index 100% rename from src/bugger.c rename to src/device/bugger.c diff --git a/src/hwm.c b/src/device/hwm.c similarity index 100% rename from src/hwm.c rename to src/device/hwm.c diff --git a/src/hwm_lm75.c b/src/device/hwm_lm75.c similarity index 100% rename from src/hwm_lm75.c rename to src/device/hwm_lm75.c diff --git a/src/hwm_lm78.c b/src/device/hwm_lm78.c similarity index 100% rename from src/hwm_lm78.c rename to src/device/hwm_lm78.c diff --git a/src/ibm_5161.c b/src/device/ibm_5161.c similarity index 100% rename from src/ibm_5161.c rename to src/device/ibm_5161.c diff --git a/src/isamem.c b/src/device/isamem.c similarity index 100% rename from src/isamem.c rename to src/device/isamem.c diff --git a/src/isartc.c b/src/device/isartc.c similarity index 100% rename from src/isartc.c rename to src/device/isartc.c diff --git a/src/keyboard.c b/src/device/keyboard.c similarity index 100% rename from src/keyboard.c rename to src/device/keyboard.c diff --git a/src/keyboard_at.c b/src/device/keyboard_at.c similarity index 100% rename from src/keyboard_at.c rename to src/device/keyboard_at.c diff --git a/src/keyboard_xt.c b/src/device/keyboard_xt.c similarity index 100% rename from src/keyboard_xt.c rename to src/device/keyboard_xt.c diff --git a/src/mouse.c b/src/device/mouse.c similarity index 100% rename from src/mouse.c rename to src/device/mouse.c diff --git a/src/mouse_bus.c b/src/device/mouse_bus.c similarity index 100% rename from src/mouse_bus.c rename to src/device/mouse_bus.c diff --git a/src/mouse_ps2.c b/src/device/mouse_ps2.c similarity index 100% rename from src/mouse_ps2.c rename to src/device/mouse_ps2.c diff --git a/src/mouse_serial.c b/src/device/mouse_serial.c similarity index 100% rename from src/mouse_serial.c rename to src/device/mouse_serial.c diff --git a/src/postcard.c b/src/device/postcard.c similarity index 100% rename from src/postcard.c rename to src/device/postcard.c diff --git a/src/serial.c b/src/device/serial.c similarity index 100% rename from src/serial.c rename to src/device/serial.c diff --git a/src/smbus.c b/src/device/smbus.c similarity index 100% rename from src/smbus.c rename to src/device/smbus.c diff --git a/src/smbus_piix4.c b/src/device/smbus_piix4.c similarity index 100% rename from src/smbus_piix4.c rename to src/device/smbus_piix4.c diff --git a/src/io.c b/src/io.c index 5aaedc8d6..0091fae01 100644 --- a/src/io.c +++ b/src/io.c @@ -332,8 +332,10 @@ outb(uint16_t port, uint8_t val) if (!found) { sub_cycles(io_delay); +#ifdef USE_DYNAREC if (cpu_use_dynarec && (port == 0xeb)) update_tsc(); +#endif } io_log("(%i, %i, %04i) outb(%04X, %02X)\n", in_smm, found, qfound, port, val); @@ -425,8 +427,10 @@ outw(uint16_t port, uint16_t val) if (!found) { sub_cycles(io_delay); +#ifdef USE_DYNAREC if (cpu_use_dynarec && (port == 0xeb)) update_tsc(); +#endif } io_log("(%i, %i, %04i) outw(%04X, %04X)\n", in_smm, found, qfound, port, val); @@ -552,8 +556,10 @@ outl(uint16_t port, uint32_t val) if (!found) { sub_cycles(io_delay); +#ifdef USE_DYNAREC if (cpu_use_dynarec && (port == 0xeb)) update_tsc(); +#endif } io_log("(%i, %i, %04i) outl(%04X, %08X)\n", in_smm, found, qfound, port, val); diff --git a/src/intel_flash.c b/src/mem/intel_flash.c similarity index 100% rename from src/intel_flash.c rename to src/mem/intel_flash.c diff --git a/src/mem.c b/src/mem/mem.c similarity index 96% rename from src/mem.c rename to src/mem/mem.c index 71cf714c3..e92652b5c 100644 --- a/src/mem.c +++ b/src/mem/mem.c @@ -1,2868 +1,2888 @@ -/* - * 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. - * - * Memory handling and MMU. - * - * NOTE: Experimenting with dynamically allocated lookup tables; - * the DYNAMIC_TABLES=1 enables this. Will eventually go - * away, either way... - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include "x86_ops.h" -#include "x86.h" -#include <86box/machine.h> -#include <86box/m_xt_xi8088.h> -#include <86box/config.h> -#include <86box/io.h> -#include <86box/mem.h> -#include <86box/rom.h> -#ifdef USE_DYNAREC -# include "codegen_public.h" -#else -#ifdef USE_NEW_DYNAREC -# define PAGE_MASK_SHIFT 6 -#else -# define PAGE_MASK_INDEX_MASK 3 -# define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_SHIFT 4 -#endif -# define PAGE_MASK_MASK 63 -#endif - - -#define FIXME 0 -#define DYNAMIC_TABLES 0 /* experimental */ - - -mem_mapping_t base_mapping, - ram_low_mapping, /* 0..640K mapping */ -#if 1 - ram_mid_mapping, -#endif - ram_remapped_mapping, /* 640..1024K mapping */ - ram_high_mapping, /* 1024K+ mapping */ - ram_2gb_mapping, /* 1024M+ mapping */ - ram_remapped_mapping, - ram_split_mapping, - ram_smram_mapping[2], - bios_mapping, - bios_high_mapping; - -page_t *pages, /* RAM page table */ - **page_lookup; /* pagetable lookup */ -uint32_t pages_sz; /* #pages in table */ - -uint8_t *ram, *ram2; /* the virtual RAM */ -uint32_t rammask; - -uint8_t *rom; /* the virtual ROM */ -uint32_t biosmask, biosaddr; - -uint32_t pccache; -uint8_t *pccache2; - -int readlnext; -int readlookup[256], - readlookupp[256]; -uintptr_t *readlookup2; -int writelnext; -int writelookup[256], - writelookupp[256]; -uintptr_t *writelookup2; - -uint32_t mem_logical_addr; - -int shadowbios = 0, - shadowbios_write; -int readlnum = 0, - writelnum = 0; -int cachesize = 256; - -uint32_t get_phys_virt, - get_phys_phys; - -smram_t smram[2] = { { 0x000a0000, 0x000a0000 }, { 0x000a0000, 0x000a0000 } }; - -int mem_a20_key = 0, - mem_a20_alt = 0, - mem_a20_state = 0; - -int mmuflush = 0; -int mmu_perm = 4; - -uint64_t *byte_dirty_mask; -uint64_t *byte_code_present_mask; - -uint32_t purgable_page_list_head = 0; -int purgeable_page_count = 0; - -int use_phys_exec = 0; - - -/* FIXME: re-do this with a 'mem_ops' struct. */ -static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; -static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -static uint32_t _mem_state[MEM_MAPPINGS_NO]; - -#if FIXME -#if (MEM_GRANULARITY_BITS >= 12) -static uint8_t ff_array[MEM_GRANULARITY_SIZE]; -#else -static uint8_t ff_array[4096]; /* Must be at least one page. */ -#endif -#else -static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; -#endif - - -#ifdef ENABLE_MEM_LOG -int mem_do_log = ENABLE_MEM_LOG; - - -static void -mem_log(const char *fmt, ...) -{ - va_list ap; - - if (mem_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define mem_log(fmt, ...) -#endif - - -int -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); -} - - -void -resetreadlookup(void) -{ - int c; - - /* This is NULL after app startup, when mem_init() has not yet run. */ -#if DYNAMIC_TABLES -mem_log("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); -#endif - - /* Initialize the page lookup table. */ -#if DYNAMIC_TABLES - memset(page_lookup, 0x00, pages_sz*sizeof(page_t *)); -#else - memset(page_lookup, 0x00, (1<<20)*sizeof(page_t *)); -#endif - - /* Initialize the tables for lower (<= 1024K) RAM. */ - for (c = 0; c < 256; c++) { - readlookup[c] = 0xffffffff; - writelookup[c] = 0xffffffff; - } - - /* Initialize the tables for high (> 1024K) RAM. */ -#if DYNAMIC_TABLES - memset(readlookup2, 0xff, pages_sz*sizeof(uintptr_t)); - memset(writelookup2, 0xff, pages_sz*sizeof(uintptr_t)); -#else - memset(readlookup2, 0xff, (1<<20)*sizeof(uintptr_t)); - memset(writelookup2, 0xff, (1<<20)*sizeof(uintptr_t)); -#endif - - readlnext = 0; - writelnext = 0; - pccache = 0xffffffff; -} - - -void -flushmmucache(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } - mmuflush++; - - pccache = (uint32_t)0xffffffff; - pccache2 = (uint8_t *)0xffffffff; - -#ifdef USE_DYNAREC - codegen_flush(); -#endif -} - - -void -flushmmucache_nopc(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } -} - - -void -flushmmucache_cr3(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } -} - - -void -mem_flush_write_page(uint32_t addr, uint32_t virt) -{ - page_t *page_target = &pages[addr >> 12]; - int c; - uint32_t a; - - for (c = 0; c < 256; c++) { - if (writelookup[c] != (int) 0xffffffff) { - a = (uintptr_t)(addr & ~0xfff) - (virt & ~0xfff); - uintptr_t target; - - if ((addr & ~0xfff) >= (1 << 30)) - target = (uintptr_t)&ram2[a - (1 << 30)]; - else - target = (uintptr_t)&ram[a]; - - if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { - writelookup2[writelookup[c]] = -1; - page_lookup[writelookup[c]] = NULL; - writelookup[c] = 0xffffffff; - } - } - } -} - - -#define mmutranslate_read(addr) mmutranslatereal(addr,0) -#define mmutranslate_write(addr) mmutranslatereal(addr,1) -#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] -#define rammap64(x) ((uint64_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] - -static uint64_t -mmutranslatereal_normal(uint32_t addr, int rw) -{ - uint32_t temp,temp2,temp3; - uint32_t addr2; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap(addr2) |= 0x20; - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - if (!(temp&1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap(addr2) |= 0x20; - rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw?0x60:0x20); - - return (uint64_t) ((temp&~0xfff)+(addr&0xfff)); -} - - -static uint64_t -mmutranslatereal_pae(uint32_t addr, int rw) -{ - uint64_t temp,temp2,temp3,temp4; - uint64_t addr2,addr3,addr4; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); - temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); - temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - - return 0xffffffffffffffffULL; - } - mmu_perm = temp & 4; - rammap64(addr3) |= 0x20; - - return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; - } - - addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL; - temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap64(addr3) |= 0x20; - rammap64(addr4) |= (rw? 0x60 : 0x20); - - return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; -} - - -uint64_t -mmutranslatereal(uint32_t addr, int rw) -{ - if (cr4 & CR4_PAE) - return mmutranslatereal_pae(addr, rw); - else - return mmutranslatereal_normal(addr, rw); -} - - -/* This is needed because the old recompiler calls this to check for page fault. */ -uint32_t -mmutranslatereal32(uint32_t addr, int rw) -{ - return (uint32_t) mmutranslatereal(addr, rw); -} - - -static uint64_t -mmutranslate_noabrt_normal(uint32_t addr, int rw) -{ - uint32_t temp,temp2,temp3; - uint32_t addr2; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - - if (! (temp & 1)) - return 0xffffffffffffffffULL; - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); -} - - -static uint64_t -mmutranslate_noabrt_pae(uint32_t addr, int rw) -{ - uint64_t temp,temp2,temp3,temp4; - uint64_t addr2,addr3,addr4; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); - temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; - - if (! (temp & 1)) - return 0xffffffffffffffffULL; - - addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); - temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; - - if (! (temp & 1)) - return 0xffffffffffffffffULL; - - if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; - } - - addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL;; - temp3 = temp & temp4; - - if (!(temp&1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; -} - - -uint64_t -mmutranslate_noabrt(uint32_t addr, int rw) -{ - if (cr4 & CR4_PAE) - return mmutranslate_noabrt_pae(addr, rw); - else - return mmutranslate_noabrt_normal(addr, rw); -} - - -void -mmu_invalidate(uint32_t addr) -{ - flushmmucache_cr3(); -} - - -uint8_t -mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) -{ - if (addr < start) - return 0; - else if (addr >= (start + len)) - return 0; - else - return 1; -} - - -uint32_t -mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) -{ - uint32_t mask = len - 1; - - return chunk_start + (addr & mask); -} - - -void -addreadlookup(uint32_t virt, uint32_t phys) -{ - uint32_t a; - - if (virt == 0xffffffff) return; - - if (readlookup2[virt>>12] != (uintptr_t) -1) return; - - if (readlookup[readlnext] != (int) 0xffffffff) - readlookup2[readlookup[readlnext]] = -1; - - a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff); - - if ((phys & ~0xfff) >= (1 << 30)) - readlookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; - else - readlookup2[virt>>12] = (uintptr_t)&ram[a]; - - readlookupp[readlnext] = mmu_perm; - readlookup[readlnext++] = virt >> 12; - readlnext &= (cachesize-1); - - sub_cycles(9); -} - - -void -addwritelookup(uint32_t virt, uint32_t phys) -{ - uint32_t a; - - if (virt == 0xffffffff) return; - - if (page_lookup[virt >> 12]) return; - - if (writelookup[writelnext] != -1) { - page_lookup[writelookup[writelnext]] = NULL; - writelookup2[writelookup[writelnext]] = -1; - } - -#ifdef USE_NEW_DYNAREC - if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) -#else -#ifdef USE_DYNAREC - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) -#else - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) -#endif -#endif - page_lookup[virt >> 12] = &pages[phys >> 12]; - else { - a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff); - - if ((phys & ~0xfff) >= (1 << 30)) - writelookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; - else - writelookup2[virt>>12] = (uintptr_t)&ram[a]; - } - - writelookupp[writelnext] = mmu_perm; - writelookup[writelnext++] = virt >> 12; - writelnext &= (cachesize - 1); - - sub_cycles(9); -} - - -uint8_t * -getpccache(uint32_t a) -{ - uint64_t a64 = (uint64_t) a; - uint32_t a2; - - a2 = a; - - if (cr0 >> 31) { - a64 = mmutranslate_read(a64); - - if (a64 == 0xffffffffffffffffULL) return ram; - } - a64 &= rammask; - - if (_mem_exec[a64 >> MEM_GRANULARITY_BITS]) { - if (is286) { - if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM)) - cpu_prefetch_cycles = cpu_rom_prefetch_cycles; - else - cpu_prefetch_cycles = cpu_mem_prefetch_cycles; - } - - return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t)(a64 & MEM_GRANULARITY_PAGE) - (uintptr_t)(a2 & ~0xfff)]; - } - - mem_log("Bad getpccache %08X%08X\n", (uint32_t) (a >> 32), (uint32_t) (a & 0xffffffff)); - -#if FIXME - return &ff_array[0-(uintptr_t)(a2 & ~0xfff)]; -#else - return (uint8_t *)&ff_pccache; -#endif -} - - -uint8_t -readmembl(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xff; - if (addr64 > 0xffffffffULL) - return 0xff; - } - addr = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_b) - return map->read_b(addr, map->p); - - return 0xff; -} - - -void -writemembl(uint32_t addr, uint8_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - mem_logical_addr = addr; - - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_b) { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; - } - - if (cr0 >> 31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->write_b) - map->write_b(addr, val, map->p); -} - - -#ifdef USE_NEW_DYNAREC -uint16_t -readmemwl(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr64 & 1) { - if (!cpu_cyrix_alignment || (addr64 & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr64 & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffff; - if (mmutranslate_read(addr+1) == 0xffffffffffffffffULL) - return 0xffff; - } - return readmembl(addr)|(readmembl(addr+1)<<8); - } else if (readlookup2[addr >> 12] != -1) - return *(uint16_t *)(readlookup2[addr >> 12] + addr); - } - if (cr0>>31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xffff; - if (addr64 > 0xffffffffULL) - return 0xffff; - } - - addr = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - return map->read_w(addr, map->p); - - if (map && map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); - - return 0xffff; -} - - -void -writememwl(uint32_t addr, uint16_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFFE) { - if (cr0 >> 31) { - if (mmutranslate_write(addr) == 0xffffffff) - return; - if (mmutranslate_write(addr+1) == 0xffffffff) - return; - } - writemembl(addr,val); - writemembl(addr+1,val>>8); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_w) { - page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_w) - map->write_w(addr, val, map->p); - else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - } - } -} - - -uint32_t -readmemll(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr & 0xfff) > 0xffc) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffffffff; - if (mmutranslate_read(addr+3) == 0xffffffffffffffffULL) - return 0xffffffff; - } - return readmemwl(addr)|(readmemwl(addr+2)<<16); - } else if (readlookup2[addr >> 12] != -1) - return *(uint32_t *)(readlookup2[addr >> 12] + addr); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffff; - if (addr64 > 0xffffffffULL) - return 0xffffffff; - } - - addr = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->read_l) - return map->read_l(addr, map->p); - - if (map->read_w) - return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); - - if (map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | - (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); - } - - return 0xffffffff; -} - - -void -writememll(uint32_t addr, uint32_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFFC) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffffffffffffULL) - return; - if (mmutranslate_write(addr+3) == 0xffffffffffffffffULL) - return; - } - writememwl(addr,val); - writememwl(addr+2,val>>16); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) - map->write_l(addr, val, map->p); - else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - } - } -} - - -uint64_t -readmemql(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 7) { - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (mmutranslate_read(addr+7) == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - } - return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); - } else if (readlookup2[addr >> 12] != -1) - return *(uint64_t *)(readlookup2[addr >> 12] + addr); - } - - if (cr0>>31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (addr64 > 0xffffffffULL) - return 0xffffffffffffffffULL; - } - - addr = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); - - return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); -} - - -void -writememql(uint32_t addr, uint64_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 7) { - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffffffffffffULL) - return; - if (mmutranslate_write(addr+7) == 0xffffffffffffffffULL) - return; - } - writememll(addr, val); - writememll(addr+4, val >> 32); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); - page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) { - map->write_l(addr, val, map->p); - map->write_l(addr + 4, val >> 32, map->p); - } else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - map->write_w(addr + 4, val >> 32, map->p); - map->write_w(addr + 6, val >> 48, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - map->write_b(addr + 4, val >> 32, map->p); - map->write_b(addr + 5, val >> 40, map->p); - map->write_b(addr + 6, val >> 48, map->p); - map->write_b(addr + 7, val >> 56, map->p); - } - } -} -#else -uint8_t -readmemb386l(uint32_t seg, uint32_t addr) -{ - return readmembl(addr + seg); -} - - -void -writememb386l(uint32_t seg, uint32_t addr, uint8_t val) -{ - writemembl(addr + seg, val); -} - - -uint16_t -readmemwl(uint32_t seg, uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 1) { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr2 & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) - return 0xffff; - if (mmutranslate_read(addr2+1) == 0xffffffffffffffffULL) - return 0xffff; - } - if (is386) return readmemb386l(seg,addr)|(((uint16_t) readmemb386l(seg,addr+1))<<8); - else return readmembl(seg+addr)|(((uint16_t) readmembl(seg+addr+1))<<8); - } - else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) - return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffff; - if (addr64 > 0xffffffffULL) - return 0xffff; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - return map->read_w(addr2, map->p); - - if (map && map->read_b) { - if (AT) - return map->read_b(addr2, map->p) | - ((uint16_t) (map->read_b(addr2 + 1, map->p)) << 8); - else - return map->read_b(addr2, map->p) | - ((uint16_t) (map->read_b(seg + ((addr + 1) & 0xffff), map->p)) << 8); - } - - return 0xffff; -} - - -void -writememwl(uint32_t seg, uint32_t addr, uint16_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 1) { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr2 & 0xFFF) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+1) == 0xffffffffffffffffULL) return; - } - if (is386) { - writememb386l(seg,addr,val); - writememb386l(seg,addr+1,val>>8); - } else { - writemembl(seg+addr,val); - writemembl(seg+addr+1,val>>8); - } - return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { - *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_w) { - page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); - return; - } - - if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->write_w) { - map->write_w(addr2, val, map->p); - return; - } - - if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - return; - } -} - - -uint32_t -readmemll(uint32_t seg, uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 3) { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr2 & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffff; - if (mmutranslate_read(addr2+3) == 0xffffffffffffffffULL) return 0xffffffff; - } - return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); - } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) - return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffff; - if (addr64 > 0xffffffffULL) - return 0xffffffff; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->read_l) - return map->read_l(addr2, map->p); - - if (map && map->read_w) - return map->read_w(addr2, map->p) | - ((uint32_t) (map->read_w(addr2 + 2, map->p)) << 16); - - if (map && map->read_b) - return map->read_b(addr2, map->p) | - ((uint32_t) (map->read_b(addr2 + 1, map->p)) << 8) | - ((uint32_t) (map->read_b(addr2 + 2, map->p)) << 16) | - ((uint32_t) (map->read_b(addr2 + 3, map->p)) << 24); - - return 0xffffffff; -} - - -void -writememll(uint32_t seg, uint32_t addr, uint32_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 3) { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr2 & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+3) == 0xffffffffffffffffULL) return; - } - writememwl(seg,addr,val); - writememwl(seg,addr+2,val>>16); - return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { - *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); - return; - } - - if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } else - addr64 = (uint32_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->write_l) { - map->write_l(addr2, val, map->p); - return; - } - if (map && map->write_w) { - map->write_w(addr2, val, map->p); - map->write_w(addr2 + 2, val >> 16, map->p); - return; - } - if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - map->write_b(addr2 + 2, val >> 16, map->p); - map->write_b(addr2 + 3, val >> 24, map->p); - return; - } -} - - -uint64_t -readmemql(uint32_t seg, uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 7) { - sub_cycles(timing_misaligned); - if ((addr2 & 0xfff) > 0xff8) { - if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; - if (mmutranslate_read(addr2+7) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; - } - return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); - } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) - return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (addr64 > 0xffffffffULL) - return 0xffffffffffffffffULL; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr2, map->p) | ((uint64_t)map->read_l(addr2 + 4, map->p) << 32); - - return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); -} - - -void -writememql(uint32_t seg, uint32_t addr, uint64_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (addr2 & 7) { - sub_cycles(timing_misaligned); - if ((addr2 & 0xfff) > 0xff8) { - if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+7) == 0xffffffffffffffffULL) return; - } - writememll(seg, addr, val); - writememll(seg, addr+4, val >> 32); - return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { - *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); - page_lookup[addr2>>12]->write_l(addr2 + 4, val >> 32, page_lookup[addr2>>12]); - return; - } - - if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->write_l) { - map->write_l(addr2, val, map->p); - map->write_l(addr2+4, val >> 32, map->p); - return; - } - if (map && map->write_w) { - map->write_w(addr2, val, map->p); - map->write_w(addr2 + 2, val >> 16, map->p); - map->write_w(addr2 + 4, val >> 32, map->p); - map->write_w(addr2 + 6, val >> 48, map->p); - return; - } - if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - map->write_b(addr2 + 2, val >> 16, map->p); - map->write_b(addr2 + 3, val >> 24, map->p); - map->write_b(addr2 + 4, val >> 32, map->p); - map->write_b(addr2 + 5, val >> 40, map->p); - map->write_b(addr2 + 6, val >> 48, map->p); - map->write_b(addr2 + 7, val >> 56, map->p); - return; - } -} -#endif - - -int -mem_mapping_is_romcs(uint32_t addr, int write) -{ - mem_mapping_t *map; - - if (write) - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - else - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map) - return !!(map->flags & MEM_MAPPING_ROMCS); - else - return 0; -} - - -uint8_t -mem_readb_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) - return _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]; - else if (map && map->read_b) - return map->read_b(addr, map->p); - else - return 0xff; -} - - -uint16_t -mem_readw_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - uint16_t temp, *p; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { - p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); - return *p; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) - return map->read_w(addr, map->p); - else { - temp = mem_readb_phys(addr + 1) << 8; - temp |= mem_readb_phys(addr); - } - - return temp; -} - - -uint32_t -mem_readl_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - uint32_t temp, *p; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { - p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); - return *p; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) - return map->read_l(addr, map->p); - else { - temp = mem_readw_phys(addr + 2) << 16; - temp |= mem_readw_phys(addr); - } - - return temp; -} - - -void -mem_read_phys(void *dest, uint32_t addr, int transfer_size) -{ - uint8_t *pb; - uint16_t *pw; - uint32_t *pl; - - if (transfer_size == 4) { - pl = (uint32_t *) dest; - *pl = mem_readl_phys(addr); - } else if (transfer_size == 2) { - pw = (uint16_t *) dest; - *pw = mem_readw_phys(addr); - } else if (transfer_size == 1) { - pb = (uint8_t *) dest; - *pb = mem_readb_phys(addr); - } -} - - -void -mem_writeb_phys(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) - _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; - else if (map && map->write_b) - map->write_b(addr, val, map->p); -} - - -void -mem_writew_phys(uint32_t addr, uint16_t val) -{ - mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - uint16_t *p; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { - p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); - *p = val; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (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]; - uint32_t *p; - - mem_logical_addr = 0xffffffff; - - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { - p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); - *p = val; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) - map->write_l(addr, val, map->p); - else { - mem_writew_phys(addr, val & 0xffff); - mem_writew_phys(addr + 2, (val >> 16) & 0xffff); - } -} - - -void -mem_write_phys(void *src, uint32_t addr, int transfer_size) -{ - uint8_t *pb; - uint16_t *pw; - uint32_t *pl; - - if (transfer_size == 4) { - pl = (uint32_t *) src; - mem_writel_phys(addr, *pl); - } else if (transfer_size == 2) { - pw = (uint16_t *) src; - mem_writew_phys(addr, *pw); - } else if (transfer_size == 1) { - pb = (uint8_t *) src; - mem_writeb_phys(addr, *pb); - } -} - - -uint8_t -mem_read_ram(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return ram[addr]; -} - - -uint16_t -mem_read_ramw(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint16_t *)&ram[addr]; -} - - -uint32_t -mem_read_raml(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint32_t *)&ram[addr]; -} - - -uint8_t -mem_read_ram_2gb(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return ram2[addr - (1 << 30)]; -} - - -uint16_t -mem_read_ram_2gbw(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint16_t *)&ram2[addr - (1 << 30)]; -} - - -uint32_t -mem_read_ram_2gbl(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint32_t *)&ram2[addr - (1 << 30)]; -} - - -uint8_t -mem_read_smram(uint32_t addr, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - if (new_addr >= (1 << 30)) - return mem_read_ram_2gb(new_addr, priv); - else - return mem_read_ram(new_addr, priv); -} - - -uint16_t -mem_read_smramw(uint32_t addr, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - if (new_addr >= (1 << 30)) - return mem_read_ram_2gbw(new_addr, priv); - else - return mem_read_ramw(new_addr, priv); -} - - -uint32_t -mem_read_smraml(uint32_t addr, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - if (new_addr >= (1 << 30)) - return mem_read_ram_2gbl(new_addr, priv); - else - return mem_read_raml(new_addr, priv); -} - - -#ifdef USE_NEW_DYNAREC -static inline int -page_index(page_t *p) -{ - return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); -} - - -void -page_add_to_evict_list(page_t *p) -{ - pages[purgable_page_list_head].evict_prev = page_index(p); - p->evict_next = purgable_page_list_head; - p->evict_prev = 0; - purgable_page_list_head = pages[purgable_page_list_head].evict_prev; - purgeable_page_count++; -} - - -void -page_remove_from_evict_list(page_t *p) -{ - if (!page_in_evict_list(p)) - fatal("page_remove_from_evict_list: not in evict list!\n"); - if (p->evict_prev) - pages[p->evict_prev].evict_next = p->evict_next; - else - purgable_page_list_head = p->evict_next; - if (p->evict_next) - pages[p->evict_next].evict_prev = p->evict_prev; - p->evict_prev = EVICT_NOT_IN_LIST; - purgeable_page_count--; -} - - -void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) -{ - if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); - - p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - p->byte_dirty_mask[byte_offset] |= byte_mask; - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - - -void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) -{ - if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - *(uint16_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { - p->byte_dirty_mask[byte_offset+1] |= 1; - if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } else - byte_mask |= (byte_mask << 1); - - p->byte_dirty_mask[byte_offset] |= byte_mask; - - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - - -void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) -{ - if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - *(uint32_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - p->byte_dirty_mask[byte_offset] |= byte_mask; - if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) { - uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); - - p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; - if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } - } -} -#else -void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) -{ -#ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - p->mem[addr & 0xfff] = val; - } -} - - -void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) -{ -#ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint16_t *)&p->mem[addr & 0xfff] = val; - } -} - - -void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) -{ -#ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint32_t *)&p->mem[addr & 0xfff] = val; - } -} -#endif - - -void -mem_write_ram(uint32_t addr, uint8_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write B %02X to %08X\n", val, addr); -#endif - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[addr >> 12]); -} - - -void -mem_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write W %04X to %08X\n", val, addr); -#endif - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[addr >> 12]); -} - - -void -mem_write_raml(uint32_t addr, uint32_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write L %08X to %08X\n", val, addr); -#endif - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[addr >> 12]); -} - - -void -mem_write_smram(uint32_t addr, uint8_t val, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - mem_write_ram(new_addr, val, priv); -} - - -void -mem_write_smramw(uint32_t addr, uint16_t val, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - mem_write_ramw(new_addr, val, priv); -} - - -void -mem_write_smraml(uint32_t addr, uint32_t val, void *priv) -{ - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; - - mem_write_raml(new_addr, val, priv); -} - - -static uint8_t -mem_read_remapped(uint32_t addr, void *priv) -{ - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return ram[addr]; -} - - -static uint16_t -mem_read_remappedw(uint32_t addr, void *priv) -{ - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram[addr]; -} - - -static uint32_t -mem_read_remappedl(uint32_t addr, void *priv) -{ - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram[addr]; -} - - -static void -mem_write_remapped(uint32_t addr, uint8_t val, void *priv) -{ - uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); -} - - -static void -mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) -{ - uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); -} - - -static void -mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) -{ - uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); -} - - -uint8_t -mem_read_bios(uint32_t addr, void *priv) -{ - uint8_t ret = 0xff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = rom[addr - biosaddr]; - - return ret; -} - - -uint16_t -mem_read_biosw(uint32_t addr, void *priv) -{ - uint16_t ret = 0xffff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint16_t *)&rom[addr - biosaddr]; - - return ret; -} - - -uint32_t -mem_read_biosl(uint32_t addr, void *priv) -{ - uint32_t ret = 0xffffffff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint32_t *)&rom[addr - biosaddr]; - - return ret; -} - - -void -mem_write_null(uint32_t addr, uint8_t val, void *p) -{ -} - - -void -mem_write_nullw(uint32_t addr, uint16_t val, void *p) -{ -} - - -void -mem_write_nulll(uint32_t addr, uint32_t val, void *p) -{ -} - - -void -mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) -{ - uint64_t mask; -#ifdef USE_NEW_DYNAREC - page_t *p; - - start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - - for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { - if ((start_addr >> 12) >= pages_sz) - continue; - - mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - p = &pages[start_addr >> 12]; - - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -#else - uint32_t cur_addr; - start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - - for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { - mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses - may crash the emulator. */ - cur_addr = (start_addr >> 12); - if (cur_addr < pages_sz) - pages[cur_addr].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - } -#endif -} - - -static __inline int -mem_mapping_read_allowed(uint32_t flags, uint32_t state, int exec) -{ - uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT; - uint32_t state_masked; - - if (in_smm && ((smm_state & MEM_READ_MASK) != MEM_READ_NORMAL)) - state = smm_state; - - state_masked = (state & MEM_READ_MASK); - - if (state_masked & MEM_READ_SMRAM) - return (flags & MEM_MAPPING_SMRAM); - else if ((state_masked & MEM_READ_SMRAM_EX) && exec) - return (flags & MEM_MAPPING_SMRAM); - else if (state_masked & MEM_READ_DISABLED_EX) - return 0; - else switch (state_masked) { - case MEM_READ_DISABLED: - return 0; - - case MEM_READ_ANY: - return !(flags & MEM_MAPPING_SMRAM); - - /* On external and 0 mappings without ROMCS. */ - case MEM_READ_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); - - /* On external and 0 mappings with ROMCS. */ - case MEM_READ_ROMCS: - return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); - - /* On any external mappings. */ - case MEM_READ_EXTANY: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); - - case MEM_READ_EXTERNAL_EX: - if (exec) - return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); - else - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); - - case MEM_READ_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); - - default: - fatal("mem_mapping_read_allowed : bad state %x\n", state); - } - - return 0; -} - - -static __inline int -mem_mapping_write_allowed(uint32_t flags, uint32_t state) -{ - uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT; - uint32_t state_masked; - - if (in_smm && ((smm_state & MEM_WRITE_MASK) != MEM_WRITE_NORMAL)) - state = smm_state; - - state_masked = (state & MEM_WRITE_MASK); - - if (state_masked & MEM_WRITE_SMRAM) - return (flags & MEM_MAPPING_SMRAM); - else if (state_masked & MEM_WRITE_DISABLED_EX) - return 0; - else switch (state_masked) { - case MEM_WRITE_DISABLED: - return 0; - - case MEM_WRITE_ANY: - return !(flags & MEM_MAPPING_SMRAM); - - /* On external and 0 mappings without ROMCS. */ - case MEM_WRITE_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); - - /* On external and 0 mappings with ROMCS. */ - case MEM_WRITE_ROMCS: - return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); - - /* On any external mappings. */ - case MEM_WRITE_EXTANY: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); - - case MEM_WRITE_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); - - default: - fatal("mem_mapping_write_allowed : bad state %x\n", state); - } - - return 0; -} - - -void -mem_mapping_recalc(uint64_t base, uint64_t size) -{ - mem_mapping_t *map = base_mapping.next; - uint64_t c; - - if (! size) return; - - /* Clear out old mappings. */ - for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { - read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - } - - /* Walk mapping list. */ - while (map != NULL) { - /*In range?*/ - if (map->enable && (uint64_t)map->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)map->base + (uint64_t)map->size) > (uint64_t)base) { - uint64_t start = (map->base < base) ? map->base : base; - uint64_t end = (((uint64_t)map->base + (uint64_t)map->size) < (base + size)) ? ((uint64_t)map->base + (uint64_t)map->size) : (base + size); - if (start < map->base) - start = map->base; - - for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { - if ((map->read_b || map->read_w || map->read_l) && - mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 0)) { -#ifdef ENABLE_MEM_LOG - if ((start >= 0xa0000) && (start <= 0xbffff)) - mem_log("Read allowed: %08X (mapping for %08X)\n", map, start); -#endif - read_mapping[c >> MEM_GRANULARITY_BITS] = map; - } - if (map->exec && - mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 1)) { -#ifdef ENABLE_MEM_LOG - if ((start >= 0xa0000) && (start <= 0xbffff)) - mem_log("Exec allowed: %08X (mapping for %08X)\n", map, start); -#endif - _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); - } - if ((map->write_b || map->write_w || map->write_l) && - mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) { -#ifdef ENABLE_MEM_LOG - if ((start >= 0xa0000) && (start <= 0xbffff)) - mem_log("Write allowed: %08X (mapping for %08X)\n", map, start); -#endif - write_mapping[c >> MEM_GRANULARITY_BITS] = map; - } - } - } - map = map->next; - } - - flushmmucache_cr3(); -} - - -void -mem_mapping_del(mem_mapping_t *map) -{ - mem_mapping_t *ptr; - - /* Disable the entry. */ - mem_mapping_disable(map); - - /* Zap it from the list. */ - for (ptr = &base_mapping; ptr->next != NULL; ptr = ptr->next) { - if (ptr->next == map) { - ptr->next = map->next; - break; - } - } -} - - -void -mem_mapping_add(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) -{ - mem_mapping_t *dest = &base_mapping; - - /* Add mapping to the end of the list.*/ - while (dest->next) - dest = dest->next; - dest->next = map; - map->prev = dest; - - if (size) - map->enable = 1; - else - map->enable = 0; - map->base = base; - map->size = size; - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - map->exec = exec; - map->flags = fl; - map->p = p; - map->dev = NULL; - map->next = NULL; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_do_recalc(mem_mapping_t *map) -{ - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_handler(mem_mapping_t *map, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)) -{ - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) -{ - /* Remove old mapping. */ - map->enable = 0; - mem_mapping_recalc(map->base, map->size); - - /* Set new mapping. */ - map->enable = 1; - map->base = base; - map->size = size; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) -{ - map->exec = exec; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_p(mem_mapping_t *map, void *p) -{ - map->p = p; -} - - -void -mem_mapping_set_dev(mem_mapping_t *map, void *p) -{ - map->dev = p; -} - - -void -mem_mapping_disable(mem_mapping_t *map) -{ - map->enable = 0; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_enable(mem_mapping_t *map) -{ - map->enable = 1; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state) -{ - uint32_t c; - - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { - if (smm) - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xf0f0ffff) | ((state & 0x0f0f) << MEM_STATE_SMM_SHIFT); - else - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xfffff0f0) | (state & 0x0f0f); -#ifdef ENABLE_MEM_LOG - if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) - mem_log("Set mem state for block at %08X to %02X\n", c + base, state); -#endif - } - - mem_mapping_recalc(base, size); -} - - -void -mem_set_mem_state_smram(int smm, uint32_t base, uint32_t size, int is_smram) -{ - uint32_t c, smstate = 0x0000; - - smstate = is_smram ? (MEM_READ_SMRAM | MEM_WRITE_SMRAM) : 0x0000; - - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { - if (smm) - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT); - else - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate; -#ifdef ENABLE_MEM_LOG - if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) - mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state); -#endif - } - - mem_mapping_recalc(base, size); -} - - -void -mem_set_mem_state_smram_ex(int smm, uint32_t base, uint32_t size, int is_smram) -{ - uint32_t c, smstate = 0x0000; - - switch (is_smram & 0x03) { - case 0x00: - smstate = 0x0000; - break; - case 0x01: - smstate = (MEM_READ_SMRAM | MEM_WRITE_SMRAM); - break; - case 0x02: - smstate = MEM_READ_SMRAM_EX; - break; - case 0x03: - smstate = (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX); - break; - } - - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { - if (smm) - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT); - else - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate; -#ifdef ENABLE_MEM_LOG - if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) - mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state); -#endif - } - - mem_mapping_recalc(base, size); -} - - -void -mem_set_mem_state(uint32_t base, uint32_t size, int state) -{ - mem_set_mem_state_common(0, base, size, state); -} - - -void -mem_set_mem_state_smm(uint32_t base, uint32_t size, int state) -{ - mem_set_mem_state_common(1, base, size, state); -} - - -void -mem_set_mem_state_both(uint32_t base, uint32_t size, int state) -{ - mem_set_mem_state_common(0, base, size, state); - mem_set_mem_state_common(1, base, size, state); -} - - -void -mem_add_bios(void) -{ - int temp_cpu_type, temp_cpu_16bitbus = 1; - - if (AT) { - temp_cpu_type = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type; - temp_cpu_16bitbus = (temp_cpu_type == CPU_286 || temp_cpu_type == CPU_386SX || temp_cpu_type == CPU_486SLC || temp_cpu_type == CPU_IBM386SLC || temp_cpu_type == CPU_IBM486SLC ); - } - - if (biosmask > 0x1ffff) { - /* 256k+ BIOS'es only have low mappings at E0000-FFFFF. */ - mem_mapping_add(&bios_mapping, 0xe0000, 0x20000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - &rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state_both(0x0e0000, 0x20000, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } else { - mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state_both(biosaddr, biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } - - if (AT) { - mem_mapping_add(&bios_high_mapping, biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state_both(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } -} - - -void -mem_a20_init(void) -{ - if (AT) { - rammask = cpu_16bitbus ? 0xefffff : 0xffefffff; - flushmmucache(); - mem_a20_state = mem_a20_key | mem_a20_alt; - } else { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - } -} - - -/* Reset the memory state. */ -void -mem_reset(void) -{ - uint32_t c, m, m2; - - m = 1024UL * mem_size; - if (ram != NULL) { - free(ram); - ram = NULL; - } - if (ram2 != NULL) { - free(ram2); - ram2 = NULL; - } - if (mem_size > 2097152) - fatal("Attempting to use more than 2 GB of guest RAM\n"); - - if (mem_size > 1048576) { - ram = (uint8_t *)malloc(1 << 30); /* allocate and clear the RAM block of the first 1 GB */ - memset(ram, 0x00, 1 << 30); - ram2 = (uint8_t *)malloc(m - (1 << 30)); /* allocate and clear the RAM block above 1 GB */ - memset(ram2, 0x00, m - (1 << 30)); - } else { - ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */ - memset(ram, 0x00, m); - } - - /* - * Allocate the page table based on how much RAM we have. - * We re-allocate the table on each (hard) reset, as the - * memory amount could have changed. - */ - if (AT) { - if (cpu_16bitbus) { - /* 80186/286; maximum address space is 16MB. */ - m = 4096; - } else { - /* 80386+; maximum address space is 4GB. */ - m = 1048576; - } - } else { - /* 8088/86; maximum address space is 1MB. */ - m = 256; - } - - /* Calculate the amount of pages used by RAM, so that we can - give all the pages above this amount NULL write handlers. */ - m2 = (mem_size + 384) >> 2; - if ((m2 << 2) < (mem_size + 384)) - m2++; - if (m2 < 4096) - m2 = 4096; - - /* - * Allocate and initialize the (new) page table. - * We only do this if the size of the page table has changed. - */ -#if DYNAMIC_TABLES -mem_log("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); -#endif - if (pages_sz != m) { - pages_sz = m; - if (pages) { - free(pages); - pages = NULL; - } - pages = (page_t *)malloc(m*sizeof(page_t)); -#if DYNAMIC_TABLES -mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); -#endif - -#if DYNAMIC_TABLES - /* Allocate the (new) lookup tables. */ - if (page_lookup != NULL) free(page_lookup); - page_lookup = (page_t **)malloc(pages_sz*sizeof(page_t *)); - - if (readlookup2 != NULL) free(readlookup2); - readlookup2 = malloc(pages_sz*sizeof(uintptr_t)); - - if (writelookup2 != NULL) free(writelookup2); - writelookup2 = malloc(pages_sz*sizeof(uintptr_t)); - -#endif - } - -#if DYNAMIC_TABLES - memset(page_lookup, 0x00, pages_sz * sizeof(page_t *)); -#else - memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); -#endif - - memset(pages, 0x00, pages_sz*sizeof(page_t)); - -#ifdef USE_NEW_DYNAREC - if (byte_dirty_mask) { - free(byte_dirty_mask); - byte_dirty_mask = NULL; - } - byte_dirty_mask = malloc((mem_size * 1024) / 8); - memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); - - if (byte_code_present_mask) { - free(byte_code_present_mask); - byte_code_present_mask = NULL; - } - byte_code_present_mask = malloc((mem_size * 1024) / 8); - memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); -#endif - - for (c = 0; c < pages_sz; c++) { - 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]; - if (c < m) { - 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 { - /* Make absolute sure non-RAM pages have NULL handlers so the - memory read/write handlers know to ignore them. */ - 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 - } - - memset(_mem_exec, 0x00, sizeof(_mem_exec)); - - memset(&base_mapping, 0x00, sizeof(base_mapping)); - - memset(_mem_state, 0x00, sizeof(_mem_state)); - - mem_set_mem_state_both(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state_both(0x0a0000, 0x60000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - mem_mapping_add(&ram_low_mapping, 0x00000, - (mem_size > 640) ? 0xa0000 : mem_size * 1024, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram, MEM_MAPPING_INTERNAL, NULL); - - if (mem_size > 1024) { - if (cpu_16bitbus && mem_size > 16256) { - mem_set_mem_state_both(0x100000, (16256 - 1024) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((16256 - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } else { - if (mem_size > 1048576) { - mem_set_mem_state_both(0x100000, (1048576 - 1024) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((1048576 - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_2gb_mapping, (1 << 30), - ((mem_size - 1048576) * 1024), - mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram2, MEM_MAPPING_INTERNAL, NULL); - } else { - mem_set_mem_state_both(0x100000, (mem_size - 1024) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((mem_size - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } - } - } - - /* if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); */ - if (mem_size > 768) { - mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); - } - - mem_mapping_add(&ram_smram_mapping[0], 0xa0000, 0x60000, - mem_read_smram,mem_read_smramw,mem_read_smraml, - mem_write_smram,mem_write_smramw,mem_write_smraml, - ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[0])); - mem_mapping_add(&ram_smram_mapping[1], 0xa0000, 0x60000, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[1])); - mem_mapping_disable(&ram_smram_mapping[0]); - mem_mapping_disable(&ram_smram_mapping[1]); - - 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); - - mem_a20_init(); - - smram[0].host_base = smram[0].ram_base = 0x00000000; - smram[1].host_base = smram[1].ram_base = 0x00000000; - -#ifdef USE_NEW_DYNAREC - purgable_page_list_head = 0; - purgeable_page_count = 0; -#endif -} - - -void -mem_init(void) -{ - /* Perform a one-time init. */ - ram = rom = NULL; - ram2 = NULL; - pages = NULL; -#if DYNAMIC_TABLES - page_lookup = NULL; - readlookup2 = NULL; - writelookup2 = NULL; - -#else - /* Allocate the lookup tables. */ - page_lookup = (page_t **)malloc((1<<20)*sizeof(page_t *)); - - readlookup2 = malloc((1<<20)*sizeof(uintptr_t)); - - writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); -#endif - -#if FIXME - memset(ff_array, 0xff, sizeof(ff_array)); -#endif - - /* Reset the memory state. */ - mem_reset(); -} - - -void -mem_remap_top(int kb) -{ - uint32_t c; - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int offset, size = mem_size - 640; - - mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); - if (mem_size <= 640) return; - - if (kb == 0) { - /* Called to disable the mapping. */ - mem_mapping_disable(&ram_remapped_mapping); - - return; - } - - if (size > kb) - size = kb; - - for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { - offset = c - ((start * 1024) >> 12); - pages[c].mem = &ram[0xA0000 + (offset << 12)]; - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; -#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]; -#endif - } - - mem_set_mem_state_both(start * 1024, size * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); - - flushmmucache(); -} - - -void -mem_reset_page_blocks(void) -{ - uint32_t c; - - if (pages == NULL) return; - - for (c = 0; c < pages_sz; c++) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; -#ifdef USE_NEW_DYNAREC - pages[c].block = BLOCK_INVALID; - pages[c].block_2 = BLOCK_INVALID; -#else - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; -#endif - } -} - - -void -mem_a20_recalc(void) -{ - int state; - - if (! AT) { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - - return; - } - - state = mem_a20_key | mem_a20_alt; - if (state && !mem_a20_state) { - rammask = (AT && cpu_16bitbus) ? 0xffffff : 0xffffffff; - flushmmucache(); - } else if (!state && mem_a20_state) { - rammask = (AT && cpu_16bitbus) ? 0xefffff : 0xffefffff; - flushmmucache(); - } - - mem_a20_state = state; -} +/* + * 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. + * + * Memory handling and MMU. + * + * NOTE: Experimenting with dynamically allocated lookup tables; + * the DYNAMIC_TABLES=1 enables this. Will eventually go + * away, either way... + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86_ops.h" +#include "x86.h" +#include <86box/machine.h> +#include <86box/m_xt_xi8088.h> +#include <86box/config.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#ifdef USE_DYNAREC +# include "codegen_public.h" +#else +#ifdef USE_NEW_DYNAREC +# define PAGE_MASK_SHIFT 6 +#else +# define PAGE_MASK_INDEX_MASK 3 +# define PAGE_MASK_INDEX_SHIFT 10 +# define PAGE_MASK_SHIFT 4 +#endif +# define PAGE_MASK_MASK 63 +#endif +#if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) +#define BLOCK_PC_INVALID 0xffffffff +#define BLOCK_INVALID 0 +#endif + + +#define FIXME 0 +#define DYNAMIC_TABLES 0 /* experimental */ + + +mem_mapping_t base_mapping, + ram_low_mapping, /* 0..640K mapping */ +#if 1 + ram_mid_mapping, +#endif + ram_remapped_mapping, /* 640..1024K mapping */ + ram_high_mapping, /* 1024K+ mapping */ + ram_2gb_mapping, /* 1024M+ mapping */ + ram_remapped_mapping, + ram_split_mapping, + ram_smram_mapping[2], + bios_mapping, + bios_high_mapping; + +page_t *pages, /* RAM page table */ + **page_lookup; /* pagetable lookup */ +uint32_t pages_sz; /* #pages in table */ + +uint8_t *ram, *ram2; /* the virtual RAM */ +uint32_t rammask; + +uint8_t *rom; /* the virtual ROM */ +uint32_t biosmask, biosaddr; + +uint32_t pccache; +uint8_t *pccache2; + +int readlnext; +int readlookup[256], + readlookupp[256]; +uintptr_t *readlookup2; +int writelnext; +int writelookup[256], + writelookupp[256]; +uintptr_t *writelookup2; + +uint32_t mem_logical_addr; + +int shadowbios = 0, + shadowbios_write; +int readlnum = 0, + writelnum = 0; +int cachesize = 256; + +uint32_t get_phys_virt, + get_phys_phys; + +smram_t smram[2] = { { 0x000a0000, 0x000a0000 }, { 0x000a0000, 0x000a0000 } }; + +int mem_a20_key = 0, + mem_a20_alt = 0, + mem_a20_state = 0; + +int mmuflush = 0; +int mmu_perm = 4; + +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + +uint32_t purgable_page_list_head = 0; +int purgeable_page_count = 0; + +int use_phys_exec = 0; + + +/* FIXME: re-do this with a 'mem_ops' struct. */ +static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; +static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; +static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; +static uint32_t _mem_state[MEM_MAPPINGS_NO]; + +#if FIXME +#if (MEM_GRANULARITY_BITS >= 12) +static uint8_t ff_array[MEM_GRANULARITY_SIZE]; +#else +static uint8_t ff_array[4096]; /* Must be at least one page. */ +#endif +#else +static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; +#endif + + +#ifdef ENABLE_MEM_LOG +int mem_do_log = ENABLE_MEM_LOG; + + +static void +mem_log(const char *fmt, ...) +{ + va_list ap; + + if (mem_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define mem_log(fmt, ...) +#endif + + +int +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); +} + + +void +resetreadlookup(void) +{ + int c; + + /* This is NULL after app startup, when mem_init() has not yet run. */ +#if DYNAMIC_TABLES +mem_log("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); +#endif + + /* Initialize the page lookup table. */ +#if DYNAMIC_TABLES + memset(page_lookup, 0x00, pages_sz*sizeof(page_t *)); +#else + memset(page_lookup, 0x00, (1<<20)*sizeof(page_t *)); +#endif + + /* Initialize the tables for lower (<= 1024K) RAM. */ + for (c = 0; c < 256; c++) { + readlookup[c] = 0xffffffff; + writelookup[c] = 0xffffffff; + } + + /* Initialize the tables for high (> 1024K) RAM. */ +#if DYNAMIC_TABLES + memset(readlookup2, 0xff, pages_sz*sizeof(uintptr_t)); + memset(writelookup2, 0xff, pages_sz*sizeof(uintptr_t)); +#else + memset(readlookup2, 0xff, (1<<20)*sizeof(uintptr_t)); + memset(writelookup2, 0xff, (1<<20)*sizeof(uintptr_t)); +#endif + + readlnext = 0; + writelnext = 0; + pccache = 0xffffffff; +} + + +void +flushmmucache(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = -1; + writelookup[c] = 0xffffffff; + } + } + mmuflush++; + + pccache = (uint32_t)0xffffffff; + pccache2 = (uint8_t *)0xffffffff; + +#ifdef USE_DYNAREC + codegen_flush(); +#endif +} + + +void +flushmmucache_nopc(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = -1; + writelookup[c] = 0xffffffff; + } + } +} + + +void +flushmmucache_cr3(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = -1; + writelookup[c] = 0xffffffff; + } + } +} + + +void +mem_flush_write_page(uint32_t addr, uint32_t virt) +{ + page_t *page_target = &pages[addr >> 12]; + int c; + uint32_t a; + + for (c = 0; c < 256; c++) { + if (writelookup[c] != (int) 0xffffffff) { + a = (uintptr_t)(addr & ~0xfff) - (virt & ~0xfff); + uintptr_t target; + + if ((addr & ~0xfff) >= (1 << 30)) + target = (uintptr_t)&ram2[a - (1 << 30)]; + else + target = (uintptr_t)&ram[a]; + + if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { + writelookup2[writelookup[c]] = -1; + page_lookup[writelookup[c]] = NULL; + writelookup[c] = 0xffffffff; + } + } + } +} + + +#define mmutranslate_read(addr) mmutranslatereal(addr,0) +#define mmutranslate_write(addr) mmutranslatereal(addr,1) +#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] +#define rammap64(x) ((uint64_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] + +static uint64_t +mmutranslatereal_normal(uint32_t addr, int rw) +{ + uint32_t temp,temp2,temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = rammap(addr2); + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) temp |= 4; + if (rw) temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap(addr2) |= 0x20; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + if (!(temp&1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) temp |= 4; + if (rw) temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap(addr2) |= 0x20; + rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw?0x60:0x20); + + return (uint64_t) ((temp&~0xfff)+(addr&0xfff)); +} + + +static uint64_t +mmutranslatereal_pae(uint32_t addr, int rw) +{ + uint64_t temp,temp2,temp3,temp4; + uint64_t addr2,addr3,addr4; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); + temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) temp |= 4; + if (rw) temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); + temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; + temp3 = temp & temp2; + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) temp |= 4; + if (rw) temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + if (temp & 0x80) { + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return 0xffffffffffffffffULL; + } + mmu_perm = temp & 4; + rammap64(addr3) |= 0x20; + + return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; + } + + addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); + temp = rammap64(addr4) & 0x000000ffffffffffULL; + temp3 = temp & temp4; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) temp |= 4; + if (rw) temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap64(addr3) |= 0x20; + rammap64(addr4) |= (rw? 0x60 : 0x20); + + return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; +} + + +uint64_t +mmutranslatereal(uint32_t addr, int rw) +{ + if (cr4 & CR4_PAE) + return mmutranslatereal_pae(addr, rw); + else + return mmutranslatereal_normal(addr, rw); +} + + +/* This is needed because the old recompiler calls this to check for page fault. */ +uint32_t +mmutranslatereal32(uint32_t addr, int rw) +{ + return (uint32_t) mmutranslatereal(addr, rw); +} + + +static uint64_t +mmutranslate_noabrt_normal(uint32_t addr, int rw) +{ + uint32_t temp,temp2,temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = rammap(addr2); + + if (! (temp & 1)) + return 0xffffffffffffffffULL; + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); +} + + +static uint64_t +mmutranslate_noabrt_pae(uint32_t addr, int rw) +{ + uint64_t temp,temp2,temp3,temp4; + uint64_t addr2,addr3,addr4; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); + temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; + + if (! (temp & 1)) + return 0xffffffffffffffffULL; + + addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); + temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; + temp3 = temp & temp2; + + if (! (temp & 1)) + return 0xffffffffffffffffULL; + + if (temp & 0x80) { + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; + } + + addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); + temp = rammap64(addr4) & 0x000000ffffffffffULL;; + temp3 = temp & temp4; + + if (!(temp&1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; +} + + +uint64_t +mmutranslate_noabrt(uint32_t addr, int rw) +{ + if (cr4 & CR4_PAE) + return mmutranslate_noabrt_pae(addr, rw); + else + return mmutranslate_noabrt_normal(addr, rw); +} + + +void +mmu_invalidate(uint32_t addr) +{ + flushmmucache_cr3(); +} + + +uint8_t +mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) +{ + if (addr < start) + return 0; + else if (addr >= (start + len)) + return 0; + else + return 1; +} + + +uint32_t +mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) +{ + uint32_t mask = len - 1; + + return chunk_start + (addr & mask); +} + + +void +addreadlookup(uint32_t virt, uint32_t phys) +{ + uint32_t a; + + if (virt == 0xffffffff) return; + + if (readlookup2[virt>>12] != (uintptr_t) -1) return; + + if (readlookup[readlnext] != (int) 0xffffffff) + readlookup2[readlookup[readlnext]] = -1; + + a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff); + + if ((phys & ~0xfff) >= (1 << 30)) + readlookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; + else + readlookup2[virt>>12] = (uintptr_t)&ram[a]; + + readlookupp[readlnext] = mmu_perm; + readlookup[readlnext++] = virt >> 12; + readlnext &= (cachesize-1); + + sub_cycles(9); +} + + +void +addwritelookup(uint32_t virt, uint32_t phys) +{ + uint32_t a; + + if (virt == 0xffffffff) return; + + if (page_lookup[virt >> 12]) return; + + if (writelookup[writelnext] != -1) { + page_lookup[writelookup[writelnext]] = NULL; + writelookup2[writelookup[writelnext]] = -1; + } + +#ifdef USE_NEW_DYNAREC +#ifdef USE_DYNAREC + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) +#else + if (pages[phys >> 12].block) +#endif +#else +#ifdef USE_DYNAREC + if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) +#else + if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) +#endif +#endif + page_lookup[virt >> 12] = &pages[phys >> 12]; + else { + a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff); + + if ((phys & ~0xfff) >= (1 << 30)) + writelookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; + else + writelookup2[virt>>12] = (uintptr_t)&ram[a]; + } + + writelookupp[writelnext] = mmu_perm; + writelookup[writelnext++] = virt >> 12; + writelnext &= (cachesize - 1); + + sub_cycles(9); +} + + +uint8_t * +getpccache(uint32_t a) +{ + uint64_t a64 = (uint64_t) a; + uint32_t a2; + + a2 = a; + + if (cr0 >> 31) { + a64 = mmutranslate_read(a64); + + if (a64 == 0xffffffffffffffffULL) return ram; + } + a64 &= rammask; + + if (_mem_exec[a64 >> MEM_GRANULARITY_BITS]) { + if (is286) { + if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM)) + cpu_prefetch_cycles = cpu_rom_prefetch_cycles; + else + cpu_prefetch_cycles = cpu_mem_prefetch_cycles; + } + + return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t)(a64 & MEM_GRANULARITY_PAGE) - (uintptr_t)(a2 & ~0xfff)]; + } + + mem_log("Bad getpccache %08X%08X\n", (uint32_t) (a >> 32), (uint32_t) (a & 0xffffffff)); + +#if FIXME + return &ff_array[0-(uintptr_t)(a2 & ~0xfff)]; +#else + return (uint8_t *)&ff_pccache; +#endif +} + + +uint8_t +readmembl(uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (cr0 >> 31) { + addr64 = mmutranslate_read(addr); + if (addr64 == 0xffffffffffffffffULL) + return 0xff; + if (addr64 > 0xffffffffULL) + return 0xff; + } + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->p); + + return 0xff; +} + + +void +writemembl(uint32_t addr, uint8_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + mem_logical_addr = addr; + + if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_b) { + page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); + return; + } + + if (cr0 >> 31) { + addr64 = mmutranslate_write(addr); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->p); +} + + +#ifdef USE_NEW_DYNAREC +uint16_t +readmemwl(uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr64 & 1) { + if (!cpu_cyrix_alignment || (addr64 & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr64 & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_read(addr) == 0xffffffffffffffffULL) + return 0xffff; + if (mmutranslate_read(addr+1) == 0xffffffffffffffffULL) + return 0xffff; + } + return readmembl(addr)|(readmembl(addr+1)<<8); + } else if (readlookup2[addr >> 12] != -1) + return *(uint16_t *)(readlookup2[addr >> 12] + addr); + } + if (cr0>>31) { + addr64 = mmutranslate_read(addr); + if (addr64 == 0xffffffffffffffffULL) + return 0xffff; + if (addr64 > 0xffffffffULL) + return 0xffff; + } + + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + + return 0xffff; +} + + +void +writememwl(uint32_t addr, uint16_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFFE) { + if (cr0 >> 31) { + if (mmutranslate_write(addr) == 0xffffffff) + return; + if (mmutranslate_write(addr+1) == 0xffffffff) + return; + } + writemembl(addr,val); + writemembl(addr+1,val>>8); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_w) { + page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr64 = mmutranslate_write(addr); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } + + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_w) + map->write_w(addr, val, map->p); + else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + } + } +} + + +uint32_t +readmemll(uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr & 0xfff) > 0xffc) { + if (cr0>>31) { + if (mmutranslate_read(addr) == 0xffffffffffffffffULL) + return 0xffffffff; + if (mmutranslate_read(addr+3) == 0xffffffffffffffffULL) + return 0xffffffff; + } + return readmemwl(addr)|(readmemwl(addr+2)<<16); + } else if (readlookup2[addr >> 12] != -1) + return *(uint32_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0 >> 31) { + addr64 = mmutranslate_read(addr); + if (addr64 == 0xffffffffffffffffULL) + return 0xffffffff; + if (addr64 > 0xffffffffULL) + return 0xffffffff; + } + + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->read_l) + return map->read_l(addr, map->p); + + if (map->read_w) + return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); + + if (map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | + (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); + } + + return 0xffffffff; +} + + +void +writememll(uint32_t addr, uint32_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFFC) { + if (cr0>>31) { + if (mmutranslate_write(addr) == 0xffffffffffffffffULL) + return; + if (mmutranslate_write(addr+3) == 0xffffffffffffffffULL) + return; + } + writememwl(addr,val); + writememwl(addr+2,val>>16); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr64 = mmutranslate_write(addr); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } + + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_l) + map->write_l(addr, val, map->p); + else if (map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + } else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + } + } +} + + +uint64_t +readmemql(uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 7) { + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFF8) { + if (cr0>>31) { + if (mmutranslate_read(addr) == 0xffffffffffffffffULL) + return 0xffffffffffffffffULL; + if (mmutranslate_read(addr+7) == 0xffffffffffffffffULL) + return 0xffffffffffffffffULL; + } + return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); + } else if (readlookup2[addr >> 12] != -1) + return *(uint64_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0>>31) { + addr64 = mmutranslate_read(addr); + if (addr64 == 0xffffffffffffffffULL) + return 0xffffffffffffffffULL; + if (addr64 > 0xffffffffULL) + return 0xffffffffffffffffULL; + } + + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_l) + return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); + + return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); +} + + +void +writememql(uint32_t addr, uint64_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 7) { + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFF8) { + if (cr0>>31) { + if (mmutranslate_write(addr) == 0xffffffffffffffffULL) + return; + if (mmutranslate_write(addr+7) == 0xffffffffffffffffULL) + return; + } + writememll(addr, val); + writememll(addr+4, val >> 32); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr64 = mmutranslate_write(addr); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } + + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_l) { + map->write_l(addr, val, map->p); + map->write_l(addr + 4, val >> 32, map->p); + } else if (map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + map->write_w(addr + 4, val >> 32, map->p); + map->write_w(addr + 6, val >> 48, map->p); + } else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + map->write_b(addr + 4, val >> 32, map->p); + map->write_b(addr + 5, val >> 40, map->p); + map->write_b(addr + 6, val >> 48, map->p); + map->write_b(addr + 7, val >> 56, map->p); + } + } +} +#else +uint8_t +readmemb386l(uint32_t seg, uint32_t addr) +{ + return readmembl(addr + seg); +} + + +void +writememb386l(uint32_t seg, uint32_t addr, uint8_t val) +{ + writemembl(addr + seg, val); +} + + +uint16_t +readmemwl(uint32_t seg, uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 1) { + if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr2 & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) + return 0xffff; + if (mmutranslate_read(addr2+1) == 0xffffffffffffffffULL) + return 0xffff; + } + if (is386) return readmemb386l(seg,addr)|(((uint16_t) readmemb386l(seg,addr+1))<<8); + else return readmembl(seg+addr)|(((uint16_t) readmembl(seg+addr+1))<<8); + } + else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) + return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (cr0 >> 31) { + addr64 = mmutranslate_read(addr2); + if (addr64 == 0xffffffffffffffffULL) + return 0xffff; + if (addr64 > 0xffffffffULL) + return 0xffff; + } else + addr64 = (uint64_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr2, map->p); + + if (map && map->read_b) { + if (AT) + return map->read_b(addr2, map->p) | + ((uint16_t) (map->read_b(addr2 + 1, map->p)) << 8); + else + return map->read_b(addr2, map->p) | + ((uint16_t) (map->read_b(seg + ((addr + 1) & 0xffff), map->p)) << 8); + } + + return 0xffff; +} + + +void +writememwl(uint32_t seg, uint32_t addr, uint16_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 1) { + if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr2 & 0xFFF) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; + if (mmutranslate_write(addr2+1) == 0xffffffffffffffffULL) return; + } + if (is386) { + writememb386l(seg,addr,val); + writememb386l(seg,addr+1,val>>8); + } else { + writemembl(seg+addr,val); + writemembl(seg+addr+1,val>>8); + } + return; + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { + *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_w) { + page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); + return; + } + + if (cr0 >> 31) { + addr64 = mmutranslate_write(addr2); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } else + addr64 = (uint64_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr2, val, map->p); + return; + } + + if (map && map->write_b) { + map->write_b(addr2, val, map->p); + map->write_b(addr2 + 1, val >> 8, map->p); + return; + } +} + + +uint32_t +readmemll(uint32_t seg, uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 3) { + if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr2 & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffff; + if (mmutranslate_read(addr2+3) == 0xffffffffffffffffULL) return 0xffffffff; + } + return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); + } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) + return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (cr0 >> 31) { + addr64 = mmutranslate_read(addr2); + if (addr64 == 0xffffffffffffffffULL) + return 0xffffffff; + if (addr64 > 0xffffffffULL) + return 0xffffffff; + } else + addr64 = (uint64_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; + + if (map && map->read_l) + return map->read_l(addr2, map->p); + + if (map && map->read_w) + return map->read_w(addr2, map->p) | + ((uint32_t) (map->read_w(addr2 + 2, map->p)) << 16); + + if (map && map->read_b) + return map->read_b(addr2, map->p) | + ((uint32_t) (map->read_b(addr2 + 1, map->p)) << 8) | + ((uint32_t) (map->read_b(addr2 + 2, map->p)) << 16) | + ((uint32_t) (map->read_b(addr2 + 3, map->p)) << 24); + + return 0xffffffff; +} + + +void +writememll(uint32_t seg, uint32_t addr, uint32_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 3) { + if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr2 & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; + if (mmutranslate_write(addr2+3) == 0xffffffffffffffffULL) return; + } + writememwl(seg,addr,val); + writememwl(seg,addr+2,val>>16); + return; + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { + *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { + page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); + return; + } + + if (cr0 >> 31) { + addr64 = mmutranslate_write(addr2); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } else + addr64 = (uint32_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr2, val, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr2, val, map->p); + map->write_w(addr2 + 2, val >> 16, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr2, val, map->p); + map->write_b(addr2 + 1, val >> 8, map->p); + map->write_b(addr2 + 2, val >> 16, map->p); + map->write_b(addr2 + 3, val >> 24, map->p); + return; + } +} + + +uint64_t +readmemql(uint32_t seg, uint32_t addr) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 7) { + sub_cycles(timing_misaligned); + if ((addr2 & 0xfff) > 0xff8) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; + if (mmutranslate_read(addr2+7) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; + } + return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); + } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) + return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (cr0 >> 31) { + addr64 = mmutranslate_read(addr2); + if (addr64 == 0xffffffffffffffffULL) + return 0xffffffffffffffffULL; + if (addr64 > 0xffffffffULL) + return 0xffffffffffffffffULL; + } else + addr64 = (uint64_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; + if (map && map->read_l) + return map->read_l(addr2, map->p) | ((uint64_t)map->read_l(addr2 + 4, map->p) << 32); + + return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); +} + + +void +writememql(uint32_t seg, uint32_t addr, uint64_t val) +{ + uint64_t addr64 = (uint64_t) addr; + mem_mapping_t *map; + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (addr2 & 7) { + sub_cycles(timing_misaligned); + if ((addr2 & 0xfff) > 0xff8) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; + if (mmutranslate_write(addr2+7) == 0xffffffffffffffffULL) return; + } + writememll(seg, addr, val); + writememll(seg, addr+4, val >> 32); + return; + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { + *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { + page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); + page_lookup[addr2>>12]->write_l(addr2 + 4, val >> 32, page_lookup[addr2>>12]); + return; + } + + if (cr0 >> 31) { + addr64 = mmutranslate_write(addr2); + if (addr64 == 0xffffffffffffffffULL) + return; + if (addr64 > 0xffffffffULL) + return; + } else + addr64 = (uint64_t) addr2; + + addr2 = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr2, val, map->p); + map->write_l(addr2+4, val >> 32, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr2, val, map->p); + map->write_w(addr2 + 2, val >> 16, map->p); + map->write_w(addr2 + 4, val >> 32, map->p); + map->write_w(addr2 + 6, val >> 48, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr2, val, map->p); + map->write_b(addr2 + 1, val >> 8, map->p); + map->write_b(addr2 + 2, val >> 16, map->p); + map->write_b(addr2 + 3, val >> 24, map->p); + map->write_b(addr2 + 4, val >> 32, map->p); + map->write_b(addr2 + 5, val >> 40, map->p); + map->write_b(addr2 + 6, val >> 48, map->p); + map->write_b(addr2 + 7, val >> 56, map->p); + return; + } +} +#endif + + +int +mem_mapping_is_romcs(uint32_t addr, int write) +{ + mem_mapping_t *map; + + if (write) + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + else + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map) + return !!(map->flags & MEM_MAPPING_ROMCS); + else + return 0; +} + + +uint8_t +mem_readb_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) + return _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]; + else if (map && map->read_b) + return map->read_b(addr, map->p); + else + return 0xff; +} + + +uint16_t +mem_readw_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint16_t temp, *p; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); + return *p; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) + return map->read_w(addr, map->p); + else { + temp = mem_readb_phys(addr + 1) << 8; + temp |= mem_readb_phys(addr); + } + + return temp; +} + + +uint32_t +mem_readl_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint32_t temp, *p; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); + return *p; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) + return map->read_l(addr, map->p); + else { + temp = mem_readw_phys(addr + 2) << 16; + temp |= mem_readw_phys(addr); + } + + return temp; +} + + +void +mem_read_phys(void *dest, uint32_t addr, int transfer_size) +{ + uint8_t *pb; + uint16_t *pw; + uint32_t *pl; + + if (transfer_size == 4) { + pl = (uint32_t *) dest; + *pl = mem_readl_phys(addr); + } else if (transfer_size == 2) { + pw = (uint16_t *) dest; + *pw = mem_readw_phys(addr); + } else if (transfer_size == 1) { + pb = (uint8_t *) dest; + *pb = mem_readb_phys(addr); + } +} + + +void +mem_writeb_phys(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) + _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; + else if (map && map->write_b) + map->write_b(addr, val, map->p); +} + + +void +mem_writew_phys(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + uint16_t *p; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); + *p = val; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (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]; + uint32_t *p; + + mem_logical_addr = 0xffffffff; + + if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); + *p = val; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) + map->write_l(addr, val, map->p); + else { + mem_writew_phys(addr, val & 0xffff); + mem_writew_phys(addr + 2, (val >> 16) & 0xffff); + } +} + + +void +mem_write_phys(void *src, uint32_t addr, int transfer_size) +{ + uint8_t *pb; + uint16_t *pw; + uint32_t *pl; + + if (transfer_size == 4) { + pl = (uint32_t *) src; + mem_writel_phys(addr, *pl); + } else if (transfer_size == 2) { + pw = (uint16_t *) src; + mem_writew_phys(addr, *pw); + } else if (transfer_size == 1) { + pb = (uint8_t *) src; + mem_writeb_phys(addr, *pb); + } +} + + +uint8_t +mem_read_ram(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read B %02X from %08X\n", ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return ram[addr]; +} + + +uint16_t +mem_read_ramw(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *)&ram[addr]; +} + + +uint32_t +mem_read_raml(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint32_t *)&ram[addr]; +} + + +uint8_t +mem_read_ram_2gb(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read B %02X from %08X\n", ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return ram2[addr - (1 << 30)]; +} + + +uint16_t +mem_read_ram_2gbw(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *)&ram2[addr - (1 << 30)]; +} + + +uint32_t +mem_read_ram_2gbl(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint32_t *)&ram2[addr - (1 << 30)]; +} + + +uint8_t +mem_read_smram(uint32_t addr, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + if (new_addr >= (1 << 30)) + return mem_read_ram_2gb(new_addr, priv); + else + return mem_read_ram(new_addr, priv); +} + + +uint16_t +mem_read_smramw(uint32_t addr, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + if (new_addr >= (1 << 30)) + return mem_read_ram_2gbw(new_addr, priv); + else + return mem_read_ramw(new_addr, priv); +} + + +uint32_t +mem_read_smraml(uint32_t addr, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + if (new_addr >= (1 << 30)) + return mem_read_ram_2gbl(new_addr, priv); + else + return mem_read_raml(new_addr, priv); +} + + +#ifdef USE_NEW_DYNAREC +static inline int +page_index(page_t *p) +{ + return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); +} + + +void +page_add_to_evict_list(page_t *p) +{ + pages[purgable_page_list_head].evict_prev = page_index(p); + p->evict_next = purgable_page_list_head; + p->evict_prev = 0; + purgable_page_list_head = pages[purgable_page_list_head].evict_prev; + purgeable_page_count++; +} + + +void +page_remove_from_evict_list(page_t *p) +{ + if (!page_in_evict_list(p)) + fatal("page_remove_from_evict_list: not in evict list!\n"); + if (p->evict_prev) + pages[p->evict_prev].evict_next = p->evict_next; + else + purgable_page_list_head = p->evict_next; + if (p->evict_next) + pages[p->evict_next].evict_prev = p->evict_prev; + p->evict_prev = EVICT_NOT_IN_LIST; + purgeable_page_count--; +} + + +void +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { +#else + if (val != p->mem[addr & 0xfff]) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + + p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + + +void +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { +#else + if (val != *(uint16_t *)&p->mem[addr & 0xfff]) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + *(uint16_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { + p->byte_dirty_mask[byte_offset+1] |= 1; + if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } else + byte_mask |= (byte_mask << 1); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + + +void +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { +#else + if (val != *(uint32_t *)&p->mem[addr & 0xfff]) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + *(uint32_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + p->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + + p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; + if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } + } +} +#else +void +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { +#else + if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff])) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + p->mem[addr & 0xfff] = val; + } +} + + +void +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { +#else + if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint16_t *)&p->mem[addr & 0xfff] = val; + } +} + + +void +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ +#ifdef USE_DYNAREC + if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { +#else + if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { +#endif + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint32_t *)&p->mem[addr & 0xfff] = val; + } +} +#endif + + +void +mem_write_ram(uint32_t addr, uint8_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write B %02X to %08X\n", val, addr); +#endif + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[addr >> 12]); +} + + +void +mem_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write W %04X to %08X\n", val, addr); +#endif + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[addr >> 12]); +} + + +void +mem_write_raml(uint32_t addr, uint32_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write L %08X to %08X\n", val, addr); +#endif + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[addr >> 12]); +} + + +void +mem_write_smram(uint32_t addr, uint8_t val, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + mem_write_ram(new_addr, val, priv); +} + + +void +mem_write_smramw(uint32_t addr, uint16_t val, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + mem_write_ramw(new_addr, val, priv); +} + + +void +mem_write_smraml(uint32_t addr, uint32_t val, void *priv) +{ + smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; + + mem_write_raml(new_addr, val, priv); +} + + +static uint8_t +mem_read_remapped(uint32_t addr, void *priv) +{ + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + + +static uint16_t +mem_read_remappedw(uint32_t addr, void *priv) +{ + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *)&ram[addr]; +} + + +static uint32_t +mem_read_remappedl(uint32_t addr, void *priv) +{ + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *)&ram[addr]; +} + + +static void +mem_write_remapped(uint32_t addr, uint8_t val, void *priv) +{ + uint32_t oldaddr = addr; + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); +} + + +static void +mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) +{ + uint32_t oldaddr = addr; + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); +} + + +static void +mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) +{ + uint32_t oldaddr = addr; + if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) + addr = 0xA0000 + (addr - (mem_size * 1024)); + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); +} + + +uint8_t +mem_read_bios(uint32_t addr, void *priv) +{ + uint8_t ret = 0xff; + + addr &= 0x000fffff; + + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = rom[addr - biosaddr]; + + return ret; +} + + +uint16_t +mem_read_biosw(uint32_t addr, void *priv) +{ + uint16_t ret = 0xffff; + + addr &= 0x000fffff; + + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint16_t *)&rom[addr - biosaddr]; + + return ret; +} + + +uint32_t +mem_read_biosl(uint32_t addr, void *priv) +{ + uint32_t ret = 0xffffffff; + + addr &= 0x000fffff; + + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint32_t *)&rom[addr - biosaddr]; + + return ret; +} + + +void +mem_write_null(uint32_t addr, uint8_t val, void *p) +{ +} + + +void +mem_write_nullw(uint32_t addr, uint16_t val, void *p) +{ +} + + +void +mem_write_nulll(uint32_t addr, uint32_t val, void *p) +{ +} + + +void +mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) +{ + uint64_t mask; +#ifdef USE_NEW_DYNAREC + page_t *p; + + start_addr &= ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + + for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { + if ((start_addr >> 12) >= pages_sz) + continue; + + mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + + p = &pages[start_addr >> 12]; + + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +#else + uint32_t cur_addr; + start_addr &= ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + + for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { + mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + + /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses + may crash the emulator. */ + cur_addr = (start_addr >> 12); + if (cur_addr < pages_sz) + pages[cur_addr].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + } +#endif +} + + +static __inline int +mem_mapping_read_allowed(uint32_t flags, uint32_t state, int exec) +{ + uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT; + uint32_t state_masked; + + if (in_smm && ((smm_state & MEM_READ_MASK) != MEM_READ_NORMAL)) + state = smm_state; + + state_masked = (state & MEM_READ_MASK); + + if (state_masked & MEM_READ_SMRAM) + return (flags & MEM_MAPPING_SMRAM); + else if ((state_masked & MEM_READ_SMRAM_EX) && exec) + return (flags & MEM_MAPPING_SMRAM); + else if (state_masked & MEM_READ_DISABLED_EX) + return 0; + else switch (state_masked) { + case MEM_READ_DISABLED: + return 0; + + case MEM_READ_ANY: + return !(flags & MEM_MAPPING_SMRAM); + + /* On external and 0 mappings without ROMCS. */ + case MEM_READ_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); + + /* On external and 0 mappings with ROMCS. */ + case MEM_READ_ROMCS: + return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); + + /* On any external mappings. */ + case MEM_READ_EXTANY: + return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); + + case MEM_READ_EXTERNAL_EX: + if (exec) + return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + else + return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); + + case MEM_READ_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + + default: + fatal("mem_mapping_read_allowed : bad state %x\n", state); + } + + return 0; +} + + +static __inline int +mem_mapping_write_allowed(uint32_t flags, uint32_t state) +{ + uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT; + uint32_t state_masked; + + if (in_smm && ((smm_state & MEM_WRITE_MASK) != MEM_WRITE_NORMAL)) + state = smm_state; + + state_masked = (state & MEM_WRITE_MASK); + + if (state_masked & MEM_WRITE_SMRAM) + return (flags & MEM_MAPPING_SMRAM); + else if (state_masked & MEM_WRITE_DISABLED_EX) + return 0; + else switch (state_masked) { + case MEM_WRITE_DISABLED: + return 0; + + case MEM_WRITE_ANY: + return !(flags & MEM_MAPPING_SMRAM); + + /* On external and 0 mappings without ROMCS. */ + case MEM_WRITE_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); + + /* On external and 0 mappings with ROMCS. */ + case MEM_WRITE_ROMCS: + return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM); + + /* On any external mappings. */ + case MEM_WRITE_EXTANY: + return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); + + case MEM_WRITE_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + + default: + fatal("mem_mapping_write_allowed : bad state %x\n", state); + } + + return 0; +} + + +void +mem_mapping_recalc(uint64_t base, uint64_t size) +{ + mem_mapping_t *map = base_mapping.next; + uint64_t c; + + if (! size) return; + + /* Clear out old mappings. */ + for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { + read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; + } + + /* Walk mapping list. */ + while (map != NULL) { + /*In range?*/ + if (map->enable && (uint64_t)map->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)map->base + (uint64_t)map->size) > (uint64_t)base) { + uint64_t start = (map->base < base) ? map->base : base; + uint64_t end = (((uint64_t)map->base + (uint64_t)map->size) < (base + size)) ? ((uint64_t)map->base + (uint64_t)map->size) : (base + size); + if (start < map->base) + start = map->base; + + for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { + if ((map->read_b || map->read_w || map->read_l) && + mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 0)) { +#ifdef ENABLE_MEM_LOG + if ((start >= 0xa0000) && (start <= 0xbffff)) + mem_log("Read allowed: %08X (mapping for %08X)\n", map, start); +#endif + read_mapping[c >> MEM_GRANULARITY_BITS] = map; + } + if (map->exec && + mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 1)) { +#ifdef ENABLE_MEM_LOG + if ((start >= 0xa0000) && (start <= 0xbffff)) + mem_log("Exec allowed: %08X (mapping for %08X)\n", map, start); +#endif + _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); + } + if ((map->write_b || map->write_w || map->write_l) && + mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) { +#ifdef ENABLE_MEM_LOG + if ((start >= 0xa0000) && (start <= 0xbffff)) + mem_log("Write allowed: %08X (mapping for %08X)\n", map, start); +#endif + write_mapping[c >> MEM_GRANULARITY_BITS] = map; + } + } + } + map = map->next; + } + + flushmmucache_cr3(); +} + + +void +mem_mapping_del(mem_mapping_t *map) +{ + mem_mapping_t *ptr; + + /* Disable the entry. */ + mem_mapping_disable(map); + + /* Zap it from the list. */ + for (ptr = &base_mapping; ptr->next != NULL; ptr = ptr->next) { + if (ptr->next == map) { + ptr->next = map->next; + break; + } + } +} + + +void +mem_mapping_add(mem_mapping_t *map, + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, + uint32_t fl, + void *p) +{ + mem_mapping_t *dest = &base_mapping; + + /* Add mapping to the end of the list.*/ + while (dest->next) + dest = dest->next; + dest->next = map; + map->prev = dest; + + if (size) + map->enable = 1; + else + map->enable = 0; + map->base = base; + map->size = size; + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + map->exec = exec; + map->flags = fl; + map->p = p; + map->dev = NULL; + map->next = NULL; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_do_recalc(mem_mapping_t *map) +{ + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_set_handler(mem_mapping_t *map, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p)) +{ + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) +{ + /* Remove old mapping. */ + map->enable = 0; + mem_mapping_recalc(map->base, map->size); + + /* Set new mapping. */ + map->enable = 1; + map->base = base; + map->size = size; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) +{ + map->exec = exec; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_set_p(mem_mapping_t *map, void *p) +{ + map->p = p; +} + + +void +mem_mapping_set_dev(mem_mapping_t *map, void *p) +{ + map->dev = p; +} + + +void +mem_mapping_disable(mem_mapping_t *map) +{ + map->enable = 0; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_enable(mem_mapping_t *map) +{ + map->enable = 1; + + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state) +{ + uint32_t c; + + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + if (smm) + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xf0f0ffff) | ((state & 0x0f0f) << MEM_STATE_SMM_SHIFT); + else + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xfffff0f0) | (state & 0x0f0f); +#ifdef ENABLE_MEM_LOG + if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) + mem_log("Set mem state for block at %08X to %02X\n", c + base, state); +#endif + } + + mem_mapping_recalc(base, size); +} + + +void +mem_set_mem_state_smram(int smm, uint32_t base, uint32_t size, int is_smram) +{ + uint32_t c, smstate = 0x0000; + + smstate = is_smram ? (MEM_READ_SMRAM | MEM_WRITE_SMRAM) : 0x0000; + + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + if (smm) + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT); + else + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate; +#ifdef ENABLE_MEM_LOG + if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) + mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state); +#endif + } + + mem_mapping_recalc(base, size); +} + + +void +mem_set_mem_state_smram_ex(int smm, uint32_t base, uint32_t size, int is_smram) +{ + uint32_t c, smstate = 0x0000; + + switch (is_smram & 0x03) { + case 0x00: + smstate = 0x0000; + break; + case 0x01: + smstate = (MEM_READ_SMRAM | MEM_WRITE_SMRAM); + break; + case 0x02: + smstate = MEM_READ_SMRAM_EX; + break; + case 0x03: + smstate = (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX); + break; + } + + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + if (smm) + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT); + else + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate; +#ifdef ENABLE_MEM_LOG + if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) + mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state); +#endif + } + + mem_mapping_recalc(base, size); +} + + +void +mem_set_mem_state(uint32_t base, uint32_t size, int state) +{ + mem_set_mem_state_common(0, base, size, state); +} + + +void +mem_set_mem_state_smm(uint32_t base, uint32_t size, int state) +{ + mem_set_mem_state_common(1, base, size, state); +} + + +void +mem_set_mem_state_both(uint32_t base, uint32_t size, int state) +{ + mem_set_mem_state_common(0, base, size, state); + mem_set_mem_state_common(1, base, size, state); +} + + +void +mem_add_bios(void) +{ + int temp_cpu_type, temp_cpu_16bitbus = 1; + + if (AT) { + temp_cpu_type = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type; + temp_cpu_16bitbus = (temp_cpu_type == CPU_286 || temp_cpu_type == CPU_386SX || temp_cpu_type == CPU_486SLC || temp_cpu_type == CPU_IBM386SLC || temp_cpu_type == CPU_IBM486SLC ); + } + + if (biosmask > 0x1ffff) { + /* 256k+ BIOS'es only have low mappings at E0000-FFFFF. */ + mem_mapping_add(&bios_mapping, 0xe0000, 0x20000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + &rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + + mem_set_mem_state_both(0x0e0000, 0x20000, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); + } else { + mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + + mem_set_mem_state_both(biosaddr, biosmask + 1, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); + } + + if (AT) { + mem_mapping_add(&bios_high_mapping, biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + + mem_set_mem_state_both(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); + } +} + + +void +mem_a20_init(void) +{ + if (AT) { + rammask = cpu_16bitbus ? 0xefffff : 0xffefffff; + flushmmucache(); + mem_a20_state = mem_a20_key | mem_a20_alt; + } else { + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + } +} + + +/* Reset the memory state. */ +void +mem_reset(void) +{ + uint32_t c, m, m2; + + m = 1024UL * mem_size; + if (ram != NULL) { + free(ram); + ram = NULL; + } + if (ram2 != NULL) { + free(ram2); + ram2 = NULL; + } + if (mem_size > 2097152) + fatal("Attempting to use more than 2 GB of guest RAM\n"); + + if (mem_size > 1048576) { + ram = (uint8_t *)malloc(1 << 30); /* allocate and clear the RAM block of the first 1 GB */ + memset(ram, 0x00, 1 << 30); + ram2 = (uint8_t *)malloc(m - (1 << 30)); /* allocate and clear the RAM block above 1 GB */ + memset(ram2, 0x00, m - (1 << 30)); + } else { + ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */ + memset(ram, 0x00, m); + } + + /* + * Allocate the page table based on how much RAM we have. + * We re-allocate the table on each (hard) reset, as the + * memory amount could have changed. + */ + if (AT) { + if (cpu_16bitbus) { + /* 80186/286; maximum address space is 16MB. */ + m = 4096; + } else { + /* 80386+; maximum address space is 4GB. */ + m = 1048576; + } + } else { + /* 8088/86; maximum address space is 1MB. */ + m = 256; + } + + /* Calculate the amount of pages used by RAM, so that we can + give all the pages above this amount NULL write handlers. */ + m2 = (mem_size + 384) >> 2; + if ((m2 << 2) < (mem_size + 384)) + m2++; + if (m2 < 4096) + m2 = 4096; + + /* + * Allocate and initialize the (new) page table. + * We only do this if the size of the page table has changed. + */ +#if DYNAMIC_TABLES +mem_log("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); +#endif + if (pages_sz != m) { + pages_sz = m; + if (pages) { + free(pages); + pages = NULL; + } + pages = (page_t *)malloc(m*sizeof(page_t)); +#if DYNAMIC_TABLES +mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); +#endif + +#if DYNAMIC_TABLES + /* Allocate the (new) lookup tables. */ + if (page_lookup != NULL) free(page_lookup); + page_lookup = (page_t **)malloc(pages_sz*sizeof(page_t *)); + + if (readlookup2 != NULL) free(readlookup2); + readlookup2 = malloc(pages_sz*sizeof(uintptr_t)); + + if (writelookup2 != NULL) free(writelookup2); + writelookup2 = malloc(pages_sz*sizeof(uintptr_t)); + +#endif + } + +#if DYNAMIC_TABLES + memset(page_lookup, 0x00, pages_sz * sizeof(page_t *)); +#else + memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); +#endif + + memset(pages, 0x00, pages_sz*sizeof(page_t)); + +#ifdef USE_NEW_DYNAREC + if (byte_dirty_mask) { + free(byte_dirty_mask); + byte_dirty_mask = NULL; + } + byte_dirty_mask = malloc((mem_size * 1024) / 8); + memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); + + if (byte_code_present_mask) { + free(byte_code_present_mask); + byte_code_present_mask = NULL; + } + byte_code_present_mask = malloc((mem_size * 1024) / 8); + memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); +#endif + + for (c = 0; c < pages_sz; c++) { + 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]; + if (c < m) { + 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 { + /* Make absolute sure non-RAM pages have NULL handlers so the + memory read/write handlers know to ignore them. */ + 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 + } + + memset(_mem_exec, 0x00, sizeof(_mem_exec)); + + memset(&base_mapping, 0x00, sizeof(base_mapping)); + + memset(_mem_state, 0x00, sizeof(_mem_state)); + + mem_set_mem_state_both(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state_both(0x0a0000, 0x60000, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + mem_mapping_add(&ram_low_mapping, 0x00000, + (mem_size > 640) ? 0xa0000 : mem_size * 1024, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram, MEM_MAPPING_INTERNAL, NULL); + + if (mem_size > 1024) { + if (cpu_16bitbus && mem_size > 16256) { + mem_set_mem_state_both(0x100000, (16256 - 1024) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_high_mapping, 0x100000, + ((16256 - 1024) * 1024), + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); + } else { + if (mem_size > 1048576) { + mem_set_mem_state_both(0x100000, (1048576 - 1024) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_high_mapping, 0x100000, + ((1048576 - 1024) * 1024), + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); + mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_2gb_mapping, (1 << 30), + ((mem_size - 1048576) * 1024), + mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram2, MEM_MAPPING_INTERNAL, NULL); + } else { + mem_set_mem_state_both(0x100000, (mem_size - 1024) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_high_mapping, 0x100000, + ((mem_size - 1024) * 1024), + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); + } + } + } + + /* if (mem_size > 768) + mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); */ + if (mem_size > 768) { + mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); + } + + mem_mapping_add(&ram_smram_mapping[0], 0xa0000, 0x60000, + mem_read_smram,mem_read_smramw,mem_read_smraml, + mem_write_smram,mem_write_smramw,mem_write_smraml, + ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[0])); + mem_mapping_add(&ram_smram_mapping[1], 0xa0000, 0x60000, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[1])); + mem_mapping_disable(&ram_smram_mapping[0]); + mem_mapping_disable(&ram_smram_mapping[1]); + + 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); + + mem_a20_init(); + + smram[0].host_base = smram[0].ram_base = 0x00000000; + smram[1].host_base = smram[1].ram_base = 0x00000000; + +#ifdef USE_NEW_DYNAREC + purgable_page_list_head = 0; + purgeable_page_count = 0; +#endif +} + + +void +mem_init(void) +{ + /* Perform a one-time init. */ + ram = rom = NULL; + ram2 = NULL; + pages = NULL; +#if DYNAMIC_TABLES + page_lookup = NULL; + readlookup2 = NULL; + writelookup2 = NULL; + +#else + /* Allocate the lookup tables. */ + page_lookup = (page_t **)malloc((1<<20)*sizeof(page_t *)); + + readlookup2 = malloc((1<<20)*sizeof(uintptr_t)); + + writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); +#endif + +#if FIXME + memset(ff_array, 0xff, sizeof(ff_array)); +#endif + + /* Reset the memory state. */ + mem_reset(); +} + + +void +mem_remap_top(int kb) +{ + uint32_t c; + uint32_t start = (mem_size >= 1024) ? mem_size : 1024; + int offset, size = mem_size - 640; + + mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); + if (mem_size <= 640) return; + + if (kb == 0) { + /* Called to disable the mapping. */ + mem_mapping_disable(&ram_remapped_mapping); + + return; + } + + if (size > kb) + size = kb; + + for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { + offset = c - ((start * 1024) >> 12); + pages[c].mem = &ram[0xA0000 + (offset << 12)]; + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; +#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]; +#endif + } + + mem_set_mem_state_both(start * 1024, size * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); + + flushmmucache(); +} + + +void +mem_reset_page_blocks(void) +{ + uint32_t c; + + if (pages == NULL) return; + + for (c = 0; c < pages_sz; c++) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; +#ifdef USE_NEW_DYNAREC + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; +#else + pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; + pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; +#endif + } +} + + +void +mem_a20_recalc(void) +{ + int state; + + if (! AT) { + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + + return; + } + + state = mem_a20_key | mem_a20_alt; + if (state && !mem_a20_state) { + rammask = (AT && cpu_16bitbus) ? 0xffffff : 0xffffffff; + flushmmucache(); + } else if (!state && mem_a20_state) { + rammask = (AT && cpu_16bitbus) ? 0xefffff : 0xffefffff; + flushmmucache(); + } + + mem_a20_state = state; +} diff --git a/src/rom.c b/src/mem/rom.c similarity index 100% rename from src/rom.c rename to src/mem/rom.c diff --git a/src/spd.c b/src/mem/spd.c similarity index 100% rename from src/spd.c rename to src/mem/spd.c diff --git a/src/sst_flash.c b/src/mem/sst_flash.c similarity index 95% rename from src/sst_flash.c rename to src/mem/sst_flash.c index 468d5d48a..6acd4440b 100644 --- a/src/sst_flash.c +++ b/src/mem/sst_flash.c @@ -1,458 +1,458 @@ -/* - * 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. - * - * Implementation of an SST flash chip. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/mem.h> -#include <86box/machine.h> -#include <86box/timer.h> -#include <86box/nvr.h> -#include <86box/plat.h> - - -typedef struct sst_t -{ - uint8_t id, is_39, page_bytes, sdp; - - int command_state, id_mode, - dirty; - - uint32_t size, mask, - page_mask, page_base; - - uint8_t page_buffer[128]; - uint8_t *array; - - mem_mapping_t mapping[8], mapping_h[8]; - - pc_timer_t page_write_timer; -} sst_t; - - -static wchar_t flash_path[1024]; - - -#define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ -#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ -#define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ -#define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ -#define SST_ERASE 0x80 /* Both 29 and 39 */ - /* With data 60h on 6th cycle, it's alt. ID */ -#define SST_SET_ID_MODE 0x90 /* Both 29 and 39 */ -#define SST_BYTE_PROGRAM 0xa0 /* Both 29 and 39 */ -#define SST_CLEAR_ID_MODE 0xf0 /* Both 29 and 39 */ - /* 1st cycle variant only on 39 */ - -#define SST_ID_MANUFACTURER 0xbf /* SST Manufacturer's ID */ -#define SST_ID_SST29EE010 0x07 -#define SST_ID_SST29LE_VE010 0x08 -#define SST_ID_SST29EE020 0x10 -#define SST_ID_SST29LE_VE020 0x12 -#define SST_ID_SST39SF512 0xb4 -#define SST_ID_SST39SF010 0xb5 -#define SST_ID_SST39SF020 0xb6 -#define SST_ID_SST39SF040 0xb7 - - -static void -sst_sector_erase(sst_t *dev, uint32_t addr) -{ - memset(&dev->array[addr & (dev->mask & ~0xfff)], 0xff, 4096); - dev->dirty = 1; -} - - -static void -sst_new_command(sst_t *dev, uint32_t addr, uint8_t val) -{ - if (dev->command_state == 5) switch (val) { - case SST_CHIP_ERASE: - memset(dev->array, 0xff, 0x20000); - dev->command_state = 0; - break; - - case SST_SDP_DISABLE: - if (!dev->is_39) - dev->sdp = 0; - dev->command_state = 0; - break; - - case SST_SECTOR_ERASE: - if (dev->is_39) - sst_sector_erase(dev, addr); - dev->command_state = 0; - break; - - case SST_SET_ID_MODE_ALT: - dev->id_mode = 1; - dev->command_state = 0; - break; - - default: - dev->command_state = 0; - break; - } else switch (val) { - case SST_ERASE: - dev->command_state = 3; - break; - - case SST_SET_ID_MODE: - dev->id_mode = 1; - dev->command_state = 0; - break; - - case SST_BYTE_PROGRAM: - if (!dev->is_39) { - memset(dev->page_buffer, 0xff, 128); - dev->page_bytes = 0; - timer_on_auto(&dev->page_write_timer, 210.0); - } - dev->command_state = 6; - break; - - case SST_CLEAR_ID_MODE: - dev->id_mode = 0; - dev->command_state = 0; - break; - - default: - dev->command_state = 0; - break; - } -} - - -static void -sst_page_write(void *priv) -{ - sst_t *dev = (sst_t *) priv; - - memcpy(&(dev->array[dev->page_base]), dev->page_buffer, 128); - dev->dirty = 1; - dev->page_bytes = 0; - dev->command_state = 0; -} - - -static uint8_t -sst_read_id(uint32_t addr, void *p) -{ - sst_t *dev = (sst_t *) p; - - if ((addr & 0xffff) == 0) - return SST_ID_MANUFACTURER; /* SST */ - else if ((addr & 0xffff) == 1) - return dev->id; - else - return 0xff; -} - - -static void -sst_buf_write(sst_t *dev, uint32_t addr, uint8_t val) -{ - dev->page_buffer[addr & 0x0000007f] = val; - timer_disable(&dev->page_write_timer); - dev->page_bytes++; - if (dev->page_bytes >= 128) - sst_page_write(dev); - else - timer_set_delay_u64(&dev->page_write_timer, 210 * TIMER_USEC); -} - - -static void -sst_write(uint32_t addr, uint8_t val, void *p) -{ - sst_t *dev = (sst_t *) p; - - switch (dev->command_state) { - case 0: - case 3: - /* 1st and 4th Bus Write Cycle */ - if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { - if (dev->id_mode) - dev->id_mode = 0; - dev->command_state = 0; - } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) - dev->command_state++; - else { - if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { - /* 29 series, software data protection off, start loading the page. */ - dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ - dev->command_state = 7; - sst_buf_write(dev, addr, val); - } - dev->command_state = 0; - } - break; - case 1: - case 4: - /* 2nd and 5th Bus Write Cycle */ - if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) - dev->command_state++; - else - dev->command_state = 0; - break; - case 2: - case 5: - /* 3rd and 6th Bus Write Cycle */ - if ((addr & 0x7fff) == 0x5555) - sst_new_command(dev, addr, val); - else - dev->command_state = 0; - break; - case 6: - /* Page Load Cycle (29) / Data Write Cycle (39SF) */ - if (dev->is_39) { - dev->array[addr & dev->mask] = val; - dev->command_state = 0; - dev->dirty = 1; - } else { - dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ - dev->command_state++; - sst_buf_write(dev, addr, val); - } - break; - case 7: - if (!dev->is_39 && ((addr & dev->page_mask) == dev->page_base)) - sst_buf_write(dev, addr, val); - break; - } -} - - -static uint8_t -sst_read(uint32_t addr, void *p) -{ - sst_t *dev = (sst_t *) p; - uint8_t ret = 0xff; - - addr &= 0x000fffff; - - if (dev->id_mode) - ret = sst_read_id(addr, p); - else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = dev->array[addr - biosaddr]; - } - - return ret; -} - - -static uint16_t -sst_readw(uint32_t addr, void *p) -{ - sst_t *dev = (sst_t *) p; - uint16_t ret = 0xffff; - - addr &= 0x000fffff; - - if (dev->id_mode) - ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8); - else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint16_t *)&dev->array[addr - biosaddr]; - } - - return ret; -} - - -static uint32_t -sst_readl(uint32_t addr, void *p) -{ - sst_t *dev = (sst_t *) p; - uint32_t ret = 0xffffffff; - - addr &= 0x000fffff; - - if (dev->id_mode) - ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16); - else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint32_t *)&dev->array[addr - biosaddr]; - } - - return ret; -} - - -static void -sst_add_mappings(sst_t *dev) -{ - int i = 0, count; - uint32_t base, fbase; - uint32_t root_base; - - count = dev->size >> 16; - root_base = 0x100000 - dev->size; - - for (i = 0; i < count; i++) { - base = root_base + (i << 16); - fbase = base & biosmask; - - memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); - - if (base >= 0xe0000) { - mem_mapping_add(&(dev->mapping[i]), base, 0x10000, - sst_read, sst_readw, sst_readl, - sst_write, NULL, NULL, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - } - mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000), 0x10000, - sst_read, sst_readw, sst_readl, - sst_write, NULL, NULL, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - } -} - - -static void * -sst_init(const device_t *info) -{ - FILE *f; - sst_t *dev = malloc(sizeof(sst_t)); - memset(dev, 0, sizeof(sst_t)); - - size_t l = strlen(machine_get_internal_name_ex(machine))+1; - wchar_t *machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); - mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); - l = wcslen(machine_name)+5; - wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); - swprintf(flash_name, l, L"%ls.bin", machine_name); - - if (wcslen(flash_name) <= 1024) - wcscpy(flash_path, flash_name); - else - wcsncpy(flash_path, flash_name, 1024); - - mem_mapping_disable(&bios_mapping); - mem_mapping_disable(&bios_high_mapping); - - dev->array = (uint8_t *) malloc(biosmask + 1); - memset(dev->array, 0xff, biosmask + 1); - - dev->id = info->local; - dev->is_39 = (dev->id >= SST_ID_SST39SF512); - - if (dev->id == SST_ID_SST39SF512) - dev->size = 0x10000; - else if ((dev->id == SST_ID_SST29EE020) || (dev->id == SST_ID_SST29LE_VE020) || (dev->id == SST_ID_SST39SF020)) - dev->size = 0x40000; - else if (dev->id == SST_ID_SST39SF040) - dev->size = 0x80000; - else - dev->size = 0x20000; - dev->mask = dev->size - 1; - dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ - dev->sdp = 1; - - sst_add_mappings(dev); - - f = nvr_fopen(flash_path, L"rb"); - if (f) { - if (fread(&(dev->array[0x00000]), 1, dev->size, f) != dev->size) - fatal("Less than %i bytes read from the SST Flash ROM file\n", dev->size); - fclose(f); - } else - dev->dirty = 1; /* It is by definition dirty on creation. */ - - free(flash_name); - free(machine_name); - - if (!dev->is_39) - timer_add(&dev->page_write_timer, sst_page_write, dev, 0); - - return dev; -} - - -static void -sst_close(void *p) -{ - FILE *f; - sst_t *dev = (sst_t *)p; - - if (dev->dirty) { - f = nvr_fopen(flash_path, L"wb"); - fwrite(&(dev->array[0x00000]), dev->size, 1, f); - fclose(f); - } - - free(dev->array); - dev->array = NULL; - - free(dev); -} - - -const device_t sst_flash_29ee010_device = -{ - "SST 29EE010 Flash BIOS", - 0, - SST_ID_SST29EE010, - sst_init, - sst_close, - NULL, - NULL, NULL, NULL, NULL -}; - - -const device_t sst_flash_29ee020_device = -{ - "SST 29EE020 Flash BIOS", - 0, - SST_ID_SST29EE020, - sst_init, - sst_close, - NULL, - NULL, NULL, NULL, NULL -}; - - -const device_t sst_flash_39sf010_device = -{ - "SST 39SF010 Flash BIOS", - 0, - SST_ID_SST39SF010, - sst_init, - sst_close, - NULL, - NULL, NULL, NULL, NULL -}; - - -const device_t sst_flash_39sf020_device = -{ - "SST 39SF020 Flash BIOS", - 0, - SST_ID_SST39SF020, - sst_init, - sst_close, - NULL, - NULL, NULL, NULL, NULL -}; +/* + * 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. + * + * Implementation of an SST flash chip. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/machine.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/plat.h> + + +typedef struct sst_t +{ + uint8_t id, is_39, page_bytes, sdp; + + int command_state, id_mode, + dirty; + + uint32_t size, mask, + page_mask, page_base; + + uint8_t page_buffer[128]; + uint8_t *array; + + mem_mapping_t mapping[8], mapping_h[8]; + + pc_timer_t page_write_timer; +} sst_t; + + +static wchar_t flash_path[1024]; + + +#define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ +#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ +#define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ +#define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ +#define SST_ERASE 0x80 /* Both 29 and 39 */ + /* With data 60h on 6th cycle, it's alt. ID */ +#define SST_SET_ID_MODE 0x90 /* Both 29 and 39 */ +#define SST_BYTE_PROGRAM 0xa0 /* Both 29 and 39 */ +#define SST_CLEAR_ID_MODE 0xf0 /* Both 29 and 39 */ + /* 1st cycle variant only on 39 */ + +#define SST_ID_MANUFACTURER 0xbf /* SST Manufacturer's ID */ +#define SST_ID_SST29EE010 0x07 +#define SST_ID_SST29LE_VE010 0x08 +#define SST_ID_SST29EE020 0x10 +#define SST_ID_SST29LE_VE020 0x12 +#define SST_ID_SST39SF512 0xb4 +#define SST_ID_SST39SF010 0xb5 +#define SST_ID_SST39SF020 0xb6 +#define SST_ID_SST39SF040 0xb7 + + +static void +sst_sector_erase(sst_t *dev, uint32_t addr) +{ + memset(&dev->array[addr & (dev->mask & ~0xfff)], 0xff, 4096); + dev->dirty = 1; +} + + +static void +sst_new_command(sst_t *dev, uint32_t addr, uint8_t val) +{ + if (dev->command_state == 5) switch (val) { + case SST_CHIP_ERASE: + memset(dev->array, 0xff, 0x20000); + dev->command_state = 0; + break; + + case SST_SDP_DISABLE: + if (!dev->is_39) + dev->sdp = 0; + dev->command_state = 0; + break; + + case SST_SECTOR_ERASE: + if (dev->is_39) + sst_sector_erase(dev, addr); + dev->command_state = 0; + break; + + case SST_SET_ID_MODE_ALT: + dev->id_mode = 1; + dev->command_state = 0; + break; + + default: + dev->command_state = 0; + break; + } else switch (val) { + case SST_ERASE: + dev->command_state = 3; + break; + + case SST_SET_ID_MODE: + dev->id_mode = 1; + dev->command_state = 0; + break; + + case SST_BYTE_PROGRAM: + if (!dev->is_39) { + memset(dev->page_buffer, 0xff, 128); + dev->page_bytes = 0; + timer_on_auto(&dev->page_write_timer, 210.0); + } + dev->command_state = 6; + break; + + case SST_CLEAR_ID_MODE: + dev->id_mode = 0; + dev->command_state = 0; + break; + + default: + dev->command_state = 0; + break; + } +} + + +static void +sst_page_write(void *priv) +{ + sst_t *dev = (sst_t *) priv; + + memcpy(&(dev->array[dev->page_base]), dev->page_buffer, 128); + dev->dirty = 1; + dev->page_bytes = 0; + dev->command_state = 0; +} + + +static uint8_t +sst_read_id(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + + if ((addr & 0xffff) == 0) + return SST_ID_MANUFACTURER; /* SST */ + else if ((addr & 0xffff) == 1) + return dev->id; + else + return 0xff; +} + + +static void +sst_buf_write(sst_t *dev, uint32_t addr, uint8_t val) +{ + dev->page_buffer[addr & 0x0000007f] = val; + timer_disable(&dev->page_write_timer); + dev->page_bytes++; + if (dev->page_bytes >= 128) + sst_page_write(dev); + else + timer_set_delay_u64(&dev->page_write_timer, 210 * TIMER_USEC); +} + + +static void +sst_write(uint32_t addr, uint8_t val, void *p) +{ + sst_t *dev = (sst_t *) p; + + switch (dev->command_state) { + case 0: + case 3: + /* 1st and 4th Bus Write Cycle */ + if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { + if (dev->id_mode) + dev->id_mode = 0; + dev->command_state = 0; + } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + dev->command_state++; + else { + if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { + /* 29 series, software data protection off, start loading the page. */ + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state = 7; + sst_buf_write(dev, addr, val); + } + dev->command_state = 0; + } + break; + case 1: + case 4: + /* 2nd and 5th Bus Write Cycle */ + if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + dev->command_state++; + else + dev->command_state = 0; + break; + case 2: + case 5: + /* 3rd and 6th Bus Write Cycle */ + if ((addr & 0x7fff) == 0x5555) + sst_new_command(dev, addr, val); + else + dev->command_state = 0; + break; + case 6: + /* Page Load Cycle (29) / Data Write Cycle (39SF) */ + if (dev->is_39) { + dev->array[addr & dev->mask] = val; + dev->command_state = 0; + dev->dirty = 1; + } else { + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state++; + sst_buf_write(dev, addr, val); + } + break; + case 7: + if (!dev->is_39 && ((addr & dev->page_mask) == dev->page_base)) + sst_buf_write(dev, addr, val); + break; + } +} + + +static uint8_t +sst_read(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint8_t ret = 0xff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read_id(addr, p); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint16_t +sst_readw(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint16_t ret = 0xffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint16_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint32_t +sst_readl(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint32_t ret = 0xffffffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint32_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static void +sst_add_mappings(sst_t *dev) +{ + int i = 0, count; + uint32_t base, fbase; + uint32_t root_base; + + count = dev->size >> 16; + root_base = 0x100000 - dev->size; + + for (i = 0; i < count; i++) { + base = root_base + (i << 16); + fbase = base & biosmask; + + memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); + + if (base >= 0xe0000) { + mem_mapping_add(&(dev->mapping[i]), base, 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + } + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000), 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + } +} + + +static void * +sst_init(const device_t *info) +{ + FILE *f; + sst_t *dev = malloc(sizeof(sst_t)); + memset(dev, 0, sizeof(sst_t)); + + size_t l = strlen(machine_get_internal_name_ex(machine))+1; + wchar_t *machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); + mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); + l = wcslen(machine_name)+5; + wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); + swprintf(flash_name, l, L"%ls.bin", machine_name); + + if (wcslen(flash_name) <= 1024) + wcscpy(flash_path, flash_name); + else + wcsncpy(flash_path, flash_name, 1024); + + mem_mapping_disable(&bios_mapping); + mem_mapping_disable(&bios_high_mapping); + + dev->array = (uint8_t *) malloc(biosmask + 1); + memset(dev->array, 0xff, biosmask + 1); + + dev->id = info->local; + dev->is_39 = (dev->id >= SST_ID_SST39SF512); + + if (dev->id == SST_ID_SST39SF512) + dev->size = 0x10000; + else if ((dev->id == SST_ID_SST29EE020) || (dev->id == SST_ID_SST29LE_VE020) || (dev->id == SST_ID_SST39SF020)) + dev->size = 0x40000; + else if (dev->id == SST_ID_SST39SF040) + dev->size = 0x80000; + else + dev->size = 0x20000; + dev->mask = dev->size - 1; + dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ + dev->sdp = 1; + + sst_add_mappings(dev); + + f = nvr_fopen(flash_path, L"rb"); + if (f) { + if (fread(&(dev->array[0x00000]), 1, dev->size, f) != dev->size) + fatal("Less than %i bytes read from the SST Flash ROM file\n", dev->size); + fclose(f); + } else + dev->dirty = 1; /* It is by definition dirty on creation. */ + + free(flash_name); + free(machine_name); + + if (!dev->is_39) + timer_add(&dev->page_write_timer, sst_page_write, dev, 0); + + return dev; +} + + +static void +sst_close(void *p) +{ + FILE *f; + sst_t *dev = (sst_t *)p; + + if (dev->dirty) { + f = nvr_fopen(flash_path, L"wb"); + fwrite(&(dev->array[0x00000]), dev->size, 1, f); + fclose(f); + } + + free(dev->array); + dev->array = NULL; + + free(dev); +} + + +const device_t sst_flash_29ee010_device = +{ + "SST 29EE010 Flash BIOS", + 0, + SST_ID_SST29EE010, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_29ee020_device = +{ + "SST 29EE020 Flash BIOS", + 0, + SST_ID_SST29EE020, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_39sf010_device = +{ + "SST 39SF010 Flash BIOS", + 0, + SST_ID_SST39SF010, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_39sf020_device = +{ + "SST 39SF020 Flash BIOS", + 0, + SST_ID_SST39SF020, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; diff --git a/src/pc.c b/src/pc.c index 28a5a2b58..6b08fae3f 100644 --- a/src/pc.c +++ b/src/pc.c @@ -838,7 +838,7 @@ pc_close(thread_t *ptr) plat_delay_ms(200); } -#ifdef USE_NEW_DYNAREC +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) codegen_close(); #endif diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 960fbe03e..fbac9453c 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -2663,7 +2663,6 @@ static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t #include <86box/vid_voodoo_codegen_x86-64.h> #else #define NO_CODEGEN -static int voodoo_recomp = 0; #endif static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 0dcb7dfb2..4c1c694aa 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,8 +8,6 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.144 2020/06/06 -# # Authors: Miran Grca, # Fred N. van Kempen, # @@ -35,6 +33,9 @@ ifeq ($(DEV_BUILD), y) ifndef DEV_BRANCH DEV_BRANCH := y endif + ifndef 596B + 596B := y + endif ifndef AMD_K5 AMD_K5 := y endif @@ -63,14 +64,11 @@ ifeq ($(DEV_BUILD), y) VECTRA54 := y endif ifndef VPP60 - VP660 := y + VPP60 := y endif ifndef SIEMENS SIEMENS := y endif - ifndef 596B - 596B := y - endif ifndef VGAWONDER VGAWONDER := y endif @@ -96,6 +94,9 @@ else ifndef DEV_BRANCH DEV_BRANCH := n endif + ifndef 596B + 596B := n + endif ifndef AMD_K5 AMD_K5 := n endif @@ -124,10 +125,10 @@ else VECTRA54 := n endif ifndef VPP60 - VP660 := n + VPP60 := n endif - ifndef 596B - 596B := n + ifndef SIEMENS + SIEMENS := n endif ifndef VGAWONDER VGAWONDER := n @@ -183,13 +184,22 @@ endif ifndef MUNT MUNT := y endif +ifndef NEW_DYNAREC + NEW_DYNAREC := n +endif ifndef DYNAREC DYNAREC := y +endif +ifeq ($(DYNAREC), y) ifeq ($(ARM), y) - DYNAREC := n + ifeq ($(NEW_DYNAREC), n) + DYNAREC := n + endif endif ifeq ($(ARM64), y) - DYNAREC := n + ifeq ($(NEW_DYNAREC), n) + DYNAREC := n + endif endif endif ifndef DISCORD @@ -197,6 +207,14 @@ ifndef DISCORD endif +# Path to the dynamic recompiler code. +ifeq ($(NEW_DYNAREC), y) + CODEGEN := codegen_new +else + CODEGEN := codegen +endif + + # Name of the executable. ifndef PROG ifneq ($(WX), n) @@ -242,9 +260,9 @@ endif ######################################################################### # Nothing should need changing from here on.. # ######################################################################### -VPATH := $(EXPATH) . codegen cpu \ - cdrom chipset disk floppy game machine \ - printer \ +VPATH := $(EXPATH) . $(CODEGEN) cpu \ + cdrom chipset device disk floppy \ + game machine mem printer \ sio sound \ sound/munt sound/munt/c_interface sound/munt/sha1 \ sound/munt/srchelper sound/munt/srchelper/srctools/src \ @@ -256,7 +274,7 @@ else TOOL_PREFIX := i686-w64-mingw32- endif CPP := ${TOOL_PREFIX}g++ -CC := gcc +CC := ${TOOL_PREFIX}gcc WINDRES := windres STRIP := strip ifeq ($(ARM64), y) @@ -277,7 +295,7 @@ DEPFILE := win/.depends # Set up the correct toolchain flags. OPTS := $(EXTRAS) $(STUFF) OPTS += -Iinclude \ - -iquote codegen -iquote cpu + -iquote $(CODEGEN) -iquote cpu ifdef EXFLAGS OPTS += $(EXFLAGS) endif @@ -316,7 +334,7 @@ else endif endif endif -AFLAGS := -msse2 -mfpmath=387 +AFLAGS := -msse2 -mfpmath=sse ifeq ($(ARM), y) DFLAGS := -march=armv7-a AOPTIM := @@ -340,22 +358,54 @@ endif # Optional modules. ifeq ($(DYNAREC), y) -ifeq ($(X64), y) -PLATCG := codegen_x86-64.o codegen_accumulate_x86-64.o -else -PLATCG := codegen_x86.o codegen_accumulate_x86.o -endif - OPTS += -DUSE_DYNAREC RFLAGS += -DUSE_DYNAREC -DYNARECOBJ := 386_dynarec_ops.o \ - codegen.o \ - codegen_ops.o codegen_timing_486.o \ + + ifeq ($(NEW_DYNAREC), y) + OPTS += -DUSE_NEW_DYNAREC + RFLAGS += -DUSE_NEW_DYNAREC + + ifeq ($(X64), y) + PLATCG := codegen_backend_x86-64.o codegen_backend_x86-64_ops.o codegen_backend_x86-64_ops_sse.o \ + codegen_backend_x86-64_uops.o + else ifeq ($(ARM64), y) + PLATCG := codegen_backend_arm64.o codegen_backend_arm64_ops.o codegen_backend_arm64_uops.o \ + codegen_backend_arm64_imm.o + else ifeq ($(ARM), y) + PLATCG := codegen_backend_arm.o codegen_backend_arm_ops.o codegen_backend_arm_uops.o + else + PLATCG := codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \ + codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o + endif + + DYNARECOBJ := codegen.o codegen_accumulate.o codegen_allocator.o codegen_block.o codegen_ir.o codegen_ops.o \ + codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ + codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o \ + codegen_ops_jump.o codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ + codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ + codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o $(PLATCG) + else + ifeq ($(X64), y) + PLATCG := codegen_x86-64.o codegen_accumulate_x86-64.o + else + PLATCG := codegen_x86.o codegen_accumulate_x86.o + endif + + DYNARECOBJ := codegen.o \ + codegen_ops.o $(PLATCG) + endif + + CGTOBJ := codegen_timing_486.o \ codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ - codegen_timing_p6.o codegen_timing_winchip.o codegen_timing_winchip2.o $(PLATCG) + codegen_timing_p6.o codegen_timing_winchip.o codegen_timing_winchip2.o +else + ifeq ($(NEW_DYNAREC), y) + OPTS += -DUSE_NEW_DYNAREC + RFLAGS += -DUSE_NEW_DYNAREC + endif endif -ifneq ($(WX), n) +ifeq ($(WX), y) OPTS += -DUSE_WX $(WX_FLAGS) LIBS += $(WX_LIBS) UIOBJ := wx_main.o wx_ui.o wx_stbar.o wx_render.o @@ -483,24 +533,13 @@ endif endif -# Options for works-in-progress. -ifndef SERIAL -SERIAL := serial.o -endif - - # Final versions of the toolchain flags. CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ - $(AFLAGS) -pipe -fomit-frame-pointer -mstackrealign -Wall \ + $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ -fno-strict-aliasing -# -funroll-loops # Add freetyp2 references through pkgconfig -ifeq ($(DEBUG), y) -CFLAGS := $(CFLAGS) -fstack-protector-all `pkg-config --cflags freetype2` -else CFLAGS := $(CFLAGS) `pkg-config --cflags freetype2` -endif CXXFLAGS := $(CFLAGS) @@ -509,24 +548,22 @@ CXXFLAGS := $(CFLAGS) # Create the (final) list of objects to build. # ######################################################################### MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o rom.o \ - usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ - via_vt82c596b.o $(VNCOBJ) + nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ + usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ + $(VNCOBJ) -INTELOBJ := intel_flash.o intel_420ex.o \ - intel_sio.o intel_piix.o +MEMOBJ := intel_flash.o mem.o rom.o spd.o sst_flash.o CPUOBJ := cpu.o cpu_table.o \ - 808x.o \ - 386.o 386_common.o \ - 386_dynarec.o \ + 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o $(CGTOBJ) \ x86seg.o x87.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ - intel_4x0.o ioapic.o neat.o opti495.o opti5x7.o scamp.o scat.o \ - rabbit.o sis_85c471.o sis_85c496.o \ - via_apollo.o via_vpx.o wd76c10.o + intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o neat.o \ + opti495.o opti5x7.o scamp.o scat.o \ + sis_85c310.o sis_85c471.o sis_85c496.o \ + via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ @@ -544,30 +581,32 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket4_5.o m_at_socket7_s7.o m_at_sockets7.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o -DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ - sio_detect.o sio_acc3221.o \ +DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o serial.o \ + smbus.o smbus_piix4.o \ + keyboard.o \ + keyboard_xt.o keyboard_at.o \ + mouse.o \ + mouse_bus.o \ + mouse_serial.o mouse_ps2.o + +SIOOBJ := sio_acc3221.o \ sio_f82c710.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \ sio_pc87306.o \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ - sio_um8669f.o \ - smbus.o smbus_piix4.o spd.o \ - keyboard.o \ - keyboard_xt.o keyboard_at.o \ - gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.o \ - mouse.o \ - mouse_bus.o \ - mouse_serial.o mouse_ps2.o + sio_um8669f.o FDDOBJ := fdd.o fdc.o fdi2raw.o \ fdd_common.o fdd_86f.o \ fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ fdd_mfm.o fdd_td0.o +GAMEOBJ := gameport.o \ + joystick_standard.o joystick_ch_flightstick_pro.o \ + joystick_sw_pad.o joystick_tm_fcs.o + HDDOBJ := hdd.o \ hdd_image.o hdd_table.o \ hdc.o \ @@ -674,9 +713,9 @@ else PLATOBJ += win_joystick_rawinput.o endif -OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \ - $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) \ - $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ +OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ + $(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) \ + $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) \ $(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) $(DEVBROBJ) \ $(DISCORDOBJ) ifdef EXOBJ @@ -685,9 +724,6 @@ endif LIBS := -mwindows -lcomctl32 \ -lopenal -lole32 -ifeq ($(DEBUG), y) - LIBS += -lssp -endif ifeq ($(VNC), y) LIBS += $(VNCLIB) -lws2_32 @@ -765,10 +801,8 @@ pcap_if.res: pcap_if.rc pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res @echo Linking pcap_if.exe .. -ifeq ($(DEBUG), y) - @$(CC) $(LDFLAGS) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res -lssp -else @$(CC) $(LDFLAGS) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res +ifneq ($(DEBUG), y) @$(STRIP) pcap_if.exe endif diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw deleted file mode 100644 index 926889e2a..000000000 --- a/src/win/Makefile_ndr.mingw +++ /dev/null @@ -1,816 +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. -# -# Makefile for Win32 (MinGW32) environment. -# -# Version: @(#)Makefile.mingw 1.0.143 2020/06/06 -# -# Authors: Miran Grca, -# Fred N. van Kempen, -# - -# Various compile-time options. -ifndef STUFF -STUFF := -endif - -# Add feature selections here. -ifndef EXTRAS -EXTRAS := -endif - -ifndef DEV_BUILD -DEV_BUILD := n -endif - -ifeq ($(DEV_BUILD), y) - ifndef DEBUG - DEBUG := y - endif - ifndef DEV_BRANCH - DEV_BRANCH := y - endif - ifndef AMD_K5 - AMD_K5 := y - endif - ifndef CL5422 - CL5422 := y - endif - ifndef LASERXT - LASERXT := y - endif - ifndef MGA - MGA := y - endif - ifndef PAS16 - PAS16 := n - endif - ifndef PORTABLE3 - PORTABLE3 := y - endif - ifndef PS1M2133 - PS1M2133 := y - endif - ifndef PS2M70T4 - PS2M70T4 := y - endif - ifndef VECTRA54 - VECTRA54 := y - endif - ifndef VPP60 - VPP60 := y - endif - ifndef SIEMENS - SIEMENS := y - endif - ifndef 596B - 596B := y - endif - ifndef VGAWONDER - VGAWONDER := y - endif - ifndef VNC - VNC := y - endif - ifndef WIN471 - WIN471 := y - endif - ifndef XL24 - XL24 := y - endif - ifndef NO_SIO - NO_SIO := y - endif - ifndef GUSMAX - GUSMAX := y - endif -else - ifndef DEBUG - DEBUG := n - endif - ifndef DEV_BRANCH - DEV_BRANCH := n - endif - ifndef AMD_K5 - AMD_K5 := n - endif - ifndef CL5422 - CL5422 := n - endif - ifndef LASERXT - LASERXT := n - endif - ifndef MGA - MGA := n - endif - ifndef PAS16 - PAS16 := n - endif - ifndef PORTABLE3 - PORTABLE3 := n - endif - ifndef PS1M2133 - PS1M2133 := n - endif - ifndef PS2M70T4 - PS2M70T4 := n - endif - ifndef VECTRA54 - VECTRA54 := n - endif - ifndef VPP60 - VPP60 := n - endif - ifndef SIEMENS - SIEMENS := n - endif - ifndef 596B - 596B := n - endif - ifndef VGAWONDER - VGAWONDER := n - endif - ifndef VNC - VNC := n - endif - ifndef WIN471 - WIN471 := n - endif - ifndef XL24 - XL24 := n - endif - ifndef NO_SIO - NO_SIO := n - endif - ifndef GUSMAX - GUSMAX := n - endif -endif - -# Defaults for several build options (possibly defined in a chained file.) -ifndef AUTODEP -AUTODEP := n -endif -ifndef OPTIM -OPTIM := n -endif -ifndef RELEASE -RELEASE := n -endif -ifndef X64 -X64 := n -endif -ifndef ARM -ARM := n -endif -ifndef ARM64 -ARM64 := n -endif -ifndef WX -WX := n -endif -ifndef DINPUT - DINPUT := y -endif -ifndef OPENAL -OPENAL := y -endif -ifndef FLUIDSYNTH -FLUIDSYNTH := y -endif -ifndef MUNT -MUNT := y -endif -ifndef DYNAREC - DYNAREC := y -endif -ifndef DISCORD - DISCORD := y -endif - - -# Name of the executable. -ifndef PROG - ifneq ($(WX), n) - PROG := Wx86Box - else - PROG := 86Box - endif -endif - -# WxWidgets basic info. Extract using the config program. -ifneq ($(WX), n) - EXPATH += wx - WX_CONFIG := wx-config.exe - ifeq ($(WX), y) - WX_PATH := C:/MinGW32/WxWidgets - WX_FLAGS := -I$(WX_PATH)/lib/wx/include/msw-unicode-3.0 \ - -I$(WX_PATH)/include/wx-3.0 \ - -D__WXMSW__ -DWX_PRECOMP -D_FILE_OFFSET_BITS=64 -pthread -# -lwx_mswu_gl-3.0 -lwxtiff-3.0 -llzma - WX_LIBS := -mwindows -mthreads -L$(WX_PATH)/lib \ - -lwx_mswu-3.0.dll \ - -lrpcrt4 -loleaut32 -lole32 -luuid \ - -lwinspool -lwinmm -lshell32 -lcomctl32 \ - -lcomdlg32 -ladvapi32 -lwsock32 -lgdi32 - endif - ifeq ($(WX), static) - WX_PATH := C:/MinGW32/WxWidgets - WX_FLAGS := -I$(WX_PATH)/lib/wx/include/msw-unicode-3.0 \ - -I$(WX_PATH)/include/wx-3.0 \ - -D__WXMSW__ -DWX_PRECOMP -D_FILE_OFFSET_BITS=64 -pthread -# -lwx_mswu_gl-3.0 -lwxtiff-3.0 -llzma - WX_LIBS := -mwindows -mthreads -L$(WX_PATH)/lib \ - -lwx_mswu-3.0 -lwxscintilla-3.0 \ - -lwxjpeg-3.0 -lwxpng-3.0 -lwxzlib-3.0 \ - -lwxregexu-3.0 -lwxexpat-3.0 \ - -lrpcrt4 -loleaut32 -lole32 -luuid \ - -lwinspool -lwinmm -lshell32 -lcomctl32 \ - -lcomdlg32 -ladvapi32 -lwsock32 -lgdi32 - endif -endif - - -######################################################################### -# Nothing should need changing from here on.. # -######################################################################### -VPATH := $(EXPATH) . codegen_new cpu \ - cdrom chipset disk floppy game machine \ - printer \ - sio sound \ - sound/munt sound/munt/c_interface sound/munt/sha1 \ - sound/munt/srchelper sound/munt/srchelper/srctools/src \ - sound/resid-fp \ - scsi video network network/slirp win -ifeq ($(X64), y) -TOOL_PREFIX := x86_64-w64-mingw32- -else -TOOL_PREFIX := i686-w64-mingw32- -endif -CPP := ${TOOL_PREFIX}g++ -CC := ${TOOL_PREFIX}gcc -WINDRES := windres -STRIP := strip -ifeq ($(ARM64), y) -CPP := aarch64-w64-mingw32-g++ -CC := aarch64-w64-mingw32-gcc -WINDRES := aarch64-w64-mingw32-windres -STRIP := aarch64-w64-mingw32-strip -endif -ifeq ($(ARM), y) -CPP := armv7-w64-mingw32-g++ -CC := armv7-w64-mingw32-gcc -WINDRES := armv7-w64-mingw32-windres -STRIP := armv7-w64-mingw32-strip -endif -DEPS = -MMD -MF $*.d -c $< -DEPFILE := win/.depends - -# Set up the correct toolchain flags. -OPTS := $(EXTRAS) $(STUFF) -OPTS += -Iinclude \ - -iquote codegen_new -iquote cpu -ifdef EXFLAGS -OPTS += $(EXFLAGS) -endif -ifdef EXINC -OPTS += -I$(EXINC) -endif -ifeq ($(X64), y) - ifeq ($(OPTIM), y) - DFLAGS := -march=native - else - DFLAGS := - endif -else - ifeq ($(OPTIM), y) - DFLAGS := -march=native - else - DFLAGS := -march=i686 - endif -endif -ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG - AOPTIM := - ifndef COPTIM - COPTIM := -Og - endif -else - DFLAGS += -g0 - ifeq ($(OPTIM), y) - AOPTIM := -mtune=native - ifndef COPTIM - COPTIM := -O3 -ffp-contract=fast -flto - endif - else - ifndef COPTIM - COPTIM := -O3 - endif - endif -endif -AFLAGS := -msse2 -mfpmath=sse -ifeq ($(ARM), y) - DFLAGS := -march=armv7-a - AOPTIM := - AFLAGS := -mfloat-abi=hard -endif -ifeq ($(ARM64), y) - DFLAGS := -march=armv8-a - AOPTIM := - AFLAGS := -mfloat-abi=hard -endif -RFLAGS := --input-format=rc -O coff -Iinclude -OPTS += -DUSE_NEW_DYNAREC -ifeq ($(RELEASE), y) -OPTS += -DRELEASE_BUILD -RFLAGS += -DRELEASE_BUILD -endif -ifeq ($(VRAMDUMP), y) -OPTS += -DENABLE_VRAM_DUMP -RFLAGS += -DENABLE_VRAM_DUMP -endif - - -# Optional modules. -ifeq ($(DYNAREC), y) -ifeq ($(X64), y) -PLATCG := codegen_backend_x86-64.o codegen_backend_x86-64_ops.o codegen_backend_x86-64_ops_sse.o \ - codegen_backend_x86-64_uops.o -else ifeq ($(ARM64), y) -PLATCG := codegen_backend_arm64.o codegen_backend_arm64_ops.o codegen_backend_arm64_uops.o \ - codegen_backend_arm64_imm.o -else ifeq ($(ARM), y) -PLATCG := codegen_backend_arm.o codegen_backend_arm_ops.o codegen_backend_arm_uops.o -else -PLATCG := codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o codegen_backend_x86_ops_sse.o \ - codegen_backend_x86_uops.o -endif - -OPTS += -DUSE_DYNAREC -RFLAGS += -DUSE_DYNAREC -DYNARECOBJ := 386_dynarec_ops.o \ - codegen.o codegen_accumulate.o codegen_allocator.o codegen_block.o codegen_ir.o codegen_ops.o \ - codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ - codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \ - codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ - codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ - codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \ - codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ - codegen_timing_p6.o codegen_timing_winchip.o codegen_timing_winchip2.o $(PLATCG) -endif - -ifneq ($(WX), n) - OPTS += -DUSE_WX $(WX_FLAGS) - LIBS += $(WX_LIBS) - UIOBJ := wx_main.o wx_ui.o wx_stbar.o wx_render.o -else - UIOBJ := win_ui.o win_stbar.o \ - win_sdl.o \ - win_dialog.o win_about.o \ - win_settings.o win_devconf.o win_snd_gain.o \ - win_new_floppy.o win_jsconf.o win_media_menu.o -endif - -ifeq ($(OPENAL), y) -OPTS += -DUSE_OPENAL -endif -ifeq ($(FLUIDSYNTH), y) -OPTS += -DUSE_FLUIDSYNTH -FSYNTHOBJ := midi_fluidsynth.o -endif - -ifeq ($(MUNT), y) -OPTS += -DUSE_MUNT -MUNTOBJ := midi_mt32.o \ - Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ - LA32FloatWaveGenerator.o LA32WaveGenerator.o \ - MidiStreamParser.o Part.o Partial.o PartialManager.o \ - Poly.o ROMInfo.o SampleRateConverter.o \ - FIRResampler.o IIR2xResampler.o LinearResampler.o ResamplerModel.o \ - SincResampler.o InternalResampler.o \ - Synth.o Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o -endif - -ifeq ($(VNC), y) -OPTS += -DUSE_VNC -RFLAGS += -DUSE_VNC - ifneq ($(VNC_PATH), ) - OPTS += -I$(VNC_PATH)\INCLUDE - VNCLIB := -L$(VNC_PATH)\LIB - endif -VNCLIB += -lvncserver -VNCOBJ := vnc.o vnc_keymap.o -endif - -ifeq ($(DISCORD), y) -OPTS += -DUSE_DISCORD -RFLAGS += -DUSE_DISCORD -DISCORDOBJ := win_discord.o -endif - -# Options for the DEV branch. -ifeq ($(DEV_BRANCH), y) -OPTS += -DDEV_BRANCH -DEVBROBJ := - -ifeq ($(AMD_K5), y) -OPTS += -DUSE_AMD_K5 -endif - -ifeq ($(CL5422), y) -OPTS += -DUSE_CL5422 -endif - -ifeq ($(LASERXT), y) -OPTS += -DUSE_LASERXT -DEVBROBJ += m_xt_laserxt.o -endif - -ifeq ($(MGA), y) -OPTS += -DUSE_MGA -DEVBROBJ += vid_mga.o -endif - -ifeq ($(PAS16), y) -OPTS += -DUSE_PAS16 -DEVBROBJ += snd_pas16.o -endif - -ifeq ($(PORTABLE3), y) -OPTS += -DUSE_PORTABLE3 -endif - -ifeq ($(PS1M2133), y) -OPTS += -DUSE_PS1M2133 -endif - -ifeq ($(PS2M70T4), y) -OPTS += -DUSE_PS2M70T4 -endif - -ifeq ($(VECTRA54), y) -OPTS += -DUSE_VECTRA54 -endif - -ifeq ($(VPP60), y) -OPTS += -DUSE_VPP60 -endif - -ifeq ($(SIEMENS), y) -OPTS += -DUSE_SIEMENS -endif - -ifeq ($(596B), y) -OPTS += -DUSE_596B -endif - -ifeq ($(VGAWONDER), y) -OPTS += -DUSE_VGAWONDER -endif - -ifeq ($(WIN471), y) -OPTS += -DUSE_WIN471 -endif - -ifeq ($(XL24), y) -OPTS += -DUSE_XL24 -endif - -ifeq ($(NO_SIO), y) -OPTS += -DNO_SIO -endif - -ifeq ($(GUSMAX), y) -OPTS += -DUSE_GUSMAX -endif - -endif - - -# Options for works-in-progress. -ifndef SERIAL -SERIAL := serial.o -endif - - -# Final versions of the toolchain flags. -CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ - $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing - -# Add freetyp2 references through pkgconfig -CFLAGS := $(CFLAGS) `pkg-config --cflags freetype2` - -CXXFLAGS := $(CFLAGS) - - -######################################################################### -# Create the (final) list of objects to build. # -######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o rom.o \ - usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ - via_vt82c596b.o $(VNCOBJ) - -INTELOBJ := intel_flash.o intel_420ex.o \ - intel_sio.o intel_piix.o - -CPUOBJ := cpu.o cpu_table.o \ - 808x.o \ - 386.o 386_common.o \ - 386_dynarec.o \ - x86seg.o x87.o \ - $(DYNARECOBJ) - -CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ - intel_4x0.o ioapic.o neat.o opti495.o opti5x7.o scamp.o scat.o \ - rabbit.o sis_85c471.o sis_85c496.o \ - via_apollo.o via_vpx.o wd76c10.o - -MCHOBJ := machine.o machine_table.o \ - m_xt.o m_xt_compaq.o \ - m_xt_t1000.o m_xt_t1000_vid.o \ - m_xt_xi8088.o m_xt_zenith.o \ - m_pcjr.o \ - m_amstrad.o m_europc.o \ - m_olivetti_m24.o m_tandy.o \ - m_at.o m_at_commodore.o \ - m_at_t3100e.o m_at_t3100e_vid.o \ - m_ps1.o m_ps1_hdc.o \ - m_ps2_isa.o m_ps2_mca.o \ - m_at_compaq.o \ - m_at_286_386sx.o m_at_386dx_486.o \ - m_at_socket4_5.o m_at_socket7_s7.o m_at_sockets7.o \ - m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o - -DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ - sio_acc3221.o \ - sio_f82c710.o \ - sio_fdc37c66x.o sio_fdc37c669.o \ - sio_fdc37c93x.o \ - sio_pc87306.o \ - sio_w83787f.o \ - sio_w83877f.o sio_w83977f.o \ - sio_um8669f.o \ - smbus.o smbus_piix4.o spd.o \ - keyboard.o \ - keyboard_xt.o keyboard_at.o \ - gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.o \ - mouse.o \ - mouse_bus.o \ - mouse_serial.o mouse_ps2.o - -FDDOBJ := fdd.o fdc.o fdi2raw.o \ - fdd_common.o fdd_86f.o \ - fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ - fdd_mfm.o fdd_td0.o - -HDDOBJ := hdd.o \ - hdd_image.o hdd_table.o \ - hdc.o \ - hdc_st506_xt.o hdc_st506_at.o \ - hdc_xta.o \ - hdc_esdi_at.o hdc_esdi_mca.o \ - hdc_xtide.o hdc_ide.o \ - hdc_ide_sff8038i.o - -CDROMOBJ := cdrom.o \ - cdrom_image_backend.o cdrom_image.o - -ZIPOBJ := zip.o - -MOOBJ := mo.o - -SCSIOBJ := scsi.o scsi_device.o \ - scsi_cdrom.o scsi_disk.o \ - scsi_x54x.o \ - scsi_aha154x.o scsi_buslogic.o \ - scsi_ncr5380.o scsi_ncr53c8xx.o \ - scsi_spock.o - -NETOBJ := network.o \ - net_pcap.o \ - net_slirp.o \ - bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \ - ip_input.o queue.o tcp_input.o debug.o ip_output.o \ - sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \ - net_dp8390.o \ - net_3c503.o net_ne2000.o \ - net_pcnet.o net_wd8003.o - -PRINTOBJ := png.o prt_cpmap.o \ - prt_escp.o prt_text.o prt_ps.o - -SNDOBJ := sound.o \ - openal.o \ - snd_opl.o snd_opl_backend.o \ - nukedopl.o \ - snd_resid.o \ - convolve.o convolve-sse.o envelope.o extfilt.o \ - filter.o pot.o sid.o voice.o wave6581__ST.o \ - wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ - wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ - wave8580_PST.o wave.o \ - midi.o midi_system.o \ - snd_speaker.o \ - snd_pssj.o \ - snd_lpt_dac.o snd_lpt_dss.o \ - snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ - snd_azt2316a.o \ - snd_cms.o \ - snd_gus.o \ - snd_sb.o snd_sb_dsp.o \ - snd_emu8k.o snd_mpu401.o \ - snd_sn76489.o snd_ssi2001.o \ - snd_wss.o \ - snd_ym7128.o - -VIDOBJ := video.o \ - vid_table.o \ - vid_cga.o vid_cga_comp.o \ - vid_compaq_cga.o \ - vid_mda.o \ - vid_hercules.o vid_herculesplus.o vid_incolor.o \ - vid_colorplus.o \ - vid_genius.o \ - vid_pgc.o vid_im1024.o \ - vid_sigma.o \ - vid_wy700.o \ - vid_ega.o vid_ega_render.o \ - vid_svga.o vid_svga_render.o \ - vid_vga.o \ - vid_ati_eeprom.o \ - vid_ati18800.o vid_ati28800.o \ - vid_ati_mach64.o vid_ati68860_ramdac.o \ - vid_bt48x_ramdac.o \ - vid_av9194.o \ - vid_icd2061.o vid_ics2595.o \ - vid_cl54xx.o \ - vid_et4000.o vid_sc1502x_ramdac.o \ - vid_et4000w32.o vid_stg_ramdac.o \ - vid_ht216.o \ - vid_oak_oti.o \ - vid_paradise.o \ - vid_ti_cf62011.o \ - vid_tvga.o \ - vid_tgui9440.o vid_tkd8001_ramdac.o \ - vid_att20c49x_ramdac.o \ - vid_s3.o vid_s3_virge.o \ - vid_sdac_ramdac.o \ - vid_voodoo.o - -PLATOBJ := win.o \ - win_dynld.o win_thread.o \ - win_cdrom.o win_keyboard.o \ - win_crashdump.o win_midi.o \ - win_mouse.o - -ifeq ($(DINPUT), y) - PLATOBJ += win_joystick.o -else - PLATOBJ += win_joystick_rawinput.o -endif - -OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) \ - $(DEVOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) \ - $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ - $(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) $(DEVBROBJ) \ - $(DISCORDOBJ) -ifdef EXOBJ -OBJ += $(EXOBJ) -endif - -LIBS := -mwindows -lcomctl32 \ - -lopenal -lole32 - -ifeq ($(VNC), y) -LIBS += $(VNCLIB) -lws2_32 -endif -ifneq ($(WX), n) -LIBS += $(WX_LIBS) -lm -endif -LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -lversion -lwinmm -static -lstdc++ -ifneq ($(X64), y) -LIBS += -Wl,--large-address-aware -endif -ifeq ($(DINPUT), y) - LIBS += -ldinput8 -endif - -LIBS += -static - -# Build module rules. -ifeq ($(AUTODEP), y) -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< -else -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) -c $< - -%.d: %.c $(wildcard $*.d) - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -E $< >NUL - -%.d: %.cc $(wildcard $*.d) - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >NUL - -%.d: %.cpp $(wildcard $*.d) - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >NUL -endif - - -all: $(PROG).exe - - -86Box.res: 86Box.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res - -$(PROG).exe: $(OBJ) 86Box.res - @echo Linking $(PROG).exe .. - @$(CC) $(LDFLAGS) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) -ifneq ($(DEBUG), y) - @$(STRIP) $(PROG).exe -endif - -pcap_if.res: pcap_if.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) -i $< -o pcap_if.res - -pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res - @echo Linking pcap_if.exe .. - @$(CC) $(LDFLAGS) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res -ifneq ($(DEBUG), y) - @$(STRIP) pcap_if.exe -endif - -hello.exe: hello.o - $(CXX) $(LDFLAGS) -o hello.exe hello.o $(WXLIBS) $(LIBS) -ifneq ($(DEBUG), y) - @$(STRIP) hello.exe -endif - - -clean: - @echo Cleaning objects.. - @-rm -f *.o 2>NUL - @-rm -f *.res 2>NUL - -clobber: clean - @echo Cleaning executables.. - @-rm -f *.d 2>NUL - @-rm -f *.exe 2>NUL -# @-rm -f $(DEPFILE) 2>NUL - -ifneq ($(AUTODEP), y) -depclean: - @-rm -f $(DEPFILE) 2>NUL - @echo Creating dependencies.. - @echo # Run "make depends" to re-create this file. >$(DEPFILE) - -depends: DEPOBJ=$(OBJ:%.o=%.d) -depends: depclean $(OBJ:%.o=%.d) - @-cat $(DEPOBJ) >>$(DEPFILE) - @-rm -f $(DEPOBJ) - -$(DEPFILE): -endif - - -# Module dependencies. -ifeq ($(AUTODEP), y) -#-include $(OBJ:%.o=%.d) (better, but sloooowwwww) --include *.d -else -include $(wildcard $(DEPFILE)) -endif - - -# End of Makefile.mingw.