mirror of https://github.com/inolen/redream.git
added branch type info to blocks
This commit is contained in:
parent
1df4e5d3a4
commit
bd97aa9603
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue