diff --git a/src/jit/frontend/sh4/sh4_frontend.c b/src/jit/frontend/sh4/sh4_frontend.c index 972a27aa..e5f7fcba 100644 --- a/src/jit/frontend/sh4/sh4_frontend.c +++ b/src/jit/frontend/sh4/sh4_frontend.c @@ -179,51 +179,51 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base, if (def->flags & SH4_FLAG_SET_PC) { if (def->op == SH4_OP_BF) { uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; - block->branch_type = BRANCH_STATIC_FALSE; + block->branch_type = JIT_BRANCH_STATIC_FALSE; block->branch_addr = dest_addr; block->next_addr = addr + 4; } else if (def->op == SH4_OP_BFS) { uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; - block->branch_type = BRANCH_STATIC_FALSE; + block->branch_type = JIT_BRANCH_STATIC_FALSE; block->branch_addr = dest_addr; block->next_addr = addr + 4; } else if (def->op == SH4_OP_BT) { uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; - block->branch_type = BRANCH_STATIC_TRUE; + block->branch_type = JIT_BRANCH_STATIC_TRUE; block->branch_addr = dest_addr; block->next_addr = addr + 4; } else if (def->op == SH4_OP_BTS) { uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; - block->branch_type = BRANCH_STATIC_TRUE; + block->branch_type = JIT_BRANCH_STATIC_TRUE; block->branch_addr = dest_addr; block->next_addr = addr + 4; } else if (def->op == SH4_OP_BRA) { /* 12-bit displacement must be sign extended */ int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20; uint32_t dest_addr = (disp * 2) + addr + 4; - block->branch_type = BRANCH_STATIC; + block->branch_type = JIT_BRANCH_STATIC; block->branch_addr = dest_addr; } else if (def->op == SH4_OP_BRAF) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_BSR) { /* 12-bit displacement must be sign extended */ int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20; uint32_t ret_addr = addr + 4; uint32_t dest_addr = ret_addr + disp * 2; - block->branch_type = BRANCH_STATIC; + block->branch_type = JIT_BRANCH_STATIC; block->branch_addr = dest_addr; } else if (def->op == SH4_OP_BSRF) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_JMP) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_JSR) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_RTS) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_RTE) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else if (def->op == SH4_OP_TRAPA) { - block->branch_type = BRANCH_DYNAMIC; + block->branch_type = JIT_BRANCH_DYNAMIC; } else { LOG_FATAL("unexpected branch op"); } diff --git a/src/jit/jit.c b/src/jit/jit.c index a89b6693..cafddc78 100644 --- a/src/jit/jit.c +++ b/src/jit/jit.c @@ -139,7 +139,9 @@ static void jit_restore_edges(struct jit *jit, struct jit_block *block) { PROF_LEAVE(); } -static void jit_invalidate_block(struct jit *jit, struct jit_block *block) { +static void jit_invalidate_block(struct jit *jit, struct jit_block *block, int reason) { + block->invalidate_reason = reason; + jit->backend->invalidate_code(jit->backend, block->guest_addr); jit_restore_edges(jit, block); @@ -165,7 +167,7 @@ static void jit_cache_block(struct jit *jit, struct jit_block *block) { } static void jit_free_block(struct jit *jit, struct jit_block *block) { - jit_invalidate_block(jit, block); + jit_invalidate_block(jit, block, JIT_REASON_UNKNOWN); rb_unlink(&jit->blocks, &block->it, &block_map_cb); rb_unlink(&jit->reverse_blocks, &block->rit, &reverse_block_map_cb); @@ -224,7 +226,7 @@ void jit_invalidate_blocks(struct jit *jit) { struct rb_node *next = rb_next(it); struct jit_block *block = container_of(it, struct jit_block, it); - jit_invalidate_block(jit, block); + jit_invalidate_block(jit, block, JIT_REASON_UNKNOWN); it = next; } @@ -289,11 +291,15 @@ void jit_compile_block(struct jit *jit, uint32_t guest_addr) { fastmem = 0; #endif - /* if the block being compiled had previously been invalidated by a fastmem - exception, finish removing it at this time and disable fastmem opts */ + /* if the block had previously been invalidated, finish removing it now */ struct jit_block *existing = jit_get_block(jit, guest_addr); if (existing) { - fastmem = existing->fastmem; + /* if the block was invalidated due to a fastmem exception, persist its + fastmem state */ + if (existing->invalidate_reason == JIT_REASON_FASTMEM) { + fastmem = existing->fastmem; + } + jit_free_block(jit, existing); } @@ -360,12 +366,11 @@ static int jit_handle_exception(void *data, struct exception_state *ex) { return 0; } - /* invalidate the block so it's recompiled without fastmem optimizations - on the next access. note, the block can't be removed from the lookup - maps at this point because it's still executing and may raise more - exceptions */ + /* disable fastmem optimizations for this block on future compiles */ block->fastmem = 0; - jit_invalidate_block(jit, block); + + /* invalidate the block so it's recompiled on the next access */ + jit_invalidate_block(jit, block, JIT_REASON_FASTMEM); return 1; } diff --git a/src/jit/jit.h b/src/jit/jit.h index c6553f9d..6f4125fa 100644 --- a/src/jit/jit.h +++ b/src/jit/jit.h @@ -18,12 +18,17 @@ typedef uint32_t (*mem_read_cb)(void *, uint32_t, uint32_t); typedef void (*mem_write_cb)(void *, uint32_t, uint32_t, uint32_t); enum { - BRANCH_STATIC, - BRANCH_STATIC_TRUE, - BRANCH_STATIC_FALSE, - BRANCH_DYNAMIC, - BRANCH_DYNAMIC_TRUE, - BRANCH_DYNAMIC_FALSE, + JIT_BRANCH_STATIC, + JIT_BRANCH_STATIC_TRUE, + JIT_BRANCH_STATIC_FALSE, + JIT_BRANCH_DYNAMIC, + JIT_BRANCH_DYNAMIC_TRUE, + JIT_BRANCH_DYNAMIC_FALSE, +}; + +enum { + JIT_REASON_UNKNOWN, + JIT_REASON_FASTMEM, }; struct jit_block { @@ -31,13 +36,6 @@ struct jit_block { uint32_t guest_addr; int guest_size; - /* address of compiled block in host memory */ - void *host_addr; - int host_size; - - /* compile with fastmem support */ - int fastmem; - /* destination address of terminating branch */ int branch_type; uint32_t branch_addr; @@ -54,6 +52,16 @@ struct jit_block { /* estimated number of guest cycles to execute block */ int num_cycles; + /* compile with fastmem support */ + int fastmem; + + /* address of compiled block in host memory */ + void *host_addr; + int host_size; + + /* reason the block was invalidated */ + int invalidate_reason; + /* edges to other blocks */ struct list in_edges; struct list out_edges;