diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 79c054e..6ce33ba 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -1440,7 +1440,7 @@ void exec386_dynarec(int cycs) { uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if (page->code_present_mask & mask) + if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) { /*Walk page tree to see if we find the correct block*/ codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); @@ -1453,10 +1453,11 @@ void exec386_dynarec(int cycs) } } } - if (valid_block && (block->page_mask & page->dirty_mask)) + + if (valid_block && (block->page_mask & *block->dirty_mask)) { - codegen_check_flush(page, page->dirty_mask, phys_addr); - page->dirty_mask = 0; + codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); + page->dirty_mask[(phys_addr >> 10) & 3] = 0; if (!block->pc) valid_block = 0; } @@ -1469,15 +1470,14 @@ void exec386_dynarec(int cycs) 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; + uint32_t phys_addr_2 = get_phys_noabrt(block->endpc); 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) + else if (block->page_mask2 & *block->dirty_mask2) { - codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); - page_2->dirty_mask = 0; + codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); + page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; if (!block->pc) valid_block = 0; } @@ -1562,7 +1562,7 @@ inrecomp=0; 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 ((cpu_state.pc - start_pc) > 4000) + if ((cpu_state.pc - start_pc) > 1000) CPU_BLOCK_END(); if (trap) @@ -1638,7 +1638,7 @@ inrecomp=0; 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 ((cpu_state.pc - start_pc) > 4000) + if ((cpu_state.pc - start_pc) > 1000) CPU_BLOCK_END(); if (trap) diff --git a/src/codegen.h b/src/codegen.h index cbac2b6..a88f39d 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -36,6 +36,7 @@ typedef struct codeblock_t { uint64_t page_mask, page_mask2; + uint64_t *dirty_mask, *dirty_mask2; uint64_t cmp; /*Previous and next pointers, for the codeblock list associated with @@ -236,8 +237,10 @@ static inline void codeblock_tree_delete(codeblock_t *block) } } +#define PAGE_MASK_INDEX_MASK 3 +#define PAGE_MASK_INDEX_SHIFT 10 #define PAGE_MASK_MASK 63 -#define PAGE_MASK_SHIFT 6 +#define PAGE_MASK_SHIFT 4 extern codeblock_t *codeblock; diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c index 5a35102..91de59f 100644 --- a/src/codegen_x86-64.c +++ b/src/codegen_x86-64.c @@ -99,7 +99,7 @@ void codegen_reset() void dump_block() { - codeblock_t *block = pages[0x119000 >> 12].block; +/* codeblock_t *block = pages[0x119000 >> 12].block; pclog("dump_block:\n"); while (block) @@ -112,12 +112,12 @@ void dump_block() block = block->next; } - pclog("dump_block done\n"); + pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) { - codeblock_t *block_prev = pages[block->phys >> 12].block; + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; if (!block->page_mask) fatal("add_to_block_list - mask = 0\n"); @@ -126,12 +126,12 @@ static void add_to_block_list(codeblock_t *block) { block->next = block_prev; block_prev->prev = block; - pages[block->phys >> 12].block = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; } else { block->next = NULL; - pages[block->phys >> 12].block = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; } if (block->next) @@ -142,18 +142,18 @@ static void add_to_block_list(codeblock_t *block) if (block->page_mask2) { - block_prev = pages[block->phys_2 >> 12].block_2; + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; if (block_prev) { block->next_2 = block_prev; block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } else { block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } } } @@ -171,7 +171,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } else { - pages[block->phys >> 12].block = block->next; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; if (block->next) block->next->prev = NULL; else @@ -193,7 +193,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) 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; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; if (block->next_2) block->next_2->prev_2 = NULL; else @@ -218,7 +218,7 @@ static void delete_block(codeblock_t *block) void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) { - struct codeblock_t *block = page->block; + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; while (block) { @@ -232,7 +232,7 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) block = block->next; } - block = page->block_2; + block = page->block_2[(phys_addr >> 10) & 3]; while (block) { @@ -252,7 +252,7 @@ void codegen_block_init(uint32_t phys_addr) codeblock_t *block; page_t *page = &pages[phys_addr >> 12]; - if (!page->block) + if (!page->block[(phys_addr >> 10) & 3]) mem_flush_write_page(phys_addr, cs+cpu_state.pc); block_current = (block_current + 1) & BLOCK_MASK; @@ -274,6 +274,8 @@ void codegen_block_init(uint32_t phys_addr) block->_cs = cs; block->pnt = block_current; block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; block->next = block->prev = NULL; block->next_2 = block->prev_2 = NULL; block->page_mask = 0; @@ -291,7 +293,7 @@ void codegen_block_start_recompile(codeblock_t *block) { page_t *page = &pages[block->phys >> 12]; - if (!page->block) + if (!page->block[(block->phys >> 10) & 3]) mem_flush_write_page(block->phys, cs+cpu_state.pc); block_num = HASH(block->phys); @@ -402,17 +404,19 @@ void codegen_block_remove() void codegen_block_generate_end_mask() { codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = ((codegen_endpc + 3) & 0xffc) | (block->phys & ~0xfff); + uint32_t start_pc; + uint32_t end_pc; block->endpc = codegen_endpc; 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 = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; start_pc >>= PAGE_MASK_SHIFT; end_pc >>= PAGE_MASK_SHIFT; @@ -423,26 +427,27 @@ void codegen_block_generate_end_mask() // pclog(" %08x %llx\n", start_pc, block->page_mask); } - pages[block->phys >> 12].code_present_mask |= block->page_mask; + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; block->phys_2 = -1; block->page_mask2 = 0; block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0xfff) + if ((block->pc ^ block->endpc) & ~0x3ff) { 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); + page_t *page_2 = &pages[block->phys_2 >> 12]; start_pc = 0; - end_pc = (block->endpc & 0xfff) >> PAGE_MASK_SHIFT; + end_pc = (block->endpc & 0x3ff) >> 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) + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) 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) @@ -451,6 +456,8 @@ void codegen_block_generate_end_mask() if (!block->next_2->pc) fatal("block->next_2->pc=0 %p\n", (void *)block->next_2); } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; } } diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 9739da8..0474703 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -1212,7 +1212,7 @@ void codegen_reset() void dump_block() { - codeblock_t *block = pages[0x119000 >> 12].block; +/* codeblock_t *block = pages[0x119000 >> 12].block; pclog("dump_block:\n"); while (block) @@ -1225,12 +1225,12 @@ void dump_block() block = block->next; } - pclog("dump_block done\n"); + pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) { - codeblock_t *block_prev = pages[block->phys >> 12].block; + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; if (!block->page_mask) fatal("add_to_block_list - mask = 0\n"); @@ -1239,12 +1239,12 @@ static void add_to_block_list(codeblock_t *block) { block->next = block_prev; block_prev->prev = block; - pages[block->phys >> 12].block = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; } else { block->next = NULL; - pages[block->phys >> 12].block = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; } if (block->next) @@ -1255,18 +1255,18 @@ static void add_to_block_list(codeblock_t *block) if (block->page_mask2) { - block_prev = pages[block->phys_2 >> 12].block_2; + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; if (block_prev) { block->next_2 = block_prev; block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } else { block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } } } @@ -1284,7 +1284,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } else { - pages[block->phys >> 12].block = block->next; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; if (block->next) block->next->prev = NULL; else @@ -1306,7 +1306,7 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) 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; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; if (block->next_2) block->next_2->prev_2 = NULL; else @@ -1331,7 +1331,7 @@ static void delete_block(codeblock_t *block) void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) { - struct codeblock_t *block = page->block; + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; while (block) { @@ -1345,7 +1345,7 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) block = block->next; } - block = page->block_2; + block = page->block_2[(phys_addr >> 10) & 3]; while (block) { @@ -1365,7 +1365,7 @@ void codegen_block_init(uint32_t phys_addr) codeblock_t *block; page_t *page = &pages[phys_addr >> 12]; - if (!page->block) + if (!page->block[(phys_addr >> 10) & 3]) mem_flush_write_page(phys_addr, cs+cpu_state.pc); block_current = (block_current + 1) & BLOCK_MASK; @@ -1387,6 +1387,8 @@ void codegen_block_init(uint32_t phys_addr) block->_cs = cs; block->pnt = block_current; block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; block->next = block->prev = NULL; block->next_2 = block->prev_2 = NULL; block->page_mask = 0; @@ -1404,7 +1406,7 @@ void codegen_block_start_recompile(codeblock_t *block) { page_t *page = &pages[block->phys >> 12]; - if (!page->block) + if (!page->block[(block->phys >> 10) & 3]) mem_flush_write_page(block->phys, cs+cpu_state.pc); block_num = HASH(block->phys); @@ -1489,17 +1491,19 @@ void codegen_block_remove() void codegen_block_generate_end_mask() { codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = ((codegen_endpc + 3) & 0xffc) | (block->phys & ~0xfff); + uint32_t start_pc; + uint32_t end_pc; block->endpc = codegen_endpc; 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 = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; start_pc >>= PAGE_MASK_SHIFT; end_pc >>= PAGE_MASK_SHIFT; @@ -1510,26 +1514,27 @@ void codegen_block_generate_end_mask() // pclog(" %08x %llx\n", start_pc, block->page_mask); } - pages[block->phys >> 12].code_present_mask |= block->page_mask; + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; block->phys_2 = -1; block->page_mask2 = 0; block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0xfff) + if ((block->pc ^ block->endpc) & ~0x3ff) { 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); + page_t *page_2 = &pages[block->phys_2 >> 12]; start_pc = 0; - end_pc = (block->endpc & 0xfff) >> PAGE_MASK_SHIFT; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; for (; start_pc <= end_pc; start_pc++) block->page_mask2 |= ((uint64_t)1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - if (!pages[block->phys_2 >> 12].block_2) + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) 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) @@ -1538,6 +1543,8 @@ void codegen_block_generate_end_mask() if (!block->next_2->pc) fatal("block->next_2->pc=0 %p\n", (void *)block->next_2); } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; } } diff --git a/src/mem.c b/src/mem.c index 8ce0d7c..2e4d4e0 100644 --- a/src/mem.c +++ b/src/mem.c @@ -988,7 +988,7 @@ void addwritelookup(uint32_t virt, uint32_t phys) // if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff)) // fatal("Bad write mapping\n"); - if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) + 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) page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; else writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -1516,7 +1516,7 @@ void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); // pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+pc, p->dirty_mask, mask); - p->dirty_mask |= mask; + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; p->mem[addr & 0xfff] = val; } } @@ -1525,10 +1525,10 @@ void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0x3f) == 0x3f) + if ((addr & 0xf) == 0xf) mask |= (mask << 1); // pclog("mem_write_ramw_page: %08x %04x %08x\n", addr, val, cs+pc); - p->dirty_mask |= mask; + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; *(uint16_t *)&p->mem[addr & 0xfff] = val; } } @@ -1537,10 +1537,10 @@ void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0x3f) >= 0x3d) + if ((addr & 0xf) >= 0xd) mask |= (mask << 1); // pclog("mem_write_raml_page: %08x %08x %08x\n", addr, val, cs+pc); - p->dirty_mask |= mask; + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; *(uint32_t *)&p->mem[addr & 0xfff] = val; } } @@ -1615,7 +1615,7 @@ void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - pages[start_addr >> 12].dirty_mask |= mask; + pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; } } @@ -2027,8 +2027,8 @@ void mem_reset_page_blocks() 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 = NULL; - pages[c].block_2 = NULL; + 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; } } diff --git a/src/mem.h b/src/mem.h index 370be13..b8c923c 100644 --- a/src/mem.h +++ b/src/mem.h @@ -112,12 +112,12 @@ typedef struct page_t uint8_t *mem; - struct codeblock_t *block, *block_2; + 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, dirty_mask; + uint64_t code_present_mask[4], dirty_mask[4]; } page_t; extern page_t *pages;