Reduce self modifying code granularity from 64 bytes to 16.

This commit is contained in:
SarahW 2017-06-13 21:05:10 +01:00
commit 3a7c4687d6
6 changed files with 95 additions and 78 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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];
}
}

View file

@ -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];
}
}

View file

@ -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;
}
}

View file

@ -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;