diff --git a/src/386_dynarec.c b/src/386_dynarec.c index f854019..053babb 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -6,8 +6,8 @@ #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "codegen.h" #include "mem.h" +#include "codegen.h" #include "cpu.h" #include "fdc.h" #include "timer.h" @@ -1191,11 +1191,11 @@ void exec386(int cycs) cycdiff=0; oldcyc=cycles; - if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x %i\n", CS, pc, SS,ESP, codeblock_page_dirty[0x1de]); +// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x %i\n", CS, pc, SS,ESP, codeblock_page_dirty[0x1de]); if (!CACHE_ON()) /*Interpret block*/ { cpu_block_end = 0; - if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); +// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); while (!cpu_block_end) { oldcs=CS; @@ -1217,8 +1217,8 @@ void exec386(int cycs) opcode = fetchdat & 0xFF; fetchdat >>= 8; - if (output == 3) - pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); +// if (output == 3) +// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); pc++; x86_opcodes[(opcode | op32) & 0x3ff](fetchdat); @@ -1257,32 +1257,53 @@ void exec386(int cycs) codeblock_t *block = codeblock_hash[hash]; int valid_block = 0; trap = 0; -// if ((cs+pc) == 0x100030) -// pclog("160070 : phys=%08x %04x(%08x):%08x\n", phys_addr, SS, ss, ESP); + if (block) { -// if ((cs+pc) == 0x100030) -// pclog("160070 : block\n", phys_addr); + page_t *page = &pages[phys_addr >> 12]; + /*Block must match current CS, PC, code segment size, + and physical address. The physical address check will + also catch any page faults at this stage*/ valid_block = (block->pc == cs + pc) && (block->_cs == cs) && (block->use32 == use32) && (block->phys == phys_addr); - - if (valid_block && codeblock_page_dirty[phys_addr >> 12]) - dirty = codegen_check_dirty(phys_addr); - -// if (pc == 0x804003f0) -// if (!(valid_block && !dirty)) -// if ((pc & 0xffffff00) == 0xe00 || (pc & 0xffffff00) == 0xd00) -// if ((cs+pc) == 0x100030) -// pclog("this block pc=%08x,%08x cs=%08x,%08x use32=%03x,%03x phys=%08x,%08x v=%i d=%i\n", -// cs+pc, block->pc, cs, block->_cs, use32, block->use32, phys_addr, block->phys, valid_block, dirty); + + if (valid_block && (block->page_mask & page->dirty_mask)) + { + codegen_check_flush(page, page->dirty_mask, phys_addr); + page->dirty_mask = 0; + if (!block->pc) + valid_block = 0; + } + if (valid_block && block->page_mask2) + { + /*We don't want the second page to cause a page + fault at this stage - that would break any + code crossing a page boundary where the first + page is present but the second isn't. Instead + allow the first page to be interpreted and for + the page fault to occur when the page boundary + is actually crossed.*/ + uint32_t phys_addr_2 = get_phys_noabrt(block->endpc) & ~0xfff; + page_t *page_2 = &pages[phys_addr_2 >> 12]; + + if ((block->phys_2 ^ phys_addr_2) & ~0xfff) + valid_block = 0; + else if (block->page_mask2 & page_2->dirty_mask) + { + codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); + page_2->dirty_mask = 0; + if (!block->pc) + valid_block = 0; + } + } } -//pclog("block - %08x:%08x %08x %03x %08x %08x %08x %i\n", cs, pc, phys_addr, hash, codeblock_hash_pc[hash], codeblock_hash_cs[hash], codeblock_hash_phys[hash], codeblock_page_dirty[phys_addr >> 12]); + if (valid_block && !dirty) { void (*code)() = (void *)&block->data[BLOCK_START]; - if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x %08x %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0], get_phys(cs+pc), block->phys); +// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); oldcs = CS; oldcpl = CPL; @@ -1299,6 +1320,7 @@ inrecomp=0; else if (!abrt) { uint32_t start_page = pc >> 12; + uint32_t start_pc = pc; // pclog("Hash %08x %i\n", codeblock_hash_pc[HASH(cs + pc)], codeblock_page_dirty[(cs + pc) >> 12]); cpu_block_end = 0; @@ -1307,13 +1329,7 @@ inrecomp=0; codegen_block_init(phys_addr); -// if (CS == 0x70 && pc == 0x84a) -// output = 3; -// if (((cs + pc) & ~0x1f) == 0x0010A182) -// output |= 2; -// if ((cs+pc) == 0xfe771) -// output = 1; - if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); +// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); while (!cpu_block_end) { oldcs=CS; @@ -1337,18 +1353,10 @@ inrecomp=0; opcode = fetchdat & 0xFF; fetchdat >>= 8; - if (output == 3) - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); - - if (((cs + pc) >> 12) != pccache) - CPU_BLOCK_END(); - - if ((pc >> 12) != start_page) - CPU_BLOCK_END(); +// if (output == 3) +// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); pc++; -/* if (opcode == 0xf2 || opcode == 0xf3 || ((opcode & ~7) == 0xd8)*/ -// codegen_set_op32(); codegen_generate_call(opcode, x86_opcodes[(opcode | op32) & 0x3ff], fetchdat, pc, pc-1); @@ -1357,45 +1365,34 @@ inrecomp=0; if (!use32) pc &= 0xffff; - if (((cs + pc) >> 12) != pccache) - CPU_BLOCK_END(); - - if (codeblock_page_dirty[phys_addr >> 12]) + /*Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ + if ((pc - start_pc) > 4000) CPU_BLOCK_END(); if (trap) CPU_BLOCK_END(); -//pclog("cpu_block_end=%d %p\n", cpu_block_end, (void *)&cpu_block_end); -/* if (ssegs) - { - ds=oldds; - ss=oldss; - ssegs=0; - codegen_generate_seg_restore(); - }*/ - //codegen_check_abrt(); - if (abrt || codeblock_page_dirty[phys_addr >> 12]) + if (abrt) { codegen_block_remove(); CPU_BLOCK_END(); } -//if (pc==0x5b42) -// cpu_block_end = 1; + ins++; insc++; } - if (!abrt && !codeblock_page_dirty[phys_addr >> 12]) + if (!abrt) codegen_block_end(); // output &= ~2; } // if (output && (SP & 1)) // fatal("odd SP\n"); } -//if (CS == 0x9087 && pc == 0x3763) -// fatal("Here\n"); cycdiff=oldcyc-cycles; tsc += cycdiff; @@ -1473,12 +1470,8 @@ inrecomp=0; } } } -/* if (SS == 0x30 && stack_check) - pclog("Load stack %04x(%08x):%08x\n", SS, ss, ESP);*/ } timer_end_period(cycles); -//if ((cs + pc) == 0x2ea5e) -// fatal(""); cycles_main -= (cycles_start - cycles); } } diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index efa4fc3..fd2cf05 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -5,6 +5,7 @@ #include "x86_ops.h" #include "x87.h" #include "x86_flags.h" +#include "mem.h" #include "codegen.h" #define CPU_BLOCK_END() cpu_block_end = 1 diff --git a/src/808x.c b/src/808x.c index bbfdaf8..85cd450 100644 --- a/src/808x.c +++ b/src/808x.c @@ -652,6 +652,9 @@ void resetx86() mmu_perm=4; memset(inscounts, 0, sizeof(inscounts)); x86seg_reset(); +#ifdef DYNAREC + codegen_reset(); +#endif } void softresetx86() diff --git a/src/codegen.c b/src/codegen.c index fec6903..1f6806a 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -2,6 +2,7 @@ #include "ibm.h" #include "x86_ops.h" +#include "mem.h" #include "codegen.h" void (*codegen_timing_start)(); diff --git a/src/codegen.h b/src/codegen.h index b9d24e6..f292ef6 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -6,28 +6,60 @@ #error Dynamic recompiler not implemented on your platform #endif +/*Handling self-modifying code (of which there is a lot on x86) : + + PCem tracks a 'dirty mask' for each physical page, in which each bit + represents 64 bytes. This is only tracked for pages that have code in - when a + page first has a codeblock generated, it is evicted from the writelookup and + added to the page_lookup for this purpose. When in the page_lookup, each write + will go through the mem_write_ram*_page() functions and set the dirty mask + appropriately. + + Each codeblock also contains a code mask (actually two masks, one for each + page the block is/may be in), again with each bit representing 64 bytes. + + Each page has a list of codeblocks present in it. As each codeblock can span + up to two pages, two lists are present. + + When a codeblock is about to be executed, the code masks are compared with the + dirty masks for the relevant pages. If either intersect, then + codegen_check_flush() is called on the affected page(s), and all affected + blocks are evicted. + + The 64 byte granularity appears to work reasonably well for most cases, + avoiding most unnecessary evictions (eg when code & data are stored in the + same page). +*/ + typedef struct codeblock_t { + /*Previous and next pointers, for the codeblock list associated with + each physical page. Two sets of pointers, as a codeblock can be + present in two pages.*/ struct codeblock_t *prev, *next; + struct codeblock_t *prev_2, *next_2; uint32_t pc; uint32_t _cs; uint32_t endpc; - uint32_t checksum; - uint32_t phys; + uint32_t phys, phys_2; uint32_t use32; int pnt; int ins; + uint64_t page_mask, page_mask2; - uint8_t data[8192]; + uint8_t data[2048]; } codeblock_t; +#define PAGE_MASK_MASK 63 +#define PAGE_MASK_SHIFT 6 + extern codeblock_t *codeblock; extern codeblock_t **codeblock_hash; -extern uint8_t *codeblock_page_dirty; void codegen_init(); +void codegen_reset(); void codegen_block_init(uint32_t phys_addr); void codegen_block_remove(); void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); @@ -35,8 +67,7 @@ void codegen_generate_seg_restore(); void codegen_check_abrt(); void codegen_set_op32(); void codegen_flush(); -void codegen_dirty(uint32_t addr); -int codegen_check_dirty(uint32_t phys_addr); +void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); extern int cpu_block_end; @@ -80,7 +111,7 @@ extern int block_pos; static inline void addbyte(uint8_t val) { codeblock[block_current].data[block_pos++] = val; - if (block_pos >= 8000) + if (block_pos >= 1850) { CPU_BLOCK_END(); } @@ -90,7 +121,7 @@ static inline void addword(uint16_t val) { *(uint16_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 2; - if (block_pos >= 8000) + if (block_pos >= 1850) { CPU_BLOCK_END(); } @@ -100,10 +131,12 @@ static inline void addlong(uint32_t val) { *(uint32_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 4; - if (block_pos >= 8000) + if (block_pos >= 1850) { CPU_BLOCK_END(); } } +/*Current physical page of block being recompiled. -1 if no recompilation taking place */ +extern uint32_t recomp_page; #endif diff --git a/src/codegen_timing_486.c b/src/codegen_timing_486.c index 1161860..60fea35 100644 --- a/src/codegen_timing_486.c +++ b/src/codegen_timing_486.c @@ -5,6 +5,7 @@ #include "x86.h" #include "x86_ops.h" #include "x87.h" +#include "mem.h" #include "codegen.h" #define CYCLES(c) (int *)c diff --git a/src/codegen_timing_pentium.c b/src/codegen_timing_pentium.c index 7f9ff28..66fe65e 100644 --- a/src/codegen_timing_pentium.c +++ b/src/codegen_timing_pentium.c @@ -16,6 +16,7 @@ #include "x86.h" #include "x86_ops.h" #include "x87.h" +#include "mem.h" #include "codegen.h" /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 9497c98..55ce35f 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -1,5 +1,3 @@ -#define CHECKSUM - #ifdef DYNAREC #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 @@ -10,6 +8,7 @@ #include "x86_flags.h" #include "x86_ops.h" #include "x87.h" +#include "mem.h" #include "codegen.h" #include "codegen_ops.h" @@ -17,20 +16,14 @@ #include "386_common.h" -#define BLOCK_EXIT_OFFSET 0x1ff0 +#define BLOCK_EXIT_OFFSET 0x7f0 + +uint32_t recomp_page = -1; int host_reg_mapping[NR_HOST_REGS]; codeblock_t *codeblock; codeblock_t **codeblock_hash; -typedef struct page_t -{ - codeblock_t *block; -} page_t; - -page_t *pages; - -uint8_t *codeblock_page_dirty; int block_current = 0; static int block_num; @@ -56,16 +49,17 @@ void codegen_init() codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - pages = malloc(((256 * 1024 * 1024) >> 12) * sizeof(page_t)); memset(codeblock, 0, sizeof(BLOCK_SIZE * sizeof(codeblock_t))); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - memset(pages, 0, ((256 * 1024 * 1024) >> 12) * sizeof(page_t)); - codeblock_page_dirty = malloc(1 << 20); - memset(codeblock_page_dirty, 1, 1 << 20); - - pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +} + +void codegen_reset() +{ + memset(codeblock, 0, sizeof(BLOCK_SIZE * sizeof(codeblock_t))); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); } void dump_block() @@ -86,173 +80,103 @@ void dump_block() pclog("dump_block done\n"); } -int codegen_check_dirty(uint32_t phys_addr) +static void delete_block(codeblock_t *block) { -#ifdef CHECKSUM - int has_evicted = 0; - int dirty = 0; - codeblock_t *block = pages[phys_addr >> 12].block; -//pclog("codegen_check_dirty %08x %08x\n", phys_addr, pages[phys_addr >> 12].block); -// if ((phys_addr & ~0xfff) == 0x119000) pclog("dirty start\n"); +// pclog("delete_block: pc=%08x\n", block->pc); + codeblock_hash[HASH(block->phys)] = NULL; + + if (!block->pc) + fatal("Deleting deleted block\n"); + block->pc = 0; + + if (block->prev) + { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } + else + { + pages[block->phys >> 12].block = block->next; + if (block->next) + block->next->prev = NULL; + else + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) + { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } + + if (block->prev_2) + { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } + else + { +// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); + pages[block->phys_2 >> 12].block_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } +} + +void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block; + while (block) { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - uint32_t checksum = 0; -// if ((phys_addr & ~0xfff) == 0x119000) pclog(" %08x\n", block->pc); - if (!block->pc) - fatal("!PC\n"); - -// if ((phys_addr & ~0xfff) == 0x119000) dump_block(); - -// if ((phys_addr & ~0xfff) == 0x119000) pclog(" %08x-%08x %08x-%08x\n", start_pc, end_pc, block->pc, block->endpc); - if (end_pc > start_pc) + if (mask & block->page_mask) { - for (; start_pc <= end_pc; start_pc += 4) - checksum += *(uint32_t *)&ram[start_pc]; + delete_block(block); + cpu_recomp_evicted++; } - else - checksum = ~block->checksum; - - if (checksum != block->checksum) - { -// if ((phys_addr & ~0xfff) == 0x119000) pclog(" evict %08x %08x %p\n", checksum, block->checksum, (void *)block->prev); - if (block->pc == (cs+pc)) - dirty = 1; - - block->pc = 0;//xffffffff; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block = block->next; - if (block->next) - block->next->prev = NULL; - } - - has_evicted = 1; - - codeblock_hash[HASH(block->phys)] = NULL; - } - + if (block == block->next) + fatal("Broken 1\n"); block = block->next; } -// if ((phys_addr & ~0xfff) == 0x8f000) pclog("dirty end\n"); - if (has_evicted) + + block = page->block_2; + + while (block) { - cpu_recomp_evicted++; - + if (mask & block->page_mask2) + { + delete_block(block); + cpu_recomp_evicted++; + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; } - - mem_flush_write_page(phys_addr, cs+pc); - - codeblock_page_dirty[phys_addr >> 12] = 0; - return dirty; -#else - return 1; -#endif } void codegen_block_init(uint32_t phys_addr) { codeblock_t *block; int has_evicted = 0; -// pclog("block_init %08x:%08x hash=%04x %08x\n", cs, pc, HASH(cs + pc), phys_addr); -//if (phys_addr > 0x100000) -// dump_block(); - if (codeblock_page_dirty[phys_addr >> 12]) - { - codeblock_t *last_block = NULL; - block = pages[phys_addr >> 12].block; -// pages[phys_addr >> 12].block = NULL; -// if ((phys_addr & ~0xfff) == 0x119000) pclog("Flush %08x\n", phys_addr); -//pclog("init start\n"); - while (block) - { - codeblock_t *old_block = block; - codeblock_t *next_block = block->next; - - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - uint32_t checksum = 0; - - if (!block->pc) - fatal("!PC on init\n"); - -//if ((phys_addr & ~0xfff) == 0x119000) dump_block(); - -// if ((phys_addr & ~0xfff) == 0x119000) pclog(" %p : %08x-%08x %08x-%08x\n", (void *)block, start_pc, end_pc, block->pc, block->endpc); - if (end_pc > start_pc) - { - for (; start_pc <= end_pc; start_pc += 4) - checksum += *(uint32_t *)&ram[start_pc]; - } - else - checksum = ~block->checksum; - - if (checksum != block->checksum) - { - if ((phys_addr & ~0xfff) == 0x119000) pclog(" evict %08x %08x %08x %p %p\n", block->pc, checksum, block->checksum, (void *)block->prev, (void *)last_block); - block->pc = 0;//xffffffff; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block = block->next; - if (block->next) - block->next->prev = NULL; - } - - codeblock_hash[HASH(block->phys)] = NULL; - - block->next = NULL; - } - - block = next_block; - last_block = old_block; - } -//if ((phys_addr & ~0xfff) == 0x119000) pclog("init end\n"); - codeblock_page_dirty[phys_addr >> 12] = 0; - mem_flush_write_page(phys_addr, cs+pc); - } + page_t *page = &pages[phys_addr >> 12]; -/* if (has_evicted) - cpu_recomp_evicted++;*/ -// pclog("Build %08x\n",cs+pc); - + if (!page->block) + mem_flush_write_page(phys_addr, cs+pc); + block_current = (block_current + 1) & BLOCK_MASK; block = &codeblock[block_current]; - if (block->pc != 0)//xffffffff) + +// if (block->pc == 0xb00b4ff5) +// pclog("Init target block\n"); + if (block->pc != 0) { -// if ((phys_addr & ~0xfff) == 0x119000) pclog("Block reuse - %04x old_pc=%08x new_pc=%08x\n", block_current, block->pc, cs+pc); -// if ((phys_addr & ~0xfff) == 0x119000) dump_block(); - /*Block currently used - throw out contents*/ - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block = block->next; - if (block->next) - block->next->prev = NULL; - } - codeblock_hash[HASH(block->phys)] = NULL; +// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); + delete_block(block); cpu_recomp_reuse++; -// if ((phys_addr & ~0xfff) == 0x119000) pclog("Block reuse end\n"); -// if ((phys_addr & ~0xfff) == 0x119000) dump_block(); } block_num = HASH(phys_addr); codeblock_hash[block_num] = &codeblock[block_current]; @@ -265,7 +189,6 @@ void codegen_block_init(uint32_t phys_addr) block->next = block->prev = NULL; block_pos = 0; - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ addbyte(0x83); /*ADDL $8,%esp*/ addbyte(0xC4); @@ -287,16 +210,21 @@ void codegen_block_init(uint32_t phys_addr) codegen_timing_block_start(); codegen_block_ins = 0; + + recomp_page = phys_addr & ~0xfff; } void codegen_block_remove() { codeblock_t *block = &codeblock[block_current]; //if ((block->phys & ~0xfff) == 0x119000) pclog("codegen_block_remove %08x\n", block->pc); +// if (block->pc == 0xb00b4ff5) +// pclog("Remove target block\n"); codeblock_hash[block_num] = NULL; block->pc = 0;//xffffffff; cpu_recomp_removed++; // pclog("Remove block %i\n", block_num); + recomp_page = -1; } void codegen_block_end() @@ -305,12 +233,12 @@ void codegen_block_end() codeblock_t *block_prev = pages[block->phys >> 12].block; uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); uint32_t end_pc = ((codegen_endpc + 3) & 0xffc) | (block->phys & ~0xfff); - uint32_t checksum = 0; - block->endpc = end_pc; + block->endpc = codegen_endpc; + +// if (block->pc == 0xb00b4ff5) +// pclog("End target block\n"); -//if ((block->phys & ~0xfff) == 0x119000) pclog("codegen_block_end start\n"); -//if ((block->phys & ~0xfff) == 0x119000) dump_block(); if (block_prev) { block->next = block_prev; @@ -323,21 +251,80 @@ void codegen_block_end() pages[block->phys >> 12].block = block; } -//if ((block->phys & ~0xfff) == 0x119000) pclog("codegen_block_end end\n"); -//if ((block->phys & ~0xfff) == 0x119000) dump_block(); - -#ifdef CHECKSUM - if (end_pc > start_pc) + if (block->next) { -// pclog("block_end %08x-%08x %08x-%08x\n", start_pc, end_pc, block->pc, block->endpc); - for (; start_pc <= end_pc; start_pc += 4) - checksum += *(uint32_t *)&ram[start_pc]; -// pclog(" %08x\n", checksum); +// pclog(" next->pc=%08x\n", block->next->pc); + if (!block->next->pc) + fatal("block->next->pc=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); } -#endif + + block->page_mask = 0; + start_pc = block->pc & 0xffc; + start_pc &= ~PAGE_MASK_MASK; + end_pc = ((block->endpc & 0xffc) + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + if (end_pc > 0xfff || end_pc < start_pc) + end_pc = 0xfff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; - block->checksum = checksum; -// pclog("Checksum for %08x - %08x = %08x\n", codeblock_hash_pc[block_num] & ~3, end_pc, checksum); +// pclog("block_end: %08x %08x\n", start_pc, end_pc); + for (; start_pc <= end_pc; start_pc++) + { + block->page_mask |= ((uint64_t)1 << start_pc); +// pclog(" %08x %llx\n", start_pc, block->page_mask); + } + + pages[block->phys >> 12].code_present_mask |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0xfff) + { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) + { +// pclog("start block - %08x %08x %p %p %p %08x\n", block->pc, block->endpc, (void *)block, (void *)block->next_2, (void *)pages[block->phys_2 >> 12].block_2, block->phys_2); + + if (pages[block->phys_2 >> 12].block_2 == block) + fatal("Block same\n"); + + block_prev = pages[block->phys_2 >> 12].block_2; + + if (block_prev) + { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2 = block; +// pclog(" pages.block_2=%p\n", (void *)block); + } + else + { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2 = block; +// pclog(" pages.block_2=%p 2\n", (void *)block); + } + + start_pc = 0; + end_pc = (block->endpc & 0xfff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t)1 << start_pc); + + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, block->endpc); +// pclog("New block - %08x %08x %p %p phys %08x %08x %016llx\n", block->pc, block->endpc, (void *)block, (void *)block->next_2, block->phys, block->phys_2, block->page_mask2); + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) + { +// pclog(" next_2->pc=%08x\n", block->next_2->pc); + if (!block->next_2->pc) + fatal("block->next_2->pc=0 %p\n", (void *)block->next_2); + } + } + } + +// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); codegen_timing_block_end(); @@ -361,6 +348,8 @@ void codegen_block_end() addbyte(0x08); addbyte(0xC3); /*RET*/ // pclog("End block %i\n", block_num); + + recomp_page = -1; } void codegen_flush() @@ -368,25 +357,6 @@ void codegen_flush() return; } -void codegen_dirty(uint32_t addr) -{ - codeblock_page_dirty[addr >> 12] = 1; -// pclog("codegen_dirty : %08x %04x:%04x\n", addr, CS, pc); -// if ((addr >> 12) == 0x152) -// pclog("Dirty : %08x %08x\n", addr, cs+pc); -/* int c; - int offset = HASH(addr & ~0xfff); -// pclog("codegen_dirty %08X\n", addr); - for (c = 0; c < 0x1000; c++) - { - if (!((codeblock_hash_pc[(c + offset) & HASH_MASK] ^ addr) & ~0xfff)) - { -// pclog("Throwing out %08X\n", codeblock_hash_pc[(c + offset) & HASH_MASK]); - codeblock_hash_pc[(c + offset) & HASH_MASK] = 0xffffffff; - } - }*/ -} - static int opcode_needs_tempc[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*00*/ @@ -482,7 +452,7 @@ void codegen_debug() { if (output) { - pclog("At %04x(%08x):%04x %04x(%08x):%04x EAX=%08x BX=%04x BP=%04x EDX=%08x\n", CS, cs, pc, SS, ss, ESP, EAX, BX,BP, EDX); + pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); } } diff --git a/src/cpu.c b/src/cpu.c index a349cfb..367a633 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -4,6 +4,7 @@ #include "io.h" #include "x86_ops.h" #ifdef DYNAREC +#include "mem.h" #include "codegen.h" #endif diff --git a/src/mem.c b/src/mem.c index 134a995..316edcb 100644 --- a/src/mem.c +++ b/src/mem.c @@ -20,6 +20,9 @@ #include "codegen.h" #endif +page_t *pages; +page_t **page_lookup; + 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); @@ -468,6 +471,7 @@ void resetreadlookup() 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; @@ -494,10 +498,11 @@ void flushmmucache() readlookup2[readlookup[c]]=0xFFFFFFFF; readlookup[c]=0xFFFFFFFF; } - if (writelookup[c]!=0xFFFFFFFF) + if (writelookup[c] != 0xFFFFFFFF) { - writelookup2[writelookup[c]]=0xFFFFFFFF; - writelookup[c]=0xFFFFFFFF; + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = 0xffffffff; + writelookup[c] = 0xFFFFFFFF; } } mmuflush++; @@ -541,10 +546,11 @@ void flushmmucache_nopc() readlookup2[readlookup[c]]=0xFFFFFFFF; readlookup[c]=0xFFFFFFFF; } - if (writelookup[c]!=0xFFFFFFFF) + if (writelookup[c] != 0xFFFFFFFF) { - writelookup2[writelookup[c]]=0xFFFFFFFF; - writelookup[c]=0xFFFFFFFF; + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = 0xffffffff; + writelookup[c] = 0xFFFFFFFF; } } } @@ -560,10 +566,11 @@ void flushmmucache_cr3() readlookup2[readlookup[c]]=0xFFFFFFFF; readlookup[c]=0xFFFFFFFF; } - if (writelookup[c]!=0xFFFFFFFF)// && !writelookupp[c]) + if (writelookup[c] != 0xFFFFFFFF)// && !writelookupp[c]) { - writelookup2[writelookup[c]]=0xFFFFFFFF; - writelookup[c]=0xFFFFFFFF; + page_lookup[writelookup[c]] = NULL; + writelookup2[writelookup[c]] = 0xffffffff; + writelookup[c] = 0xFFFFFFFF; } } /* for (c = 0; c < 1024*1024; c++) @@ -583,19 +590,27 @@ void flushmmucache_cr3() }*/ } - void mem_flush_write_page(uint32_t addr, uint32_t virt) { int c; + page_t *page_target = &pages[addr >> 12]; +// pclog("mem_flush_write_page %08x %08x\n", virt, addr); for (c = 0; c < 256; c++) { - uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xFFF) - (uintptr_t)(writelookup[c] << 12)]; - - if (writelookup2[writelookup[c]] == target) + if (writelookup[c] != 0xffffffff) { - writelookup2[writelookup[c]] = 0xffffffff; - writelookup[c] = 0xffffffff; + uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; + +// if ((virt & ~0xfff) == 0xc022e000) +// pclog(" Checking %02x %p %p\n", (void *)writelookup2[writelookup[c]], (void *)target); + if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) + { +// pclog(" throw out %02x %p %p\n", writelookup[c], (void *)page_lookup[writelookup[c]], (void *)writelookup2[writelookup[c]]); + writelookup2[writelookup[c]] = 0xffffffff; + page_lookup[writelookup[c]] = NULL; + writelookup[c] = 0xffffffff; + } } } } @@ -649,7 +664,7 @@ uint32_t mmutranslatereal(uint32_t addr, int rw) if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG))) { // if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw); - + // dumpregs(); // exit(-1); // if (addr == 0x815F6E90) output = 3; @@ -677,6 +692,29 @@ uint32_t mmutranslatereal(uint32_t addr, int rw) return (temp&~0xFFF)+(addr&0xFFF); } +uint32_t mmutranslate_noabrt(uint32_t addr, int rw) +{ + uint32_t addr2; + uint32_t temp,temp2,temp3; + + if (abrt) + return -1; + + addr2=(cr3+((addr>>20)&0xFFC)); + temp=temp2=((uint32_t *)ram)[addr2>>2]; + + if (!(temp&1)) + return -1; + + temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2]; + 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) { // readlookup2[addr >> 12] = writelookup2[addr >> 12] = 0xFFFFFFFF; @@ -738,7 +776,7 @@ void addwritelookup(uint32_t virt, uint32_t phys) if (virt == 0xffffffff) return; - if (writelookup2[virt>>12]!=0xFFFFFFFF) + if (page_lookup[virt >> 12]) { /* if (writelookup2[virt>>12] != phys&~0xfff) { @@ -761,19 +799,24 @@ void addwritelookup(uint32_t virt, uint32_t phys) } cycles-=memwaitstate; - if (writelookup[writelnext]!=0xFFFFFFFF) + if (writelookup[writelnext] != 0xFFFFFFFF) { + page_lookup[writelookup[writelnext]] = NULL; writelookup2[writelookup[writelnext]]=0xFFFFFFFF; // writelnum--; } - 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); - +// if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff)) +// fatal("Bad write mapping\n"); #if DYNAREC - codegen_dirty(phys); + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) + page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; + else #endif + writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; +// pclog("addwritelookup %08x %08x %p %p %016llx %p\n", virt, phys, (void *)page_lookup[virt >> 12], (void *)writelookup2[virt >> 12], pages[phys >> 12].dirty_mask, (void *)&pages[phys >> 12]); + writelookupp[writelnext] = mmu_perm; + writelookup[writelnext++] = virt >> 12; + writelnext &= (cachesize - 1); } #undef printf @@ -827,6 +870,11 @@ void writemembl(uint32_t addr, uint8_t val) { mem_logical_addr = addr; + 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); @@ -875,6 +923,11 @@ void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) } mem_logical_addr = addr = addr + seg; + 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); @@ -957,6 +1010,11 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val) printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr); 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); @@ -1042,6 +1100,11 @@ void writememll(uint32_t seg, uint32_t addr, uint32_t val) printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr); 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); @@ -1112,23 +1175,61 @@ uint32_t mem_read_raml(uint32_t addr, void *priv) return *(uint32_t *)&ram[addr]; } +static void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ + if (p->mem[addr & 0xfff] != val) + { +#if DYNAREC + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); +// pclog("mem_write_ramb_page: %08x %02x %08x\n", addr, val, cs+pc); + p->dirty_mask |= mask; +#endif + p->mem[addr & 0xfff] = val; + } +} +static void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ + if (*(uint16_t *)&p->mem[addr & 0xfff] != val) + { +#if DYNAREC + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0x3f) == 0x3f) + mask |= (mask << 1); +// pclog("mem_write_ramw_page: %08x %04x %08x\n", addr, val, cs+pc); + p->dirty_mask |= mask; +#endif + *(uint16_t *)&p->mem[addr & 0xfff] = val; + } +} +static void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ + if (*(uint32_t *)&p->mem[addr & 0xfff] != val) + { +#if DYNAREC + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0x3f) >= 0x3d) + mask |= (mask << 1); +// pclog("mem_write_raml_page: %08x %08x %08x\n", addr, val, cs+pc); + p->dirty_mask |= mask; +#endif + *(uint32_t *)&p->mem[addr & 0xfff] = val; + } +} + void mem_write_ram(uint32_t addr, uint8_t val, void *priv) { addwritelookup(mem_logical_addr, addr); - ram[addr] = val; -// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMb %08X\n", 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); - *(uint16_t *)&ram[addr] = val; -// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMw %08X %04X:%04X %i %04X %04X:%04X %04X:%04X\n", addr, CS, pc, ins, val, DS,SI, ES,DI); + 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); - *(uint32_t *)&ram[addr] = val; -// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI); + mem_write_raml_page(addr, val, &pages[addr >> 12]); } uint8_t mem_read_bios(uint32_t addr, void *priv) @@ -1433,8 +1534,21 @@ void mem_init() writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); cachelookup2 = malloc(1024 * 1024); biosmask = 0xffff; + pages = malloc(((mem_size * 1024 * 1024) >> 12) * sizeof(page_t)); + page_lookup = malloc((1 << 20) * sizeof(page_t *)); memset(ram, 0, mem_size * 1024 * 1024); + memset(pages, 0, ((mem_size * 1024 * 1024) >> 12) * sizeof(page_t)); + + memset(page_lookup, 0, (1 << 20) * sizeof(page_t *)); + + for (c = 0; c < ((mem_size * 1024 * 1024) >> 12); 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 * 16); c++) @@ -1476,6 +1590,17 @@ void mem_resize() ram = malloc(mem_size * 1024 * 1024); memset(ram, 0, mem_size * 1024 * 1024); + free(pages); + pages = malloc(((mem_size * 1024 * 1024) >> 12) * sizeof(page_t)); + memset(pages, 0, ((mem_size * 1024 * 1024) >> 12) * sizeof(page_t)); + for (c = 0; c < ((mem_size * 1024 * 1024) >> 12); 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 * 16); c++) { diff --git a/src/mem.h b/src/mem.h index 6991e00..6ac2cc8 100644 --- a/src/mem.h +++ b/src/mem.h @@ -98,3 +98,39 @@ void mem_write_nulll(uint32_t addr, uint32_t val, void *p); FILE *romfopen(char *fn, char *mode); mem_mapping_t bios_mapping[8]; + + +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, *block_2; + + uint64_t code_present_mask, dirty_mask; +} page_t; + +extern page_t *pages; + +extern page_t **page_lookup; + +uint32_t mmutranslate_noabrt(uint32_t addr, int rw); + +static inline get_phys(uint32_t addr) +{ + if (!(cr0 >> 31)) + return addr & rammask; + + return mmutranslatereal(addr, 0) & rammask; +} + +static inline get_phys_noabrt(uint32_t addr) +{ + if (!(cr0 >> 31)) + return addr & rammask; + + return mmutranslate_noabrt(addr, 0) & rammask; +} diff --git a/src/pc.c b/src/pc.c index a760e4c..3bd1aa2 100644 --- a/src/pc.c +++ b/src/pc.c @@ -7,6 +7,7 @@ #include "ali1429.h" #include "amstrad.h" #include "cdrom-ioctl.h" +#include "mem.h" #ifdef DYNAREC #include "x86_ops.h" #include "codegen.h" @@ -19,7 +20,6 @@ #include "sound_gus.h" #include "ide.h" #include "keyboard.h" -#include "mem.h" #include "model.h" #include "mouse.h" #include "nvr.h" diff --git a/src/win-status.c b/src/win-status.c index d817f55..9dbd6a4 100644 --- a/src/win-status.c +++ b/src/win-status.c @@ -10,6 +10,7 @@ #include "win.h" #ifdef DYNAREC #include "x86_ops.h" +#include "mem.h" #include "codegen.h" #endif diff --git a/src/x86.h b/src/x86.h index 1335cd7..3d1d851 100644 --- a/src/x86.h +++ b/src/x86.h @@ -101,12 +101,3 @@ extern int inscounts[256]; void x86illegal(); void x86seg_reset(); - - -static inline get_phys(uint32_t addr) -{ - if (!(cr0 >> 31)) - return addr & rammask; - - return mmutranslatereal(addr, 0) & rammask; -}