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->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");
}

View File

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

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