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,
struct jit_block *block) {
uint32_t addr = block->guest_addr;
uint32_t offset = 0;
block->guest_size = 0;
block->num_cycles = 0;
block->num_instrs = 0;
while (1) {
uint32_t addr = block->guest_addr + offset;
uint32_t data = guest->r16(guest->space, addr);
union sh4_instr instr = {data};
struct jit_opdef *def = sh4_get_opdef(data);
addr += 2;
offset += 2;
block->guest_size += 2;
block->num_cycles += def->cycles;
block->num_instrs++;
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);
addr += 2;
offset += 2;
block->guest_size += 2;
block->num_cycles += delay_def->cycles;
block->num_instrs++;
@ -50,11 +52,65 @@ static void sh4_analyze_block(const struct sh4_guest *guest,
CHECK(!(delay_def->flags & SH4_FLAG_DELAYED));
}
/* stop emitting once a branch has been hit. in addition, 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_PC | SH4_FLAG_SET_FPSCR | SH4_FLAG_SET_SR)) {
/* stop emitting once a branch is hit and save off branch information */
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_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;
}
}

View File

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

View File

@ -135,7 +135,6 @@ SH4_INSTR(RTS, "rts", 0000000000001011, 2, SH4_FL
// system control instructions
SH4_INSTR(LDTLB, "ldtlb", 0000000000111000, 1, 0)
SH4_INSTR(CLRMAC, "clrmac", 0000000000101000, 1, 0)
SH4_INSTR(CLRS, "clrs", 0000000001001000, 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(LDSMMACL, "lds.l @rn+, macl", 0100mmmm00010110, 1, 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(NOP, "nop", 0000000000001001, 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 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 {
/* address of source block in guest memory */
uint32_t guest_addr;
@ -29,6 +38,13 @@ struct jit_block {
/* compile with fastmem support */
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 */
int num_instrs;