From a86d717ae1f64359779c14c8ffb697a687f6d4f2 Mon Sep 17 00:00:00 2001 From: waltje Date: Wed, 14 Mar 2018 23:31:44 -0500 Subject: [PATCH] Changes to significantly reduce the emulator's RAM footprint. Changes to the memory manager reduced by 120MB for machines with CPU < 80386. Changes to the 86F diskette data processor (required by all floppy controllers) reduced by 330M. Test machine OpenXT now runs at 240MB, instead of 680MB. --- src/cpu/codegen.h | 4 +- src/floppy/fdd.c | 5 +- src/floppy/fdd.h | 4 +- src/floppy/fdd_86f.c | 111 +- src/floppy/fdd_86f.h | 6 +- src/floppy/fdd_imd.c | 6 +- src/floppy/fdd_img.c | 6 +- src/floppy/fdd_json.c | 6 +- src/floppy/fdd_td0.c | 6 +- src/mem.c | 3593 +++++++++++++++++++++------------------- src/mem.h | 353 ++-- src/pc.c | 7 +- src/win/Makefile.mingw | 5 +- 13 files changed, 2178 insertions(+), 1934 deletions(-) diff --git a/src/cpu/codegen.h b/src/cpu/codegen.h index d9cae1d..e613ecb 100644 --- a/src/cpu/codegen.h +++ b/src/cpu/codegen.h @@ -8,7 +8,7 @@ * * Definitions for the code generator. * - * Version: @(#)codegen.h 1.0.1 2018/02/14 + * Version: @(#)codegen.h 1.0.2 2018/03/14 * * Authors: Sarah Walker, * Miran Grca, @@ -303,7 +303,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t void codegen_generate_seg_restore(); void codegen_set_op32(); void codegen_flush(); -void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); +void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr); extern int cpu_block_end; extern uint32_t codegen_endpc; diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 32ff7ff..541233d 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -8,7 +8,7 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.3 2018/03/12 + * Version: @(#)fdd.c 1.0.4 2018/03/14 * * Authors: Miran Grca, * Sarah Walker, @@ -465,6 +465,7 @@ void fdd_load(int drive, wchar_t *fn) { driveloaders[drive] = c; memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2); + d86f_initialize_linked_lists(drive); loaders[c].load(drive, floppyfns[drive]); drive_empty[drive] = 0; fdd_forced_seek(drive, 0); @@ -486,6 +487,8 @@ void fdd_close(int drive) drive_empty[drive] = 1; fdd_set_head(drive, 0); floppyfns[drive][0] = 0; + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); drives[drive].hole = NULL; drives[drive].poll = NULL; drives[drive].seek = NULL; diff --git a/src/floppy/fdd.h b/src/floppy/fdd.h index 20fb1d1..6179ff1 100644 --- a/src/floppy/fdd.h +++ b/src/floppy/fdd.h @@ -8,7 +8,7 @@ * * Definitions for the floppy drive emulation. * - * Version: @(#)fdd.h 1.0.1 2018/02/14 + * Version: @(#)fdd.h 1.0.2 2018/03/14 * * Authors: Miran Grca, * Sarah Walker, @@ -281,7 +281,7 @@ typedef union void d86f_set_version(int drive, uint16_t version); void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); -void d86f_zero_bit_field(int drive, int side); +void d86f_destroy_linked_lists(int drive, int side); void d86f_set_fdc(void *fdc); void fdi_set_fdc(void *fdc); diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index e454b89..8105049 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -10,7 +10,7 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)fdd_86f.c 1.0.4 2018/03/12 + * Version: @(#)fdd_86f.c 1.0.5 2018/03/14 * * Author: Miran Grca, * @@ -214,6 +214,14 @@ typedef union { static fdc_t *d86f_fdc; +#pragma pack(push,1) +typedef struct +{ + uint8_t c, h, r, n; + void *prev; +} sector_t; +#pragma pack(pop) + #pragma pack(push,1) struct { @@ -258,7 +266,7 @@ struct uint8_t *outbuf; uint32_t dma_over; int turbo_pos; - uint16_t sector_id_bit_field[2][256][256][256]; + sector_t *last_side_sector[2]; } d86f[FDD_NUM + 1]; #pragma pack(pop) @@ -274,36 +282,38 @@ d86f_log(const char *format, ...) #ifdef ENABLE_D86F_LOG va_list ap; - if (d86f_do_log) - { + if (d86f_do_log) { va_start(ap, format); pclog_ex(format, ap); va_end(ap); - } + } #endif } -void d86f_zero_bit_field(int drive, int side) +void d86f_initialize_linked_lists(int drive) { - int i = 0; - int j = 0; - int k = 0; - int l = 0; + d86f[drive].last_side_sector[0] = NULL; + d86f[drive].last_side_sector[1] = NULL; +} - for (i = 0; i < side; i++) - { - for (j = 0; j < 256; j++) - { - for (k = 0; k < 256; k++) - { - for (l = 0; l < 256; l++) - { - d86f[drive].sector_id_bit_field[i][j][k][l] = 0; - } - } - } - } +void d86f_destroy_linked_lists(int drive, int side) +{ + sector_t *s; + sector_t *t; + + if (d86f[drive].last_side_sector[side]) { + s = d86f[drive].last_side_sector[side]; + while (s) { + t = s->prev; + free(s); + s = NULL; + if (!t) + break; + s = t; + } + d86f[drive].last_side_sector[side] = NULL; + } } static void d86f_setupcrc(uint16_t poly) @@ -2209,6 +2219,24 @@ void d86f_turbo_format(int drive, int side, int nop) } } +int d86f_sector_is_present(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +{ + sector_t *s, *t; + + if (d86f[drive].last_side_sector[side]) { + s = d86f[drive].last_side_sector[side]; + while (s) { + if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) + return 1; + if (!s->prev) + break; + t = s->prev; + s = t; + } + } + return 0; +} + void d86f_turbo_poll(int drive, int side) { if ((d86f[drive].state != STATE_IDLE) && (d86f[drive].state != STATE_SECTOR_NOT_FOUND) && ((d86f[drive].state & 0xF8) != 0xE8)) @@ -2232,7 +2260,11 @@ void d86f_turbo_poll(int drive, int side) d86f[drive].state++; return; case STATE_02_FIND_ID: - if (!(d86f[drive].sector_id_bit_field[side][fdc_get_read_track_sector(d86f_fdc).id.c][fdc_get_read_track_sector(d86f_fdc).id.h][fdc_get_read_track_sector(d86f_fdc).id.r] & (1 << fdc_get_read_track_sector(d86f_fdc).id.n))) + if (!d86f_sector_is_present(drive, side, + fdc_get_read_track_sector(d86f_fdc).id.c, + fdc_get_read_track_sector(d86f_fdc).id.h, + fdc_get_read_track_sector(d86f_fdc).id.r, + fdc_get_read_track_sector(d86f_fdc).id.n)) { d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; fdc_nosector(d86f_fdc); @@ -2253,7 +2285,11 @@ void d86f_turbo_poll(int drive, int side) case STATE_0C_FIND_ID: case STATE_11_FIND_ID: case STATE_16_FIND_ID: - if (!(d86f[drive].sector_id_bit_field[side][d86f[drive].req_sector.id.c][d86f[drive].req_sector.id.h][d86f[drive].req_sector.id.r] & (1 << d86f[drive].req_sector.id.n))) + if (!d86f_sector_is_present(drive, side, + d86f[drive].req_sector.id.c, + d86f[drive].req_sector.id.h, + d86f[drive].req_sector.id.r, + d86f[drive].req_sector.id.n)) { d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; fdc_nosector(d86f_fdc); @@ -2596,6 +2632,8 @@ uint16_t d86f_prepare_pretrack(int drive, int side, int iso) d86f[drive].index_hole_pos[side] = 0; + d86f_destroy_linked_lists(drive, side); + for (i = 0; i < raw_size; i++) { d86f_write_direct_common(drive, side, gap_fill, 0, i); @@ -2640,6 +2678,7 @@ uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint16_t pos; int i; + sector_t *s; int real_gap2_len = gap2; int real_gap3_len = gap3; @@ -2654,7 +2693,17 @@ uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint16_t dataam_mfm = 0x4555; uint16_t datadam_mfm = 0x4A55; - d86f[drive].sector_id_bit_field[side][id_buf[0]][id_buf[1]][id_buf[2]] |= (1 << id_buf[3]); + if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) { + s = (sector_t *) malloc(sizeof(sector_t)); + memset(s, 0, sizeof(sector_t)); + s->c = id_buf[0]; + s->h = id_buf[1]; + s->r = id_buf[2]; + s->n = id_buf[3]; + if (d86f[drive].last_side_sector[side]) + s->prev = d86f[drive].last_side_sector[side]; + d86f[drive].last_side_sector[side] = s; + } mfm = d86f_is_mfm(drive); @@ -3764,12 +3813,18 @@ void d86f_load(int drive, wchar_t *fn) d86f_log("86F: Disk is %scompressed and %s surface description data\n", d86f[drive].is_compressed ? "" : "not ", d86f_has_surface_desc(drive) ? "has" : "does not have"); } -void d86f_init() +void d86f_init(void) { + int i; + memset(d86f, 0, sizeof(d86f)); d86f_setupcrc(0x1021); - d86f[0].state = d86f[1].state = STATE_IDLE; + for (i = 0; i < (FDD_NUM + 1); i++) + { + d86f[i].state = STATE_IDLE; + d86f_initialize_linked_lists(i); + } } void d86f_set_fdc(void *fdc) diff --git a/src/floppy/fdd_86f.h b/src/floppy/fdd_86f.h index 278a324..3293bf7 100644 --- a/src/floppy/fdd_86f.h +++ b/src/floppy/fdd_86f.h @@ -8,7 +8,7 @@ * * Definitions for the 86F floppy image format. * - * Version: @(#)floppy_86f.h 1.0.1 2018/02/14 + * Version: @(#)floppy_86f.h 1.0.2 2018/03/14 * * Author: Miran Grca, * @@ -86,7 +86,9 @@ extern int gap4_size[2]; #define D86FVER 0x020B extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); -extern void d86f_zero_bit_field(int drive, int side); + +extern void d86f_initialize_linked_lists(int drive); +extern void d86f_destroy_linked_lists(int drive, int side); #endif /*EMU_FLOPPY_86F_H*/ diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index d1e5045..4e974ec 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -8,7 +8,7 @@ * * Implementation of the IMD floppy image format. * - * Version: @(#)fdd_imd.c 1.0.3 2018/03/12 + * Version: @(#)fdd_imd.c 1.0.4 2018/03/14 * * Author: Miran Grca, * @@ -561,8 +561,8 @@ void imd_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); - d86f_zero_bit_field(drive, 0); - d86f_zero_bit_field(drive, 1); + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); if (track > imd[drive].track_count) { diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index d2076ee..ef46b2d 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -9,7 +9,7 @@ * Implementation of the raw sector-based floppy image format, * as well as the Japanese FDI, CopyQM, and FDF formats. * - * Version: @(#)fdd_img.c 1.0.1 2018/02/14 + * Version: @(#)fdd_img.c 1.0.2 2018/03/14 * * Authors: Miran Grca, * Sarah Walker, @@ -978,8 +978,8 @@ void img_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); - d86f_zero_bit_field(drive, 0); - d86f_zero_bit_field(drive, 1); + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); if (track > img[drive].tracks) { diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index 950f361..c9758a8 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -8,7 +8,7 @@ * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)fdd_json.c 1.0.2 2018/03/12 + * Version: @(#)fdd_json.c 1.0.3 2018/03/14 * * Author: Fred N. van Kempen, * @@ -386,9 +386,9 @@ json_seek(int drive, int track) /* Reset the 86F state machine. */ d86f_reset_index_hole_pos(drive, 0); + d86f_destroy_linked_lists(drive, 0); d86f_reset_index_hole_pos(drive, 1); - d86f_zero_bit_field(drive, 0); - d86f_zero_bit_field(drive, 1); + d86f_destroy_linked_lists(drive, 1); interleave_type = 0; diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index d678c04..46d72ef 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -8,7 +8,7 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)fdd_td0.c 1.0.2 2018/03/12 + * Version: @(#)fdd_td0.c 1.0.3 2018/03/14 * * Authors: Miran Grca, * Milodrag Milanovic, @@ -1127,8 +1127,8 @@ void td0_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); - d86f_zero_bit_field(drive, 0); - d86f_zero_bit_field(drive, 1); + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); if (track > td0[drive].tracks) { diff --git a/src/mem.c b/src/mem.c index 87a83f0..954c634 100644 --- a/src/mem.c +++ b/src/mem.c @@ -1,1710 +1,1883 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Memory handling and MMU. - * - * Version: @(#)mem.c 1.0.4 2018/03/12 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include "emu.h" -#include "cpu/cpu.h" -#include "cpu/x86_ops.h" -#include "cpu/x86.h" -#include "machine/machine.h" -#include "machine/m_xt_xi8088.h" -#include "config.h" -#include "io.h" -#include "mem.h" -#include "rom.h" -#ifdef USE_DYNAREC -# include "cpu/codegen.h" -#else -#define PAGE_MASK_INDEX_MASK 3 -#define PAGE_MASK_INDEX_SHIFT 10 -#define PAGE_MASK_MASK 63 -#define PAGE_MASK_SHIFT 4 -#endif - - -static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); -static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); -static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); -static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); -static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); -static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); -static uint8_t *_mem_exec[0x40000]; -static void *_mem_priv_r[0x40000]; -static void *_mem_priv_w[0x40000]; -static mem_mapping_t *_mem_mapping_r[0x40000]; -static mem_mapping_t *_mem_mapping_w[0x40000]; -static int _mem_state[0x40000]; - -static mem_mapping_t base_mapping; -static mem_mapping_t ram_remapped_mapping; -static mem_mapping_t ram_split_mapping; -mem_mapping_t ram_low_mapping; -mem_mapping_t ram_high_mapping; -mem_mapping_t ram_mid_mapping; -mem_mapping_t bios_mapping[8]; -mem_mapping_t bios_high_mapping[8]; -mem_mapping_t romext_mapping; - -page_t *pages; -page_t **page_lookup; - -uint8_t *ram; -uint32_t rammask; - -uint32_t pccache; -uint8_t *pccache2; - -int readlookup[256],readlookupp[256]; -uintptr_t *readlookup2; -int readlnext; -int writelookup[256],writelookupp[256]; -uintptr_t *writelookup2; -int writelnext; - -int shadowbios = 0, - shadowbios_write; - -int mem_a20_state; - -unsigned char isram[0x10000]; - -static uint8_t ff_array[0x1000]; - -int mem_size; -uint32_t biosmask; -int readlnum=0,writelnum=0; -int cachesize=256; - -uint8_t *rom; -uint8_t romext[32768]; - -uint32_t ram_mapped_addr[64]; - -int split_mapping_enabled = 0; - - -void resetreadlookup(void) -{ - int c; - memset(readlookup2,0xFF,1024*1024*sizeof(uintptr_t)); - for (c=0;c<256;c++) readlookup[c]=0xFFFFFFFF; - readlnext=0; - memset(writelookup2,0xFF,1024*1024*sizeof(uintptr_t)); - memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); - for (c=0;c<256;c++) writelookup[c]=0xFFFFFFFF; - writelnext=0; - pccache=0xFFFFFFFF; -} - -int mmuflush=0; -int mmu_perm=4; - -void flushmmucache(void) -{ - int c; - for (c=0;c<256;c++) - { - if (readlookup[c]!=0xFFFFFFFF) - { - readlookup2[readlookup[c]] = -1; - readlookup[c]=0xFFFFFFFF; - } - if (writelookup[c] != 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]!=0xFFFFFFFF) - { - readlookup2[readlookup[c]] = -1; - readlookup[c]=0xFFFFFFFF; - } - if (writelookup[c] != 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]!=0xFFFFFFFF) - { - readlookup2[readlookup[c]] = -1; - readlookup[c]=0xFFFFFFFF; - } - if (writelookup[c] != 0xFFFFFFFF) - { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xFFFFFFFF; - } - } -} - -void mem_flush_write_page(uint32_t addr, uint32_t virt) -{ - int c; - page_t *page_target = &pages[addr >> 12]; - - for (c = 0; c < 256; c++) - { - if (writelookup[c] != 0xffffffff) - { - uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; - - if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) - { - writelookup2[writelookup[c]] = -1; - page_lookup[writelookup[c]] = NULL; - writelookup[c] = 0xffffffff; - } - } - } -} - -extern int output; - -#define mmutranslate_read(addr) mmutranslatereal(addr,0) -#define mmutranslate_write(addr) mmutranslatereal(addr,1) - -int pctrans=0; - -extern uint32_t testr[9]; - -#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> 14]))[((x) >> 2) & 0xfff] - -uint32_t mmutranslatereal(uint32_t addr, int rw) -{ - uint32_t addr2; - uint32_t temp,temp2,temp3; - - if (cpu_state.abrt) - return -1; - 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 -1; - } - - 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 -1; - } - - 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 -1; - } - mmu_perm=temp&4; - rammap(addr2)|=0x20; - rammap((temp2&~0xFFF)+((addr>>10)&0xFFC))|=(rw?0x60:0x20); - - return (temp&~0xFFF)+(addr&0xFFF); -} - -uint32_t mmutranslate_noabrt(uint32_t addr, int rw) -{ - uint32_t addr2; - uint32_t temp,temp2,temp3; - - if (cpu_state.abrt) - return -1; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp=temp2=rammap(addr2); - - if (!(temp&1)) - return -1; - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (CPL == 3 || cr0 & WP_FLAG))) - return -1; - - 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 -1; - - return (temp&~0xFFF)+(addr&0xFFF); -} - -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) -{ - if (virt == 0xffffffff) - return; - - if (readlookup2[virt>>12] != -1) - { - return; - } - - if (readlookup[readlnext]!=0xFFFFFFFF) - { - readlookup2[readlookup[readlnext]] = -1; - } - - readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; - readlookupp[readlnext]=mmu_perm; - readlookup[readlnext++]=virt>>12; - readlnext&=(cachesize-1); - - cycles -= 9; -} - -void addwritelookup(uint32_t virt, uint32_t phys) -{ - 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_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 - page_lookup[virt >> 12] = &pages[phys >> 12]; - else { - writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; - } - writelookupp[writelnext] = mmu_perm; - writelookup[writelnext++] = virt >> 12; - writelnext &= (cachesize - 1); - - cycles -= 9; -} - -uint8_t *getpccache(uint32_t a) -{ - uint32_t a2; - - a2=a; - - if (a2 < 0x100000 && ram_mapped_addr[a2 >> 14]) - { - a = (ram_mapped_addr[a2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? a2 : (ram_mapped_addr[a2 >> 14] & ~0x3FFF) + (a2 & 0x3FFF); - return &ram[(uintptr_t)(a & 0xFFFFF000) - (uintptr_t)(a2 & ~0xFFF)]; - } - - a2 = a; - - if (cr0>>31) - { - pctrans=1; - a = mmutranslate_read(a); - pctrans=0; - - if (a==0xFFFFFFFF) return ram; - } - a&=rammask; - - if (_mem_exec[a >> 14]) - { - if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM) - cpu_prefetch_cycles = cpu_rom_prefetch_cycles; - else - cpu_prefetch_cycles = cpu_mem_prefetch_cycles; - - return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xFFF)]; - } - - pclog("Bad getpccache %08X\n", a); - return &ff_array[0-(uintptr_t)(a2 & ~0xFFF)]; -} - -uint32_t mem_logical_addr; -uint8_t readmembl(uint32_t addr) -{ - mem_logical_addr = addr; - if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) - { - addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3FFF) + (addr & 0x3FFF); - if(addr < mem_size * 1024) return ram[addr]; - return 0xFF; - } - if (cr0 >> 31) - { - addr = mmutranslate_read(addr); - if (addr == 0xFFFFFFFF) return 0xFF; - } - addr &= rammask; - - if (_mem_read_b[addr >> 14]) { - return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); - } - return 0xFF; -} - -void writemembl(uint32_t addr, uint8_t val) -{ - mem_logical_addr = addr; - - if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) - { - addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3FFF) + (addr & 0x3FFF); - if(addr < mem_size * 1024) ram[addr] = val; - return; - } - if (page_lookup[addr>>12]) - { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0 >> 31) - { - addr = mmutranslate_write(addr); - if (addr == 0xFFFFFFFF) return; - } - addr &= rammask; - - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -} - -uint8_t readmemb386l(uint32_t seg, uint32_t addr) -{ - if (seg==-1) - { - x86gpf("NULL segment", 0); - return -1; - } - mem_logical_addr = addr = addr + seg; - if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) - { - addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3FFF) + (addr & 0x3FFF); - if(addr < mem_size * 1024) return ram[addr]; - return 0xFF; - } - - if (cr0 >> 31) - { - addr = mmutranslate_read(addr); - if (addr == 0xFFFFFFFF) return 0xFF; - } - - addr &= rammask; - - if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); - return 0xFF; -} - -void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) -{ - if (seg==-1) - { - x86gpf("NULL segment", 0); - return; - } - - mem_logical_addr = addr = addr + seg; - if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) - { - addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3FFF) + (addr & 0x3FFF); - if(addr < mem_size * 1024) ram[addr] = val; - return; - } - if (page_lookup[addr>>12]) - { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0 >> 31) - { - addr = mmutranslate_write(addr); - if (addr == 0xFFFFFFFF) return; - } - - addr &= rammask; - - if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -} - -uint16_t readmemwl(uint32_t seg, uint32_t addr) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return -1; - } - if (addr2 & 1) - { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFE) - { - if (cr0 >> 31) - { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; - if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; - } - if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); - else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); - } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); - } - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) return *((uint16_t *)&ram[addr]); - return 0xFFFF; - } - if (cr0>>31) - { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return 0xFFFF; - } - - addr2 &= rammask; - - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); - - if (_mem_read_b[addr2 >> 14]) - { - if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); - else return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); - } - return 0xffff; -} - -void writememwl(uint32_t seg, uint32_t addr, uint16_t val) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return; - } - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) *((uint16_t *)&ram[addr]) = val; - return; - } - - if (addr2 & 1) - { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFE) - { - if (cr0 >> 31) - { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+1) == 0xffffffff) 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] != -1) - { - *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - - if (page_lookup[addr2>>12]) - { - page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); - return; - } - if (cr0>>31) - { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; - } - - addr2 &= rammask; - -/* if (addr2 >= 0xa0000 && addr2 < 0xc0000) - pclog("writememwl %08X %02X\n", addr2, val);*/ - - if (_mem_write_w[addr2 >> 14]) - { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - return; - } - - if (_mem_write_b[addr2 >> 14]) - { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - return; - } -} - -uint32_t readmemll(uint32_t seg, uint32_t addr) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return -1; - } - - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) return *((uint32_t *)&ram[addr]); - return 0xFFFFFFFF; - } - - if (addr2 & 3) - { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) - cycles -= timing_misaligned; - if ((addr2&0xFFF)>0xFFC) - { - if (cr0>>31) - { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; - if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff; - } - return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); - } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0>>31) - { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return 0xFFFFFFFF; - } - - addr2&=rammask; - - if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); - - if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); - - if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); - - return 0xffffffff; -} - -void writememll(uint32_t seg, uint32_t addr, uint32_t val) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return; - } - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) *((uint32_t *)&ram[addr]) = val; - return; - } - if (addr2 & 3) - { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFFC) - { - if (cr0>>31) - { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+3) == 0xffffffff) return; - } - writememwl(seg,addr,val); - writememwl(seg,addr+2,val>>16); - return; - } - else if (writelookup2[addr2 >> 12] != -1) - { - *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - if (page_lookup[addr2>>12]) - { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); - return; - } - if (cr0>>31) - { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; - } - - addr2&=rammask; - - if (_mem_write_l[addr2 >> 14]) - { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - return; - } - if (_mem_write_w[addr2 >> 14]) - { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - return; - } - if (_mem_write_b[addr2 >> 14]) - { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); - return; - } -} - -uint64_t readmemql(uint32_t seg, uint32_t addr) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return -1; - } - - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) return *((uint64_t *)&ram[addr]); - return -1; - } - - if (addr2 & 7) - { - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFF8) - { - if (cr0>>31) - { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; - if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff; - } - return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); - } - else if (readlookup2[addr2 >> 12] != -1) - return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0>>31) - { - addr2 = mmutranslate_read(addr2); - if (addr2==0xFFFFFFFF) return -1; - } - - addr2&=rammask; - - if (_mem_read_l[addr2 >> 14]) - return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | - ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32); - - return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); -} - -void writememql(uint32_t seg, uint32_t addr, uint64_t val) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-1) - { - x86gpf("NULL segment", 0); - return; - } - if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) - { - addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3FFF) + (addr2 & 0x3FFF); - if(addr < mem_size * 1024) *((uint64_t *)&ram[addr]) = val; - return; - } - if (addr2 & 7) - { - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xFF8) - { - if (cr0>>31) - { - if (mmutranslate_write(addr2) == 0xffffffff) return; - if (mmutranslate_write(addr2+7) == 0xffffffff) return; - } - writememll(seg, addr, val); - writememll(seg, addr+4, val >> 32); - return; - } - else if (writelookup2[addr2 >> 12] != -1) - { - *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - if (page_lookup[addr2>>12]) - { - 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) - { - addr2 = mmutranslate_write(addr2); - if (addr2==0xFFFFFFFF) return; - } - - addr2&=rammask; - - if (_mem_write_l[addr2 >> 14]) - { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_l[addr2 >> 14](addr2+4, val >> 32, _mem_priv_w[addr2 >> 14]); - return; - } - if (_mem_write_w[addr2 >> 14]) - { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); - return; - } - if (_mem_write_b[addr2 >> 14]) - { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 5, val >> 40, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 7, val >> 56, _mem_priv_w[addr2 >> 14]); - return; - } -} - -uint8_t mem_readb_phys(uint32_t addr) -{ - mem_logical_addr = 0xffffffff; - - if (_mem_read_b[addr >> 14]) - return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); - - return 0xff; -} - -/* Version of mem_readby_phys that doesn't go through the CPU paging mechanism. */ -uint8_t mem_readb_phys_dma(uint32_t addr) -{ - /* mem_logical_addr = 0xffffffff; */ - - if (_mem_exec[addr >> 14]) - return _mem_exec[addr >> 14][addr & 0x3fff]; - else if (_mem_read_b[addr >> 14]) - return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); - else - return 0xff; -} - -uint16_t mem_readw_phys(uint32_t addr) -{ - mem_logical_addr = 0xffffffff; - - if (_mem_read_w[addr >> 14]) - return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]); - - return 0xff; -} - -void mem_writeb_phys(uint32_t addr, uint8_t val) -{ - mem_logical_addr = 0xffffffff; - - if (_mem_write_b[addr >> 14]) - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -} - -/* Version of mem_readby_phys that doesn't go through the CPU paging mechanism. */ -void mem_writeb_phys_dma(uint32_t addr, uint8_t val) -{ - /* mem_logical_addr = 0xffffffff; */ - - if (_mem_exec[addr >> 14]) - _mem_exec[addr >> 14][addr & 0x3fff] = val; - else if (_mem_write_b[addr >> 14]) - _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -} - -void mem_writew_phys(uint32_t addr, uint16_t val) -{ - mem_logical_addr = 0xffffffff; - - if (_mem_write_w[addr >> 14]) - _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); -} - -uint8_t mem_read_ram(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - return ram[addr]; -} -uint16_t mem_read_ramw(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram[addr]; -} -uint32_t mem_read_raml(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram[addr]; -} - -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); - 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 (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); - 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 (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); - 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; - } -} - -void mem_write_ram(uint32_t addr, uint8_t val, void *priv) -{ - 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) -{ - 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) -{ - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[addr >> 12]); -} - - -uint8_t mem_read_bios(uint32_t addr, void *priv) -{ - return rom[addr & biosmask]; -} -uint16_t mem_read_biosw(uint32_t addr, void *priv) -{ - return *(uint16_t *)&rom[addr & biosmask]; -} -uint32_t mem_read_biosl(uint32_t addr, void *priv) -{ - return *(uint32_t *)&rom[addr & biosmask]; -} - -uint8_t mem_read_romext(uint32_t addr, void *priv) -{ - return romext[addr & 0x7fff]; -} -uint16_t mem_read_romextw(uint32_t addr, void *priv) -{ - uint16_t *p = (uint16_t *)&romext[addr & 0x7fff]; - return *p; -} -uint32_t mem_read_romextl(uint32_t addr, void *priv) -{ - uint32_t *p = (uint32_t *)&romext[addr & 0x7fff]; - return *p; -} - -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) -{ - 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)) - { - uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - } -} - -static __inline int mem_mapping_read_allowed(uint32_t flags, int state) -{ - switch (state & MEM_READ_MASK) - { - case MEM_READ_ANY: - return 1; - case MEM_READ_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL); - case MEM_READ_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL); - default: - fatal("mem_mapping_read_allowed : bad state %x\n", state); - return 0; - } -} - -static __inline int mem_mapping_write_allowed(uint32_t flags, int state) -{ - switch (state & MEM_WRITE_MASK) - { - case MEM_WRITE_DISABLED: - return 0; - case MEM_WRITE_ANY: - return 1; - case MEM_WRITE_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL); - case MEM_WRITE_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL); - default: - fatal("mem_mapping_write_allowed : bad state %x\n", state); - return 0; - } -} - -static void mem_mapping_recalc(uint64_t base, uint64_t size) -{ - uint64_t c; - mem_mapping_t *mapping = base_mapping.next; - - if (!size) - return; - /*Clear out old mappings*/ - for (c = base; c < base + size; c += 0x4000) - { - _mem_read_b[c >> 14] = NULL; - _mem_read_w[c >> 14] = NULL; - _mem_read_l[c >> 14] = NULL; - _mem_priv_r[c >> 14] = NULL; - _mem_mapping_r[c >> 14] = NULL; - _mem_write_b[c >> 14] = NULL; - _mem_write_w[c >> 14] = NULL; - _mem_write_l[c >> 14] = NULL; - _mem_priv_w[c >> 14] = NULL; - _mem_mapping_w[c >> 14] = NULL; - } - - /*Walk mapping list*/ - while (mapping != NULL) - { - /*In range?*/ - if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base) - { - uint64_t start = (mapping->base < base) ? mapping->base : base; - uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size); - if (start < mapping->base) - start = mapping->base; - - for (c = start; c < end; c += 0x4000) - { - if ((mapping->read_b || mapping->read_w || mapping->read_l) && - mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14])) - { - _mem_read_b[c >> 14] = mapping->read_b; - _mem_read_w[c >> 14] = mapping->read_w; - _mem_read_l[c >> 14] = mapping->read_l; - if (mapping->exec) - _mem_exec[c >> 14] = mapping->exec + (c - mapping->base); - else - _mem_exec[c >> 14] = NULL; - _mem_priv_r[c >> 14] = mapping->p; - _mem_mapping_r[c >> 14] = mapping; - } - if ((mapping->write_b || mapping->write_w || mapping->write_l) && - mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14])) - { - _mem_write_b[c >> 14] = mapping->write_b; - _mem_write_w[c >> 14] = mapping->write_w; - _mem_write_l[c >> 14] = mapping->write_l; - _mem_priv_w[c >> 14] = mapping->p; - _mem_mapping_w[c >> 14] = mapping; - } - } - } - mapping = mapping->next; - } - flushmmucache_cr3(); -} - -void mem_mapping_add(mem_mapping_t *mapping, - 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 flags, - void *p) -{ - mem_mapping_t *dest = &base_mapping; - - /*Add mapping to the end of the list*/ - while (dest->next) - dest = dest->next; - dest->next = mapping; - mapping->prev = dest; - - if (size) - mapping->enable = 1; - else - mapping->enable = 0; - mapping->base = base; - mapping->size = size; - mapping->read_b = read_b; - mapping->read_w = read_w; - mapping->read_l = read_l; - mapping->write_b = write_b; - mapping->write_w = write_w; - mapping->write_l = write_l; - mapping->exec = exec; - mapping->flags = flags; - mapping->p = p; - mapping->next = NULL; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_mapping_set_handler(mem_mapping_t *mapping, - 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)) -{ - mapping->read_b = read_b; - mapping->read_w = read_w; - mapping->read_l = read_l; - mapping->write_b = write_b; - mapping->write_w = write_w; - mapping->write_l = write_l; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size) -{ - /*Remove old mapping*/ - mapping->enable = 0; - mem_mapping_recalc(mapping->base, mapping->size); - - /*Set new mapping*/ - mapping->enable = 1; - mapping->base = base; - mapping->size = size; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec) -{ - mapping->exec = exec; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_mapping_set_p(mem_mapping_t *mapping, void *p) -{ - mapping->p = p; -} - -void mem_mapping_disable(mem_mapping_t *mapping) -{ - mapping->enable = 0; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_mapping_enable(mem_mapping_t *mapping) -{ - mapping->enable = 1; - - mem_mapping_recalc(mapping->base, mapping->size); -} - -void mem_set_mem_state(uint32_t base, uint32_t size, int state) -{ - uint32_t c; - - for (c = 0; c < size; c += 0x4000) - _mem_state[(c + base) >> 14] = state; - - mem_mapping_recalc(base, size); -} - -void mem_add_bios() -{ - if (AT || (romset == ROM_XI8088 && xi8088_bios_128kb())) - { - mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, 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, 0); - mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - } - mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_mapping_add(&bios_high_mapping[0], (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[1], (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[2], (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[3], (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[4], (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[5], (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[6], (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[7], (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); -} - -int mem_a20_key = 0, mem_a20_alt = 0; -int mem_a20_state = 0; - -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; - } -} - - -void mem_init(void) -{ - int c; - - split_mapping_enabled = 0; - - /* Always allocate the full 16 MB memory space if memory size is smaller, - we'll need this for stupid things like the PS/2 split mapping. */ - if (mem_size < 16384) { - ram = malloc(16384 * 1024); - memset(ram, 0, 16384 * 1024); - } else { - ram = malloc((mem_size + 384) * 1024); /* 386 extra kB for top remapping */ - memset(ram, 0, (mem_size + 384) * 1024); - } - - readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); - writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); - rom = NULL; - biosmask = 0xffff; - pages = malloc((1 << 20) * sizeof(page_t)); - page_lookup = malloc((1 << 20) * sizeof(page_t *)); - - memset(pages, 0, (1 << 20) * sizeof(page_t)); - - memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); - - memset(ram_mapped_addr, 0, 64 * sizeof(uint32_t)); - - for (c = 0; c < (1 << 20); c++) - { - pages[c].mem = &ram[c << 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; - } - - memset(isram, 0, sizeof(isram)); - for (c = 0; c < (mem_size / 64); c++) - { - isram[c] = 1; - if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff)) - isram[c] = 0; - } - - memset(_mem_read_b, 0, sizeof(_mem_read_b)); - memset(_mem_read_w, 0, sizeof(_mem_read_w)); - memset(_mem_read_l, 0, sizeof(_mem_read_l)); - memset(_mem_write_b, 0, sizeof(_mem_write_b)); - memset(_mem_write_w, 0, sizeof(_mem_write_w)); - memset(_mem_write_l, 0, sizeof(_mem_write_l)); - memset(_mem_exec, 0, sizeof(_mem_exec)); - - memset(ff_array, 0xff, sizeof(ff_array)); - - memset(&base_mapping, 0, sizeof(base_mapping)); - - memset(_mem_state, 0, sizeof(_mem_state)); - - mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x0c0000, 0x40000, 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(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 - { - mem_set_mem_state(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 (romset == ROM_IBMPS1_2011) - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); - - mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 384 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); - - mem_mapping_add(&ram_split_mapping, mem_size * 1024, 384 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_split_mapping); - - mem_a20_init(); -} - -static void mem_remap_top(int max_size) -{ - int c; - - if (mem_size > 640) - { - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int size = mem_size - 640; - if (size > max_size) - size = max_size; - - for (c = (start / 64); c < ((start + size - 1) / 64); c++) - { - isram[c] = 1; - } - - mem_set_mem_state(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_split_mapping, ram + (start * 1024)); - - flushmmucache(); - } -} - -void mem_remap_top_256k() -{ - mem_remap_top(256); -} - -void mem_remap_top_384k() -{ - mem_remap_top(384); -} - -void mem_split_enable(int max_size, uint32_t addr) -{ - int c; - - uint8_t *mem_split_buffer = &ram[0x80000]; - - if (split_mapping_enabled) - return; - -#if 0 - pclog("Split mapping enable at %08X\n", addr); -#endif - - mem_set_mem_state(addr, max_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&ram_split_mapping, addr, max_size * 1024); - mem_mapping_set_exec(&ram_split_mapping, &ram[addr]); - - if (max_size == 384) - memcpy(&ram[addr], mem_split_buffer, max_size); - else - memcpy(&ram[addr], &mem_split_buffer[128 * 1024], max_size); - - for (c = ((addr / 1024) / 64); c < (((addr / 1024) + max_size - 1) / 64); c++) - { - isram[c] = 1; - } - - flushmmucache(); - - split_mapping_enabled = 1; -} - -void mem_split_disable(int max_size, uint32_t addr) -{ - int c; - - uint8_t *mem_split_buffer = &ram[0x80000]; - - if (!split_mapping_enabled) - return; - -#if 0 - pclog("Split mapping disable at %08X\n", addr); -#endif - - if (max_size == 384) - memcpy(mem_split_buffer, &ram[addr], max_size); - else - memcpy(&mem_split_buffer[128 * 1024], &ram[addr], max_size); - - mem_mapping_disable(&ram_split_mapping); - mem_set_mem_state(addr, max_size * 1024, 0); - mem_mapping_set_exec(&ram_split_mapping, NULL); - - for (c = ((addr / 1024) / 64); c < (((addr / 1024) + max_size - 1) / 64); c++) - { - isram[c] = 0; - } - - flushmmucache(); - - split_mapping_enabled = 0; -} - -void mem_resize() -{ - int c; - - split_mapping_enabled = 0; - - free(ram); - - /* Always allocate the full 16 MB memory space if memory size is smaller, - we'll need this for stupid things like the PS/2 split mapping. */ - if (mem_size < 16384) { - ram = malloc(16384 * 1024); - memset(ram, 0, 16384 * 1024); - } else { - ram = malloc((mem_size + 384) * 1024); /* 386 extra kB for top remapping */ - memset(ram, 0, (mem_size + 384) * 1024); - } - - memset(pages, 0, (1 << 20) * sizeof(page_t)); - for (c = 0; c < (1 << 20); c++) - { - pages[c].mem = &ram[c << 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; - } - - memset(isram, 0, sizeof(isram)); - for (c = 0; c < (mem_size / 64); c++) - { - isram[c] = 1; - if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff)) - isram[c] = 0; - } - - memset(_mem_read_b, 0, sizeof(_mem_read_b)); - memset(_mem_read_w, 0, sizeof(_mem_read_w)); - memset(_mem_read_l, 0, sizeof(_mem_read_l)); - memset(_mem_write_b, 0, sizeof(_mem_write_b)); - memset(_mem_write_w, 0, sizeof(_mem_write_w)); - memset(_mem_write_l, 0, sizeof(_mem_write_l)); - memset(_mem_exec, 0, sizeof(_mem_exec)); - - memset(&base_mapping, 0, sizeof(base_mapping)); - - memset(_mem_state, 0, sizeof(_mem_state)); - - mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x0c0000, 0x40000, 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(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 - { - mem_set_mem_state(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 (romset == ROM_IBMPS1_2011) - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); - - mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 384 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); - - mem_mapping_add(&ram_split_mapping, mem_size * 1024, 384 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_split_mapping); - - mem_a20_init(); -} - -void mem_reset_page_blocks() -{ - int c; - - for (c = 0; c < ((mem_size * 1024) >> 12); 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; - 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; - } -} - - -static int port_92_reg = 0; - -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; -} - - -uint8_t port_92_read(uint16_t port, void *priv) -{ - return port_92_reg; -} - - -void port_92_write(uint16_t port, uint8_t val, void *priv) -{ - if ((mem_a20_alt ^ val) & 2) - { - mem_a20_alt = (val & 2); - mem_a20_recalc(); - } - - if ((~port_92_reg & val) & 1) - { - softresetx86(); - cpu_set_edx(); - } - - port_92_reg = val; -} - - -void port_92_clear_reset(void) -{ - port_92_reg &= 2; -} - -void port_92_add(void) -{ - io_sethandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); -} - -void port_92_remove(void) -{ - io_removehandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); -} - -void port_92_reset(void) -{ - port_92_reg = 0; - mem_a20_alt = 0; - mem_a20_recalc(); - flushmmucache(); -} - -uint32_t get_phys_virt,get_phys_phys; +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Memory handling and MMU. + * + * Version: @(#)mem.c 1.0.5 2018/03/14 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "emu.h" +#include "cpu/cpu.h" +#include "cpu/x86_ops.h" +#include "cpu/x86.h" +#include "machine/machine.h" +#include "machine/m_xt_xi8088.h" +#include "config.h" +#include "io.h" +#include "mem.h" +#include "rom.h" +#ifdef USE_DYNAREC +# include "cpu/codegen.h" +#else +#define PAGE_MASK_INDEX_MASK 3 +#define PAGE_MASK_INDEX_SHIFT 10 +#define PAGE_MASK_MASK 63 +#define PAGE_MASK_SHIFT 4 +#endif + + +mem_mapping_t ram_low_mapping; +mem_mapping_t ram_high_mapping; +mem_mapping_t ram_mid_mapping; +mem_mapping_t bios_mapping[8]; +mem_mapping_t bios_high_mapping[8]; +mem_mapping_t romext_mapping; + +page_t *pages, + **page_lookup; +uint32_t page_lookup_sz; + +uint8_t isram[0x10000]; + +uint8_t *ram; +uint32_t rammask; + +uint8_t *rom; +uint8_t romext[32768]; + +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 mem_size; +uint32_t biosmask; +int readlnum = 0, + writelnum = 0; +int pctrans = 0; +int cachesize = 256; + +uint32_t ram_mapped_addr[64]; + +int split_mapping_enabled = 0; + +uint32_t get_phys_virt, + get_phys_phys; + +int mem_a20_key = 0, + mem_a20_alt = 0, + mem_a20_state = 0; + +int mmuflush = 0; +int mmu_perm = 4; + + +/* FIXME: re-do this with a 'mem_ops' struct. */ +static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv); +static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv); +static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv); +static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv); +static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv); +static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); +static uint8_t *_mem_exec[0x40000]; +static void *_mem_priv_r[0x40000]; +static void *_mem_priv_w[0x40000]; +static mem_mapping_t *_mem_mapping_r[0x40000]; +static mem_mapping_t *_mem_mapping_w[0x40000]; +static int _mem_state[0x40000]; + +static mem_mapping_t base_mapping; +static mem_mapping_t ram_remapped_mapping; +static mem_mapping_t ram_split_mapping; + +static uint8_t ff_array[0x1000]; + +static int port_92_reg = 0; + + +void +resetreadlookup(void) +{ + int c; + + /* This is NULL after app startup, when mem_init() has not yet run. */ + if (page_lookup == NULL) return; + + memset(page_lookup, 0x00, page_lookup_sz); + + for (c = 0; c < 256; c++) + readlookup[c] = 0xffffffff; + memset(readlookup2, 0xff, 1024*1024*sizeof(uintptr_t)); + readlnext = 0; + + for (c = 0; c < 256; c++) + writelookup[c] = 0xffffffff; + memset(writelookup2, 0xff, 1024*1024*sizeof(uintptr_t)); + writelnext = 0; + + pccache = 0xffffffff; +} + + +void +flushmmucache(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != 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] != 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != 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] != 0xffffffff) { + readlookup2[readlookup[c]] = -1; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != 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; + + for (c = 0; c < 256; c++) { + if (writelookup[c] != 0xffffffff) { + uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; + + 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) >> 14]))[((x) >> 2) & 0xfff] + +uint32_t +mmutranslatereal(uint32_t addr, int rw) +{ + uint32_t temp,temp2,temp3; + uint32_t addr2; + + if (cpu_state.abrt) return -1; + + 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 -1; + } + + 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 -1; + } + + 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 -1; + } + + mmu_perm = temp & 4; + rammap(addr2) |= 0x20; + rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw?0x60:0x20); + + return (temp&~0xfff)+(addr&0xfff); +} + + +uint32_t +mmutranslate_noabrt(uint32_t addr, int rw) +{ + uint32_t temp,temp2,temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return -1; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = rammap(addr2); + + if (! (temp & 1)) + return -1; + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (CPL == 3 || cr0 & WP_FLAG))) + return -1; + + 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 -1; + + return (temp & ~0xfff) + (addr & 0xfff); +} + + +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) +{ + if (virt == 0xffffffff) return; + + if (readlookup2[virt>>12] != -1) return; + + if (readlookup[readlnext] != 0xffffffff) + readlookup2[readlookup[readlnext]] = -1; + + readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; + + readlookupp[readlnext] = mmu_perm; + readlookup[readlnext++] = virt >> 12; + readlnext &= (cachesize-1); + + cycles -= 9; +} + + +void +addwritelookup(uint32_t virt, uint32_t phys) +{ + 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_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 + page_lookup[virt >> 12] = &pages[phys >> 12]; + else + writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; + + writelookupp[writelnext] = mmu_perm; + writelookup[writelnext++] = virt >> 12; + writelnext &= (cachesize - 1); + + cycles -= 9; +} + + +uint8_t * +getpccache(uint32_t a) +{ + uint32_t a2; + + a2 = a; + + if (a2 < 0x100000 && ram_mapped_addr[a2 >> 14]) { + a = (ram_mapped_addr[a2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? a2 : (ram_mapped_addr[a2 >> 14] & ~0x3FFF) + (a2 & 0x3FFF); + return &ram[(uintptr_t)(a & 0xFFFFF000) - (uintptr_t)(a2 & ~0xFFF)]; + } + + a2 = a; + + if (cr0 >> 31) { + pctrans=1; + a = mmutranslate_read(a); + pctrans = 0; + + if (a == 0xffffffff) return ram; + } + a &= rammask; + + if (_mem_exec[a >> 14]) { + if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM) + cpu_prefetch_cycles = cpu_rom_prefetch_cycles; + else + cpu_prefetch_cycles = cpu_mem_prefetch_cycles; + + return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xfff)]; + } + + pclog("Bad getpccache %08X\n", a); + + return &ff_array[0-(uintptr_t)(a2 & ~0xfff)]; +} + + +uint8_t +readmembl(uint32_t addr) +{ + mem_logical_addr = addr; + + if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { + addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); + if(addr < mem_size * 1024) return ram[addr]; + return 0xff; + } + + if (cr0 >> 31) { + addr = mmutranslate_read(addr); + if (addr == 0xffffffff) return 0xff; + } + addr &= rammask; + + if (_mem_read_b[addr >> 14]) + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + + return 0xff; +} + + +void +writemembl(uint32_t addr, uint8_t val) +{ + mem_logical_addr = addr; + + if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { + addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); + if (addr < mem_size * 1024) + ram[addr] = val; + return; + } + + if (page_lookup[addr>>12]) { + page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); + + return; + } + + if (cr0 >> 31) { + addr = mmutranslate_write(addr); + if (addr == 0xffffffff) return; + } + addr &= rammask; + + if (_mem_write_b[addr >> 14]) + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +} + + +uint8_t +readmemb386l(uint32_t seg, uint32_t addr) +{ + if (seg == -1) { + x86gpf("NULL segment", 0); + + return -1; + } + + mem_logical_addr = addr = addr + seg; + if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { + addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); + if (addr < mem_size * 1024) + return ram[addr]; + return 0xff; + } + + if (cr0 >> 31) { + addr = mmutranslate_read(addr); + if (addr == 0xffffffff) + return 0xff; + } + + addr &= rammask; + + if (_mem_read_b[addr >> 14]) + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + + return 0xff; +} + + +void +writememb386l(uint32_t seg, uint32_t addr, uint8_t val) +{ + if (seg == -1) { + x86gpf("NULL segment", 0); + return; + } + + mem_logical_addr = addr = addr + seg; + if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { + addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); + if (addr < mem_size * 1024) + ram[addr] = val; + return; + } + + if (page_lookup[addr>>12]) { + page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); + + return; + } + + if (cr0 >> 31) { + addr = mmutranslate_write(addr); + if (addr == 0xffffffff) return; + } + + addr &= rammask; + + if (_mem_write_b[addr >> 14]) + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +} + + +uint16_t +readmemwl(uint32_t seg, uint32_t addr) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return -1; + } + + if (addr2 & 1) { + if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + cycles -= timing_misaligned; + if ((addr2 & 0xFFF) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; + if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; + } + if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); + else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); + } + else if (readlookup2[addr2 >> 12] != -1) + return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + return *((uint16_t *)&ram[addr]); + return 0xffff; + } + + if (cr0 >> 31) { + addr2 = mmutranslate_read(addr2); + if (addr2 == 0xffffffff) + return 0xFFFF; + } + + addr2 &= rammask; + + if (_mem_read_w[addr2 >> 14]) + return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); + + if (_mem_read_b[addr2 >> 14]) { + if (AT) + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); + else + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); + } + + return 0xffff; +} + + +void +writememwl(uint32_t seg, uint32_t addr, uint16_t val) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return; + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + *((uint16_t *)&ram[addr]) = val; + return; + } + + if (addr2 & 1) { + if (!cpu_cyrix_alignment || (addr2 & 7) == 7) + cycles -= timing_misaligned; + if ((addr2 & 0xFFF) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffff) return; + if (mmutranslate_write(addr2+1) == 0xffffffff) 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] != -1) { + *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12]) { + page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); + return; + } + + if (cr0 >> 31) { + addr2 = mmutranslate_write(addr2); + if (addr2 == 0xffffffff) return; + } + + addr2 &= rammask; + +#if 0 + if (addr2 >= 0xa0000 && addr2 < 0xc0000) + pclog("writememwl %08X %02X\n", addr2, val); +#endif + + if (_mem_write_w[addr2 >> 14]) { + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + return; + } + + if (_mem_write_b[addr2 >> 14]) { + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); + return; + } +} + + +uint32_t +readmemll(uint32_t seg, uint32_t addr) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return -1; + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + return *((uint32_t *)&ram[addr]); + return 0xffffffff; + } + + if (addr2 & 3) { + if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + cycles -= timing_misaligned; + if ((addr2 & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff; + } + return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); + } else if (readlookup2[addr2 >> 12] != -1) + return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (cr0 >> 31) { + addr2 = mmutranslate_read(addr2); + if (addr2 == 0xffffffff) + return 0xffffffff; + } + + addr2 &= rammask; + + if (_mem_read_l[addr2 >> 14]) + return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); + + if (_mem_read_w[addr2 >> 14]) + return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); + + if (_mem_read_b[addr2 >> 14]) + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); + + return 0xffffffff; +} + + +void +writememll(uint32_t seg, uint32_t addr, uint32_t val) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return; + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + *((uint32_t *)&ram[addr]) = val; + return; + } + + if (addr2 & 3) { + if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + cycles -= timing_misaligned; + if ((addr2 & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffff) return; + if (mmutranslate_write(addr2+3) == 0xffffffff) return; + } + writememwl(seg,addr,val); + writememwl(seg,addr+2,val>>16); + return; + } else if (writelookup2[addr2 >> 12] != -1) { + *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12]) { + page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); + return; + } + + if (cr0 >> 31) { + addr2 = mmutranslate_write(addr2); + if (addr2 == 0xffffffff) return; + } + + addr2 &= rammask; + + if (_mem_write_l[addr2 >> 14]) { + _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + return; + } + if (_mem_write_w[addr2 >> 14]) { + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + return; + } + if (_mem_write_b[addr2 >> 14]) { + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); + return; + } +} + + +uint64_t +readmemql(uint32_t seg, uint32_t addr) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return -1; + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + return *((uint64_t *)&ram[addr]); + return -1; + } + + if (addr2 & 7) { + cycles -= timing_misaligned; + if ((addr2 & 0xfff) > 0xff8) { + if (cr0 >> 31) { + if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff; + if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff; + } + return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); + } else if (readlookup2[addr2 >> 12] != -1) + return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); + } + + if (cr0 >> 31) { + addr2 = mmutranslate_read(addr2); + if (addr2 == 0xffffffff) + return -1; + } + + addr2 &= rammask; + + if (_mem_read_l[addr2 >> 14]) + return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32); + + return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); +} + + +void +writememql(uint32_t seg, uint32_t addr, uint64_t val) +{ + uint32_t addr2 = mem_logical_addr = seg + addr; + + if (seg == -1) { + x86gpf("NULL segment", 0); + return; + } + + if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { + addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); + if (addr < mem_size * 1024) + *((uint64_t *)&ram[addr]) = val; + return; + } + + if (addr2 & 7) { + cycles -= timing_misaligned; + if ((addr2 & 0xfff) > 0xff8) { + if (cr0 >> 31) { + if (mmutranslate_write(addr2) == 0xffffffff) return; + if (mmutranslate_write(addr2+7) == 0xffffffff) return; + } + writememll(seg, addr, val); + writememll(seg, addr+4, val >> 32); + return; + } else if (writelookup2[addr2 >> 12] != -1) { + *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; + return; + } + } + + if (page_lookup[addr2>>12]) { + 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) { + addr2 = mmutranslate_write(addr2); + if (addr2 == 0xffffffff) return; + } + + addr2 &= rammask; + + if (_mem_write_l[addr2 >> 14]) { + _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_l[addr2 >> 14](addr2+4, val >> 32, _mem_priv_w[addr2 >> 14]); + return; + } + if (_mem_write_w[addr2 >> 14]) { + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); + return; + } + if (_mem_write_b[addr2 >> 14]) { + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 5, val >> 40, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2 + 7, val >> 56, _mem_priv_w[addr2 >> 14]); + return; + } +} + + +uint8_t +mem_readb_phys(uint32_t addr) +{ + mem_logical_addr = 0xffffffff; + + if (_mem_read_b[addr >> 14]) + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + + return 0xff; +} + + +/* + * Version of mem_readby_phys that doesn't go through + * the CPU paging mechanism. + */ +uint8_t +mem_readb_phys_dma(uint32_t addr) +{ +#if 0 + mem_logical_addr = 0xffffffff; +#endif + + if (_mem_exec[addr >> 14]) + return _mem_exec[addr >> 14][addr & 0x3fff]; + else if (_mem_read_b[addr >> 14]) + return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); + else + return 0xff; +} + + +uint16_t +mem_readw_phys(uint32_t addr) +{ + mem_logical_addr = 0xffffffff; + + if (_mem_read_w[addr >> 14]) + return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]); + + return 0xff; +} + + +void +mem_writeb_phys(uint32_t addr, uint8_t val) +{ + mem_logical_addr = 0xffffffff; + + if (_mem_write_b[addr >> 14]) + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +} + + +/* + * Version of mem_readby_phys that doesn't go through + * the CPU paging mechanism. + */ +void +mem_writeb_phys_dma(uint32_t addr, uint8_t val) +{ +#if 0 + mem_logical_addr = 0xffffffff; +#endif + + if (_mem_exec[addr >> 14]) + _mem_exec[addr >> 14][addr & 0x3fff] = val; + else if (_mem_write_b[addr >> 14]) + _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +} + + +void +mem_writew_phys(uint32_t addr, uint16_t val) +{ + mem_logical_addr = 0xffffffff; + + if (_mem_write_w[addr >> 14]) + _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); +} + + +uint8_t +mem_read_ram(uint32_t addr, void *priv) +{ + addreadlookup(mem_logical_addr, addr); + + return ram[addr]; +} + + +uint16_t +mem_read_ramw(uint32_t addr, void *priv) +{ + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *)&ram[addr]; +} + + +uint32_t +mem_read_raml(uint32_t addr, void *priv) +{ + addreadlookup(mem_logical_addr, addr); + + return *(uint32_t *)&ram[addr]; +} + + +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); + 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 (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); + 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 (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); + 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; + } +} + + +void +mem_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + 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) +{ + 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) +{ + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[addr >> 12]); +} + + +uint8_t +mem_read_bios(uint32_t addr, void *priv) +{ + return rom[addr & biosmask]; +} + + +uint16_t +mem_read_biosw(uint32_t addr, void *priv) +{ + return *(uint16_t *)&rom[addr & biosmask]; +} + + +uint32_t +mem_read_biosl(uint32_t addr, void *priv) +{ + return *(uint32_t *)&rom[addr & biosmask]; +} + + +uint8_t +mem_read_romext(uint32_t addr, void *priv) +{ + return romext[addr & 0x7fff]; +} + + +uint16_t +mem_read_romextw(uint32_t addr, void *priv) +{ + uint16_t *p = (uint16_t *)&romext[addr & 0x7fff]; + + return *p; +} + + +uint32_t +mem_read_romextl(uint32_t addr, void *priv) +{ + uint32_t *p = (uint32_t *)&romext[addr & 0x7fff]; + + return *p; +} + + +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) +{ + 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)) { + uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + + pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + } +} + + +static __inline int +mem_mapping_read_allowed(uint32_t flags, int state) +{ + switch (state & MEM_READ_MASK) { + case MEM_READ_ANY: + return 1; + + case MEM_READ_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL); + + case MEM_READ_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL); + + default: + fatal("mem_mapping_read_allowed : bad state %x\n", state); + } + + return 0; +} + + +static __inline int +mem_mapping_write_allowed(uint32_t flags, int state) +{ + switch (state & MEM_WRITE_MASK) { + case MEM_WRITE_DISABLED: + return 0; + case MEM_WRITE_ANY: + return 1; + case MEM_WRITE_EXTERNAL: + return !(flags & MEM_MAPPING_INTERNAL); + case MEM_WRITE_INTERNAL: + return !(flags & MEM_MAPPING_EXTERNAL); + default: + fatal("mem_mapping_write_allowed : bad state %x\n", state); + } + + return 0; +} + + +static void +mem_mapping_recalc(uint64_t base, uint64_t size) +{ + mem_mapping_t *mapping = base_mapping.next; + uint64_t c; + + if (! size) return; + + /* Clear out old mappings. */ + for (c = base; c < base + size; c += 0x4000) { + _mem_read_b[c >> 14] = NULL; + _mem_read_w[c >> 14] = NULL; + _mem_read_l[c >> 14] = NULL; + _mem_priv_r[c >> 14] = NULL; + _mem_mapping_r[c >> 14] = NULL; + _mem_write_b[c >> 14] = NULL; + _mem_write_w[c >> 14] = NULL; + _mem_write_l[c >> 14] = NULL; + _mem_priv_w[c >> 14] = NULL; + _mem_mapping_w[c >> 14] = NULL; + } + + /* Walk mapping list. */ + while (mapping != NULL) { + /*In range?*/ + if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base) { + uint64_t start = (mapping->base < base) ? mapping->base : base; + uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size); + if (start < mapping->base) + start = mapping->base; + + for (c = start; c < end; c += 0x4000) { + if ((mapping->read_b || mapping->read_w || mapping->read_l) && + mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14])) { + _mem_read_b[c >> 14] = mapping->read_b; + _mem_read_w[c >> 14] = mapping->read_w; + _mem_read_l[c >> 14] = mapping->read_l; + if (mapping->exec) + _mem_exec[c >> 14] = mapping->exec + (c - mapping->base); + else + _mem_exec[c >> 14] = NULL; + _mem_priv_r[c >> 14] = mapping->p; + _mem_mapping_r[c >> 14] = mapping; + } + if ((mapping->write_b || mapping->write_w || mapping->write_l) && + mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14])) { + _mem_write_b[c >> 14] = mapping->write_b; + _mem_write_w[c >> 14] = mapping->write_w; + _mem_write_l[c >> 14] = mapping->write_l; + _mem_priv_w[c >> 14] = mapping->p; + _mem_mapping_w[c >> 14] = mapping; + } + } + } + mapping = mapping->next; + } + + flushmmucache_cr3(); +} + + +void +mem_mapping_add(mem_mapping_t *mapping, + 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 flags, + void *p) +{ + mem_mapping_t *dest = &base_mapping; + + /* Add mapping to the end of the list.*/ + while (dest->next) + dest = dest->next; + dest->next = mapping; + mapping->prev = dest; + + if (size) + mapping->enable = 1; + else + mapping->enable = 0; + mapping->base = base; + mapping->size = size; + mapping->read_b = read_b; + mapping->read_w = read_w; + mapping->read_l = read_l; + mapping->write_b = write_b; + mapping->write_w = write_w; + mapping->write_l = write_l; + mapping->exec = exec; + mapping->flags = flags; + mapping->p = p; + mapping->next = NULL; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_mapping_set_handler(mem_mapping_t *mapping, + 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)) +{ + mapping->read_b = read_b; + mapping->read_w = read_w; + mapping->read_l = read_l; + mapping->write_b = write_b; + mapping->write_w = write_w; + mapping->write_l = write_l; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size) +{ + /* Remove old mapping. */ + mapping->enable = 0; + mem_mapping_recalc(mapping->base, mapping->size); + + /* Set new mapping. */ + mapping->enable = 1; + mapping->base = base; + mapping->size = size; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec) +{ + mapping->exec = exec; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_mapping_set_p(mem_mapping_t *mapping, void *p) +{ + mapping->p = p; +} + + +void +mem_mapping_disable(mem_mapping_t *mapping) +{ + mapping->enable = 0; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_mapping_enable(mem_mapping_t *mapping) +{ + mapping->enable = 1; + + mem_mapping_recalc(mapping->base, mapping->size); +} + + +void +mem_set_mem_state(uint32_t base, uint32_t size, int state) +{ + uint32_t c; + + for (c = 0; c < size; c += 0x4000) + _mem_state[(c + base) >> 14] = state; + + mem_mapping_recalc(base, size); +} + + +void +mem_add_bios(void) +{ + if (AT || (romset == ROM_XI8088 && xi8088_bios_128kb())) { + mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, + 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, 0); + mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x4000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x8000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0xc000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + } + + mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x10000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x14000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x18000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x1c000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_mapping_add(&bios_high_mapping[0], + (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom, MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[1], + (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[2], + (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[3], + (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[4], + (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[5], + (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[6], + (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[7], + (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); +} + + +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, p; + + split_mapping_enabled = 0; + + /* Free existing memory. */ + if (ram != NULL) free(ram); + if (pages != NULL) free(pages); + if (page_lookup != NULL) free(page_lookup); + + /* + * Always allocate the full 16 MB memory space if memory size + * is smaller, we'll need this for stupid things like the PS/2 + * split mapping. + */ + if (mem_size < 16384) + m = 1024UL * 16384; + else + m = 1024UL * (mem_size + 384); /* 386 extra kB for top remapping */ + ram = 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 (m <= (1 << 24)) /* 80286 max address space (16M) */ + p = (m / 4096); /* allocated mem size / pagesize */ + else + p = (1 << 20); /* entire 4GB address space */ +pclog("MEM: mem_size=%i, m=%i, p=%i\n", mem_size, m, p); + pages = (page_t *)malloc(p * sizeof(page_t)); + memset(pages, 0x00, p * sizeof(page_t)); + for (c = 0; c < p; c++) { + pages[c].mem = &ram[c << 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; + } +pclog("MEM: pages done (c=%i)\n", c); + page_lookup = malloc(p * sizeof(page_t *)); + page_lookup_sz = (p * sizeof(page_t *)); + memset(page_lookup, 0x00, page_lookup_sz); +pclog("MEM: page_lookup done\n"); + + memset(isram, 0x00, sizeof(isram)); + for (c = 0; c < (mem_size / 64); c++) { + isram[c] = 1; + if ((c >= 0xa && c <= 0xf) || + (cpu_16bitbus && c >= 0xfe && c <= 0xff)) + isram[c] = 0; + } +pclog("MEM: isram done\n"); + + memset(_mem_read_b, 0x00, sizeof(_mem_read_b)); + memset(_mem_read_w, 0x00, sizeof(_mem_read_w)); + memset(_mem_read_l, 0x00, sizeof(_mem_read_l)); + memset(_mem_write_b, 0x00, sizeof(_mem_write_b)); + memset(_mem_write_w, 0x00, sizeof(_mem_write_w)); + memset(_mem_write_l, 0x00, sizeof(_mem_write_l)); + 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(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(0x0c0000, 0x40000, + 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(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 { + mem_set_mem_state(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 (romset == ROM_IBMPS1_2011) + mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, + mem_read_romext,mem_read_romextw,mem_read_romextl, + NULL,NULL, NULL, romext, 0, NULL); + + mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 384 * 1024, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping); + + mem_mapping_add(&ram_split_mapping, mem_size * 1024, 384 * 1024, + mem_read_ram, mem_read_ramw, mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + (1 << 20), MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_split_mapping); + + mem_a20_init(); +pclog("MEM: reset done\n"); +} + + +void +mem_init(void) +{ + /* Perform a one-time init. */ + ram = NULL; + pages = NULL; + page_lookup = NULL; + + /* FIXME: move to reset? */ + rom = NULL; + biosmask = 0xffff; + + readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); + writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); + + memset(ram_mapped_addr, 0x00, 64 * sizeof(uint32_t)); + + memset(ff_array, 0xff, sizeof(ff_array)); + + /* Reset the memory state. */ + mem_reset(); +pclog("MEM: init done\n"); +} + + +static void +mem_remap_top(int max_size) +{ + int c; + + if (mem_size > 640) { + uint32_t start = (mem_size >= 1024) ? mem_size : 1024; + int size = mem_size - 640; + if (size > max_size) + size = max_size; + + for (c = (start / 64); c < ((start + size - 1) / 64); c++) + isram[c] = 1; + + mem_set_mem_state(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_split_mapping, ram + (start * 1024)); + + flushmmucache(); + } +} + + +void +mem_remap_top_256k(void) +{ + mem_remap_top(256); +} + + +void +mem_remap_top_384k(void) +{ + mem_remap_top(384); +} + + +void +mem_split_enable(int max_size, uint32_t addr) +{ + uint8_t *mem_split_buffer = &ram[0x80000]; + int c; + + if (split_mapping_enabled) return; + +#if 0 + pclog("Split mapping enable at %08X\n", addr); +#endif + + mem_set_mem_state(addr, max_size * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_addr(&ram_split_mapping, addr, max_size * 1024); + mem_mapping_set_exec(&ram_split_mapping, &ram[addr]); + + if (max_size == 384) + memcpy(&ram[addr], mem_split_buffer, max_size); + else + memcpy(&ram[addr], &mem_split_buffer[128 * 1024], max_size); + + for (c = ((addr/1024)/64); c < (((addr/1024)+max_size-1)/64); c++) + isram[c] = 1; + + flushmmucache(); + + split_mapping_enabled = 1; +} + + +void +mem_split_disable(int max_size, uint32_t addr) +{ + uint8_t *mem_split_buffer = &ram[0x80000]; + int c; + + if (! split_mapping_enabled) return; + +#if 0 + pclog("Split mapping disable at %08X\n", addr); +#endif + + if (max_size == 384) + memcpy(mem_split_buffer, &ram[addr], max_size); + else + memcpy(&mem_split_buffer[128 * 1024], &ram[addr], max_size); + + mem_mapping_disable(&ram_split_mapping); + mem_set_mem_state(addr, max_size * 1024, 0); + mem_mapping_set_exec(&ram_split_mapping, NULL); + + for (c = ((addr/1024)/64); c < (((addr/1024)+max_size-1)/64); c++) + isram[c] = 0; + + flushmmucache(); + + split_mapping_enabled = 0; +} + + +void +mem_reset_page_blocks(void) +{ + int c; + + for (c = 0; c < ((mem_size * 1024) >> 12); 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; + 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; + } +} + + +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; +} + + +uint8_t +port_92_read(uint16_t port, void *priv) +{ + return port_92_reg; +} + + +void +port_92_write(uint16_t port, uint8_t val, void *priv) +{ + if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = (val & 2); + mem_a20_recalc(); + } + + if ((~port_92_reg & val) & 1) { + softresetx86(); + cpu_set_edx(); + } + + port_92_reg = val; +} + + +void +port_92_clear_reset(void) +{ + port_92_reg &= 2; +} + + +void +port_92_add(void) +{ + io_sethandler(0x0092, 1, + port_92_read,NULL,NULL, port_92_write, NULL,NULL,NULL); +} + + +void +port_92_remove(void) +{ + io_removehandler(0x0092, 1, + port_92_read,NULL,NULL, port_92_write,NULL,NULL, NULL); +} + + +void +port_92_reset(void) +{ + port_92_reg = 0; + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); +} diff --git a/src/mem.h b/src/mem.h index b80b3cc..0e8448f 100644 --- a/src/mem.h +++ b/src/mem.h @@ -8,7 +8,7 @@ * * Definitions for the memory interface. * - * Version: @(#)mem.h 1.0.2 2018/03/12 + * Version: @(#)mem.h 1.0.3 2018/03/14 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -38,22 +38,117 @@ # define EMU_MEM_H -extern uint8_t *ram; -extern uint32_t rammask; +#define MEM_MAPPING_EXTERNAL 1 /* on external bus (ISA/PCI) */ +#define MEM_MAPPING_INTERNAL 2 /* on internal bus (RAM) */ +#define MEM_MAPPING_ROM 4 /* Executing from ROM may involve + * additional wait states. */ -extern int readlookup[256],readlookupp[256]; -extern uintptr_t *readlookup2; -extern int readlnext; -extern int writelookup[256],writelookupp[256]; -extern uintptr_t *writelookup2; -extern int writelnext; +#define MEM_MAP_TO_SHADOW_RAM_MASK 1 +#define MEM_MAP_TO_RAM_ADDR_MASK 2 + +#define MEM_READ_ANY 0x00 +#define MEM_READ_INTERNAL 0x10 +#define MEM_READ_EXTERNAL 0x20 +#define MEM_READ_MASK 0xf0 + +#define MEM_WRITE_ANY 0x00 +#define MEM_WRITE_INTERNAL 0x01 +#define MEM_WRITE_EXTERNAL 0x02 +#define MEM_WRITE_DISABLED 0x03 +#define MEM_WRITE_MASK 0x0f + + +typedef struct _mem_mapping_ { + struct _mem_mapping_ *prev, *next; + + int enable; + + uint32_t base; + uint32_t size; + + uint8_t (*read_b)(uint32_t addr, void *priv); + uint16_t (*read_w)(uint32_t addr, void *priv); + uint32_t (*read_l)(uint32_t addr, void *priv); + void (*write_b)(uint32_t addr, uint8_t val, void *priv); + void (*write_w)(uint32_t addr, uint16_t val, void *priv); + void (*write_l)(uint32_t addr, uint32_t val, void *priv); + + uint8_t *exec; + + uint32_t flags; + + void *p; +} mem_mapping_t; + +typedef struct _page_ { + void (*write_b)(uint32_t addr, uint8_t val, struct _page_ *p); + void (*write_w)(uint32_t addr, uint16_t val, struct _page_ *p); + void (*write_l)(uint32_t addr, uint32_t val, struct _page_ *p); + + uint8_t *mem; + + uint64_t code_present_mask[4], + dirty_mask[4]; + + struct codeblock_t *block[4], *block_2[4]; + + /*Head of codeblock tree associated with this page*/ + struct codeblock_t *head; +} page_t; + + +extern uint8_t *ram; +extern uint32_t rammask; + +extern uint8_t *rom; +extern uint8_t romext[32768]; +extern uint32_t biosmask; + +extern int readlookup[256], + readlookupp[256]; +extern uintptr_t * readlookup2; +extern int readlnext; +extern int writelookup[256], + writelookupp[256]; +extern uintptr_t *writelookup2; +extern int writelnext; +extern uint32_t ram_mapped_addr[64]; + +extern mem_mapping_t bios_mapping[8], + bios_high_mapping[8], + romext_mapping, + ram_low_mapping, + ram_mid_mapping, + ram_high_mapping; + +extern uint32_t mem_logical_addr; + +extern page_t *pages, + **page_lookup; + +extern uint32_t get_phys_virt,get_phys_phys; + +extern int shadowbios, + shadowbios_write; +extern int readlnum, + writelnum; + +extern int nopageerrors; +extern int memspeed[11]; +extern uint8_t isram[0x10000]; + +extern int mmu_perm; + +extern int mem_a20_state, + mem_a20_alt, + mem_a20_key; -extern int mmu_perm; #define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) #define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl(s,a):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll(s,a):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) + extern uint8_t readmembl(uint32_t addr); extern void writemembl(uint32_t addr, uint8_t val); extern uint8_t readmemb386l(uint32_t seg, uint32_t addr); @@ -70,54 +165,7 @@ extern uint32_t mmutranslatereal(uint32_t addr, int rw); extern void addreadlookup(uint32_t virt, uint32_t phys); extern void addwritelookup(uint32_t virt, uint32_t phys); -extern int shadowbios,shadowbios_write; -extern int readlnum,writelnum; - - -typedef struct mem_mapping_t -{ - struct mem_mapping_t *prev, *next; - - int enable; - - uint32_t base; - uint32_t size; - - uint8_t (*read_b)(uint32_t addr, void *priv); - uint16_t (*read_w)(uint32_t addr, void *priv); - uint32_t (*read_l)(uint32_t addr, void *priv); - void (*write_b)(uint32_t addr, uint8_t val, void *priv); - void (*write_w)(uint32_t addr, uint16_t val, void *priv); - void (*write_l)(uint32_t addr, uint32_t val, void *priv); - - uint8_t *exec; - - uint32_t flags; - - void *p; -} mem_mapping_t; - -/*Only present on external bus (ISA/PCI)*/ -#define MEM_MAPPING_EXTERNAL 1 -/*Only present on internal bus (RAM)*/ -#define MEM_MAPPING_INTERNAL 2 -/*Executing from ROM may involve additional wait states*/ -#define MEM_MAPPING_ROM 4 - -extern uint8_t *ram,*rom; -extern uint8_t romext[32768]; -extern int readlnum,writelnum; -extern int memspeed[11]; -extern int nopageerrors; -extern uint32_t biosmask; -extern unsigned char isram[0x10000]; - -#define MEM_MAP_TO_SHADOW_RAM_MASK 1 -#define MEM_MAP_TO_RAM_ADDR_MASK 2 - -extern uint32_t ram_mapped_addr[64]; - -void mem_mapping_add(mem_mapping_t *mapping, +extern void mem_mapping_add(mem_mapping_t *mapping, uint32_t base, uint32_t size, uint8_t (*read_b)(uint32_t addr, void *p), @@ -129,149 +177,74 @@ void mem_mapping_add(mem_mapping_t *mapping, uint8_t *exec, uint32_t flags, void *p); -void mem_mapping_set_handler(mem_mapping_t *mapping, + +extern void mem_mapping_set_handler(mem_mapping_t *mapping, 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)); -void mem_mapping_set_p(mem_mapping_t *mapping, void *p); -void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size); -void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec); -void mem_mapping_disable(mem_mapping_t *mapping); -void mem_mapping_enable(mem_mapping_t *mapping); -void mem_set_mem_state(uint32_t base, uint32_t size, int state); +extern void mem_mapping_set_p(mem_mapping_t *mapping, void *p); -#define MEM_READ_ANY 0x00 -#define MEM_READ_INTERNAL 0x10 -#define MEM_READ_EXTERNAL 0x20 -#define MEM_READ_MASK 0xf0 +extern void mem_mapping_set_addr(mem_mapping_t *mapping, + uint32_t base, uint32_t size); +extern void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec); +extern void mem_mapping_disable(mem_mapping_t *mapping); +extern void mem_mapping_enable(mem_mapping_t *mapping); -#define MEM_WRITE_ANY 0x00 -#define MEM_WRITE_INTERNAL 0x01 -#define MEM_WRITE_EXTERNAL 0x02 -#define MEM_WRITE_DISABLED 0x03 -#define MEM_WRITE_MASK 0x0f +extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); -extern int mem_a20_state; -extern int mem_a20_alt; -extern int mem_a20_key; -void mem_a20_recalc(); +extern uint8_t mem_readb_phys(uint32_t addr); +extern uint8_t mem_readb_phys_dma(uint32_t addr); +extern uint16_t mem_readw_phys(uint32_t addr); +extern void mem_writeb_phys(uint32_t addr, uint8_t val); +extern void mem_writeb_phys_dma(uint32_t addr, uint8_t val); +extern void mem_writew_phys(uint32_t addr, uint16_t val); -uint8_t mem_readb_phys(uint32_t addr); -uint8_t mem_readb_phys_dma(uint32_t addr); -uint16_t mem_readw_phys(uint32_t addr); -void mem_writeb_phys(uint32_t addr, uint8_t val); -void mem_writeb_phys_dma(uint32_t addr, uint8_t val); -void mem_writew_phys(uint32_t addr, uint16_t val); +extern uint8_t mem_read_ram(uint32_t addr, void *priv); +extern uint16_t mem_read_ramw(uint32_t addr, void *priv); +extern uint32_t mem_read_raml(uint32_t addr, void *priv); +extern void mem_write_ram(uint32_t addr, uint8_t val, void *priv); +extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); +extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv); -uint8_t mem_read_ram(uint32_t addr, void *priv); -uint16_t mem_read_ramw(uint32_t addr, void *priv); -uint32_t mem_read_raml(uint32_t addr, void *priv); +extern uint8_t mem_read_bios(uint32_t addr, void *priv); +extern uint16_t mem_read_biosw(uint32_t addr, void *priv); +extern uint32_t mem_read_biosl(uint32_t addr, void *priv); -void mem_write_ram(uint32_t addr, uint8_t val, void *priv); -void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); -void mem_write_raml(uint32_t addr, uint32_t val, void *priv); +extern void mem_write_null(uint32_t addr, uint8_t val, void *p); +extern void mem_write_nullw(uint32_t addr, uint16_t val, void *p); +extern void mem_write_nulll(uint32_t addr, uint32_t val, void *p); -uint8_t mem_read_bios(uint32_t addr, void *priv); -uint16_t mem_read_biosw(uint32_t addr, void *priv); -uint32_t mem_read_biosl(uint32_t addr, void *priv); +extern uint32_t mmutranslate_noabrt(uint32_t addr, int rw); -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); +extern void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); -mem_mapping_t bios_mapping[8]; -mem_mapping_t bios_high_mapping[8]; -mem_mapping_t romext_mapping; - -extern mem_mapping_t ram_high_mapping; - - -typedef struct page_t -{ - void (*write_b)(uint32_t addr, uint8_t val, struct page_t *p); - void (*write_w)(uint32_t addr, uint16_t val, struct page_t *p); - void (*write_l)(uint32_t addr, uint32_t val, struct page_t *p); - - uint8_t *mem; - - struct codeblock_t *block[4], *block_2[4]; - - /*Head of codeblock tree associated with this page*/ - struct codeblock_t *head; - - uint64_t code_present_mask[4], dirty_mask[4]; -} page_t; - -extern page_t *pages; - -extern page_t **page_lookup; - -uint32_t mmutranslate_noabrt(uint32_t addr, int rw); - -extern uint32_t get_phys_virt,get_phys_phys; - -#ifdef EMU_CPU_H -static __inline uint32_t get_phys(uint32_t addr) -{ - if (!((addr ^ get_phys_virt) & ~0xfff)) - return get_phys_phys | (addr & 0xfff); - - get_phys_virt = addr; - - if (!(cr0 >> 31)) - { - get_phys_phys = (addr & rammask) & ~0xfff; - return addr & rammask; - } - - get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff; - return get_phys_phys | (addr & 0xfff); - /* return mmutranslatereal(addr, 0) & rammask; */ -} - -static __inline uint32_t get_phys_noabrt(uint32_t addr) -{ - if (!(cr0 >> 31)) - return addr & rammask; - - return mmutranslate_noabrt(addr, 0) & rammask; -} -#endif - -void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); - -extern uint32_t mem_logical_addr; - -void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p); -void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p); -void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p); -void mem_flush_write_page(uint32_t addr, uint32_t virt); +extern void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p); +extern void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p); +extern void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p); +extern void mem_flush_write_page(uint32_t addr, uint32_t virt); extern void mem_reset_page_blocks(void); -extern mem_mapping_t ram_low_mapping; -extern mem_mapping_t ram_mid_mapping; - -extern void mem_remap_top_256k(void); -extern void mem_remap_top_384k(void); - extern void flushmmucache(void); extern void flushmmucache_cr3(void); extern void flushmmucache_nopc(void); extern void mmu_invalidate(uint32_t addr); -extern void mem_split_enable(int max_size, uint32_t addr); -extern void mem_split_disable(int max_size, uint32_t addr); - +extern void mem_a20_recalc(void); extern void mem_add_bios(void); extern void mem_init(void); -extern void mem_resize(void); +extern void mem_reset(void); +extern void mem_remap_top_256k(void); +extern void mem_remap_top_384k(void); + +extern void mem_split_enable(int max_size, uint32_t addr); +extern void mem_split_disable(int max_size, uint32_t addr); extern uint8_t port_92_read(uint16_t port, void *priv); extern void port_92_write(uint16_t port, uint8_t val, void *priv); @@ -281,4 +254,38 @@ extern void port_92_remove(void); extern void port_92_reset(void); +#ifdef EMU_CPU_H +static __inline uint32_t get_phys(uint32_t addr) +{ + if (! ((addr ^ get_phys_virt) & ~0xfff)) + return get_phys_phys | (addr & 0xfff); + + get_phys_virt = addr; + + if (! (cr0 >> 31)) { + get_phys_phys = (addr & rammask) & ~0xfff; + + return addr & rammask; + } + + get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff; + +#if 1 + return get_phys_phys | (addr & 0xfff); +#else + return mmutranslatereal(addr, 0) & rammask; +#endif +} + + +static __inline uint32_t get_phys_noabrt(uint32_t addr) +{ + if (! (cr0 >> 31)) + return addr & rammask; + + return mmutranslate_noabrt(addr, 0) & rammask; +} +#endif + + #endif /*EMU_MEM_H*/ diff --git a/src/pc.c b/src/pc.c index d6ce9e6..3d44197 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.8 2018/03/13 + * Version: @(#)pc.c 1.0.9 2018/03/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -640,7 +640,8 @@ pc_reload(wchar_t *fn) fdd_load(2, floppyfns[2]); fdd_load(3, floppyfns[3]); - mem_resize(); + mem_reset(); + network_init(); pc_reset_hard_init(); @@ -777,7 +778,7 @@ pc_reset_hard_init(void) /* Reset the general machine support modules. */ io_init(); - mem_resize(); + mem_reset(); timer_reset(); device_init(); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 95bf815..c1bb7e6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.12 2018/03/14 +# Version: @(#)Makefile.mingw 1.0.13 2018/03/14 # # Author: Fred N. van Kempen, # @@ -688,6 +688,9 @@ clobber: clean @echo Cleaning executables.. @-rm -f *.d 2>NUL @-rm -f *.exe 2>NUL +ifneq ($(PROFILER), y) + @-rm -f *.map 2>NUL +endif @-rm -f win/*.manifest 2>NUL # @-rm -f $(DEPFILE) 2>NUL