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,
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue