don't persist fastmem state for blocks that weren't invalidated by a fastmem exception

This commit is contained in:
Anthony Pesch 2017-07-12 22:58:17 -04:00
parent 578e032c7e
commit 559137d4a0
3 changed files with 50 additions and 37 deletions

View File

@ -179,51 +179,51 @@ static void sh4_frontend_analyze_code(struct jit_frontend *base,
if (def->flags & SH4_FLAG_SET_PC) { if (def->flags & SH4_FLAG_SET_PC) {
if (def->op == SH4_OP_BF) { if (def->op == SH4_OP_BF) {
uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; 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->branch_addr = dest_addr;
block->next_addr = addr + 4; block->next_addr = addr + 4;
} else if (def->op == SH4_OP_BFS) { } else if (def->op == SH4_OP_BFS) {
uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; 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->branch_addr = dest_addr;
block->next_addr = addr + 4; block->next_addr = addr + 4;
} else if (def->op == SH4_OP_BT) { } else if (def->op == SH4_OP_BT) {
uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; 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->branch_addr = dest_addr;
block->next_addr = addr + 4; block->next_addr = addr + 4;
} else if (def->op == SH4_OP_BTS) { } else if (def->op == SH4_OP_BTS) {
uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4; 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->branch_addr = dest_addr;
block->next_addr = addr + 4; block->next_addr = addr + 4;
} else if (def->op == SH4_OP_BRA) { } else if (def->op == SH4_OP_BRA) {
/* 12-bit displacement must be sign extended */ /* 12-bit displacement must be sign extended */
int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20; int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20;
uint32_t dest_addr = (disp * 2) + addr + 4; uint32_t dest_addr = (disp * 2) + addr + 4;
block->branch_type = BRANCH_STATIC; block->branch_type = JIT_BRANCH_STATIC;
block->branch_addr = dest_addr; block->branch_addr = dest_addr;
} else if (def->op == SH4_OP_BRAF) { } 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) { } else if (def->op == SH4_OP_BSR) {
/* 12-bit displacement must be sign extended */ /* 12-bit displacement must be sign extended */
int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20; int32_t disp = ((instr.disp_12.disp & 0xfff) << 20) >> 20;
uint32_t ret_addr = addr + 4; uint32_t ret_addr = addr + 4;
uint32_t dest_addr = ret_addr + disp * 2; uint32_t dest_addr = ret_addr + disp * 2;
block->branch_type = BRANCH_STATIC; block->branch_type = JIT_BRANCH_STATIC;
block->branch_addr = dest_addr; block->branch_addr = dest_addr;
} else if (def->op == SH4_OP_BSRF) { } 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) { } 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) { } 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) { } 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) { } 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) { } else if (def->op == SH4_OP_TRAPA) {
block->branch_type = BRANCH_DYNAMIC; block->branch_type = JIT_BRANCH_DYNAMIC;
} else { } else {
LOG_FATAL("unexpected branch op"); LOG_FATAL("unexpected branch op");
} }

View File

@ -139,7 +139,9 @@ static void jit_restore_edges(struct jit *jit, struct jit_block *block) {
PROF_LEAVE(); 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->backend->invalidate_code(jit->backend, block->guest_addr);
jit_restore_edges(jit, block); 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) { 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->blocks, &block->it, &block_map_cb);
rb_unlink(&jit->reverse_blocks, &block->rit, &reverse_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 rb_node *next = rb_next(it);
struct jit_block *block = container_of(it, struct jit_block, 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; it = next;
} }
@ -289,11 +291,15 @@ void jit_compile_block(struct jit *jit, uint32_t guest_addr) {
fastmem = 0; fastmem = 0;
#endif #endif
/* if the block being compiled had previously been invalidated by a fastmem /* if the block had previously been invalidated, finish removing it now */
exception, finish removing it at this time and disable fastmem opts */
struct jit_block *existing = jit_get_block(jit, guest_addr); struct jit_block *existing = jit_get_block(jit, guest_addr);
if (existing) { 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); jit_free_block(jit, existing);
} }
@ -360,12 +366,11 @@ static int jit_handle_exception(void *data, struct exception_state *ex) {
return 0; return 0;
} }
/* invalidate the block so it's recompiled without fastmem optimizations /* disable fastmem optimizations for this block on future compiles */
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 */
block->fastmem = 0; 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; return 1;
} }

View File

@ -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); typedef void (*mem_write_cb)(void *, uint32_t, uint32_t, uint32_t);
enum { enum {
BRANCH_STATIC, JIT_BRANCH_STATIC,
BRANCH_STATIC_TRUE, JIT_BRANCH_STATIC_TRUE,
BRANCH_STATIC_FALSE, JIT_BRANCH_STATIC_FALSE,
BRANCH_DYNAMIC, JIT_BRANCH_DYNAMIC,
BRANCH_DYNAMIC_TRUE, JIT_BRANCH_DYNAMIC_TRUE,
BRANCH_DYNAMIC_FALSE, JIT_BRANCH_DYNAMIC_FALSE,
};
enum {
JIT_REASON_UNKNOWN,
JIT_REASON_FASTMEM,
}; };
struct jit_block { struct jit_block {
@ -31,13 +36,6 @@ struct jit_block {
uint32_t guest_addr; uint32_t guest_addr;
int guest_size; 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 */ /* destination address of terminating branch */
int branch_type; int branch_type;
uint32_t branch_addr; uint32_t branch_addr;
@ -54,6 +52,16 @@ struct jit_block {
/* estimated number of guest cycles to execute block */ /* estimated number of guest cycles to execute block */
int num_cycles; 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 */ /* edges to other blocks */
struct list in_edges; struct list in_edges;
struct list out_edges; struct list out_edges;