Implemented new memory mapping to improve performance of self modifying code.
New scheme allows code blocks to cross pages. Reduced code block size down to 2kB.
This commit is contained in:
parent
798c24d7c4
commit
b4592cdea3
14 changed files with 465 additions and 308 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue