added branch type info to blocks

This commit is contained in:
Anthony Pesch 2017-07-10 19:45:08 -04:00
parent 1df4e5d3a4
commit bd97aa9603
4 changed files with 88 additions and 17 deletions

View File

@ -22,26 +22,28 @@ struct sh4_frontend {
static void sh4_analyze_block(const struct sh4_guest *guest, static void sh4_analyze_block(const struct sh4_guest *guest,
struct jit_block *block) { struct jit_block *block) {
uint32_t addr = block->guest_addr; uint32_t offset = 0;
block->guest_size = 0; block->guest_size = 0;
block->num_cycles = 0; block->num_cycles = 0;
block->num_instrs = 0; block->num_instrs = 0;
while (1) { while (1) {
uint32_t addr = block->guest_addr + offset;
uint32_t data = guest->r16(guest->space, addr); uint32_t data = guest->r16(guest->space, addr);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data); struct jit_opdef *def = sh4_get_opdef(data);
addr += 2; offset += 2;
block->guest_size += 2; block->guest_size += 2;
block->num_cycles += def->cycles; block->num_cycles += def->cycles;
block->num_instrs++; block->num_instrs++;
if (def->flags & SH4_FLAG_DELAYED) { if (def->flags & SH4_FLAG_DELAYED) {
uint32_t delay_data = guest->r16(guest->space, addr); uint32_t delay_data = guest->r16(guest->space, addr + 2);
struct jit_opdef *delay_def = sh4_get_opdef(delay_data); struct jit_opdef *delay_def = sh4_get_opdef(delay_data);
addr += 2; offset += 2;
block->guest_size += 2; block->guest_size += 2;
block->num_cycles += delay_def->cycles; block->num_cycles += delay_def->cycles;
block->num_instrs++; block->num_instrs++;
@ -50,11 +52,65 @@ static void sh4_analyze_block(const struct sh4_guest *guest,
CHECK(!(delay_def->flags & SH4_FLAG_DELAYED)); CHECK(!(delay_def->flags & SH4_FLAG_DELAYED));
} }
/* stop emitting once a branch has been hit. in addition, if fpscr has /* stop emitting once a branch is hit and save off branch information */
changed, stop emitting since the fpu state is invalidated. also, if if (def->flags & SH4_FLAG_SET_PC) {
sr has changed, stop emitting as there are interrupts that possibly if (def->op == SH4_OP_BF) {
need to be handled */ uint32_t dest_addr = ((int8_t)instr.disp_8.disp * 2) + addr + 4;
if (def->flags & (SH4_FLAG_SET_PC | SH4_FLAG_SET_FPSCR | SH4_FLAG_SET_SR)) { block->branch_type = 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_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_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_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_addr = dest_addr;
} else if (def->op == SH4_OP_BRAF) {
block->branch_type = 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_addr = dest_addr;
} else if (def->op == SH4_OP_BSRF) {
block->branch_type = BRANCH_DYNAMIC;
} else if (def->op == SH4_OP_JMP) {
block->branch_type = BRANCH_DYNAMIC;
} else if (def->op == SH4_OP_JSR) {
block->branch_type = BRANCH_DYNAMIC;
} else if (def->op == SH4_OP_RTS) {
block->branch_type = BRANCH_DYNAMIC;
} else if (def->op == SH4_OP_RTE) {
block->branch_type = BRANCH_DYNAMIC;
} else if (def->op == SH4_OP_TRAPA) {
block->branch_type = BRANCH_DYNAMIC;
} else {
LOG_FATAL("unexpected branch op");
}
break;
}
/* if fpscr has changed, stop emitting since the fpu state is invalidated.
also, if sr has changed, stop emitting as there are interrupts that
possibly need to be handled */
if (def->flags & (SH4_FLAG_SET_FPSCR | SH4_FLAG_SET_SR)) {
break; break;
} }
} }

View File

@ -1065,8 +1065,7 @@ INSTR(BT) {
/* BTS disp */ /* BTS disp */
INSTR(BTS) { INSTR(BTS) {
/* 8-bit displacement must be sign extended */ /* 8-bit displacement must be sign extended */
int32_t disp = (int32_t)(int8_t)i.disp_8.disp; uint32_t dest_addr = ((int8_t)i.disp_8.disp * 2) + addr + 4;
uint32_t dest_addr = (disp * 2) + addr + 4;
I32 cond = LOAD_T_I32(); I32 cond = LOAD_T_I32();
DELAY_INSTR(); DELAY_INSTR();
BRANCH_TRUE_IMM_I32(cond, dest_addr); BRANCH_TRUE_IMM_I32(cond, dest_addr);
@ -1317,6 +1316,11 @@ INSTR(LDSMPR) {
NEXT_INSTR(); NEXT_INSTR();
} }
/* LDTLB */
INSTR(LDTLB) {
LDTLB();
}
/* MOVCA.L R0,@Rn */ /* MOVCA.L R0,@Rn */
INSTR(MOVCAL) { INSTR(MOVCAL) {
I32 ea = LOAD_GPR_I32(i.def.rn); I32 ea = LOAD_GPR_I32(i.def.rn);
@ -1379,11 +1383,6 @@ INSTR(SLEEP) {
SLEEP(); SLEEP();
} }
/* LDTLB */
INSTR(LDTLB) {
LDTLB();
}
/* STC SR,Rn */ /* STC SR,Rn */
INSTR(STCSR) { INSTR(STCSR) {
I32 v = LOAD_SR_I32(); I32 v = LOAD_SR_I32();

View File

@ -135,7 +135,6 @@ SH4_INSTR(RTS, "rts", 0000000000001011, 2, SH4_FL
// system control instructions // system control instructions
SH4_INSTR(LDTLB, "ldtlb", 0000000000111000, 1, 0)
SH4_INSTR(CLRMAC, "clrmac", 0000000000101000, 1, 0) SH4_INSTR(CLRMAC, "clrmac", 0000000000101000, 1, 0)
SH4_INSTR(CLRS, "clrs", 0000000001001000, 1, 0) SH4_INSTR(CLRS, "clrs", 0000000001001000, 1, 0)
SH4_INSTR(CLRT, "clrt", 0000000000001000, 1, 0) SH4_INSTR(CLRT, "clrt", 0000000000001000, 1, 0)
@ -159,6 +158,7 @@ SH4_INSTR(LDSPR, "lds rn, pr", 0100mmmm00101010, 2, 0)
SH4_INSTR(LDSMMACH, "lds.l @rn+, mach", 0100mmmm00000110, 1, SH4_FLAG_LOAD) SH4_INSTR(LDSMMACH, "lds.l @rn+, mach", 0100mmmm00000110, 1, SH4_FLAG_LOAD)
SH4_INSTR(LDSMMACL, "lds.l @rn+, macl", 0100mmmm00010110, 1, SH4_FLAG_LOAD) SH4_INSTR(LDSMMACL, "lds.l @rn+, macl", 0100mmmm00010110, 1, SH4_FLAG_LOAD)
SH4_INSTR(LDSMPR, "lds.l @rn+, pr", 0100mmmm00100110, 2, SH4_FLAG_LOAD) SH4_INSTR(LDSMPR, "lds.l @rn+, pr", 0100mmmm00100110, 2, SH4_FLAG_LOAD)
SH4_INSTR(LDTLB, "ldtlb", 0000000000111000, 1, 0)
SH4_INSTR(MOVCAL, "movca.l r0, @rn", 0000nnnn11000011, 1, SH4_FLAG_STORE) SH4_INSTR(MOVCAL, "movca.l r0, @rn", 0000nnnn11000011, 1, SH4_FLAG_STORE)
SH4_INSTR(NOP, "nop", 0000000000001001, 1, 0) SH4_INSTR(NOP, "nop", 0000000000001001, 1, 0)
SH4_INSTR(OCBI, "ocbi", 0000nnnn10010011, 1, 0) SH4_INSTR(OCBI, "ocbi", 0000nnnn10010011, 1, 0)

View File

@ -17,6 +17,15 @@ struct val;
typedef uint32_t (*mem_read_cb)(void *, uint32_t, uint32_t); 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 {
BRANCH_STATIC,
BRANCH_STATIC_TRUE,
BRANCH_STATIC_FALSE,
BRANCH_DYNAMIC,
BRANCH_DYNAMIC_TRUE,
BRANCH_DYNAMIC_FALSE,
};
struct jit_block { struct jit_block {
/* address of source block in guest memory */ /* address of source block in guest memory */
uint32_t guest_addr; uint32_t guest_addr;
@ -29,6 +38,13 @@ struct jit_block {
/* compile with fastmem support */ /* compile with fastmem support */
int fastmem; int fastmem;
/* destination address of terminating branch */
int branch_type;
uint32_t branch_addr;
/* address of next instruction after branch */
uint32_t next_addr;
/* number of guest instructions in block */ /* number of guest instructions in block */
int num_instrs; int num_instrs;