mirror of https://github.com/inolen/redream.git
sanitize host addresses to a valid value when loading IR into recc
This commit is contained in:
parent
dd12368992
commit
37b9f52b6c
|
@ -160,12 +160,12 @@ static void arm7_translate(void *data, uint32_t addr, struct ir *ir,
|
|||
struct ir_value *remaining_cycles = ir_load_context(
|
||||
ir, offsetof(struct armv3_context, remaining_cycles), VALUE_I32);
|
||||
struct ir_value *done = ir_cmp_sle(ir, remaining_cycles, ir_alloc_i32(ir, 0));
|
||||
ir_branch_true(ir, done, ir_alloc_ptr(ir, arm7_dispatch_leave));
|
||||
ir_branch_true(ir, ir_alloc_ptr(ir, arm7_dispatch_leave), done);
|
||||
|
||||
/* interrupt check */
|
||||
struct ir_value *pending_intr = ir_load_context(
|
||||
ir, offsetof(struct armv3_context, pending_interrupts), VALUE_I32);
|
||||
ir_branch_true(ir, pending_intr, ir_alloc_ptr(ir, arm7_dispatch_interrupt));
|
||||
ir_branch_true(ir, ir_alloc_ptr(ir, arm7_dispatch_interrupt), pending_intr);
|
||||
|
||||
/* update remaining cycles */
|
||||
int cycles = (size / 4);
|
||||
|
|
|
@ -124,12 +124,12 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
|
|||
struct ir_value *remaining_cycles = ir_load_context(
|
||||
ir, offsetof(struct sh4_ctx, remaining_cycles), VALUE_I32);
|
||||
struct ir_value *done = ir_cmp_sle(ir, remaining_cycles, ir_alloc_i32(ir, 0));
|
||||
ir_branch_true(ir, done, ir_alloc_ptr(ir, sh4_dispatch_leave));
|
||||
ir_branch_true(ir, ir_alloc_ptr(ir, sh4_dispatch_leave), done);
|
||||
|
||||
/* handle pending interrupts */
|
||||
struct ir_value *pending_intr = ir_load_context(
|
||||
ir, offsetof(struct sh4_ctx, pending_interrupts), VALUE_I64);
|
||||
ir_branch_true(ir, pending_intr, ir_alloc_ptr(ir, sh4_dispatch_interrupt));
|
||||
ir_branch_true(ir, ir_alloc_ptr(ir, sh4_dispatch_interrupt), pending_intr);
|
||||
|
||||
/* update remaining cycles */
|
||||
remaining_cycles = ir_sub(ir, remaining_cycles, ir_alloc_i32(ir, as.cycles));
|
||||
|
|
|
@ -1556,31 +1556,31 @@ EMITTER(BRANCH) {
|
|||
}
|
||||
|
||||
EMITTER(BRANCH_FALSE) {
|
||||
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[0]);
|
||||
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[1]);
|
||||
|
||||
e.test(cond, cond);
|
||||
|
||||
if (instr->arg[1]->type == VALUE_LABEL) {
|
||||
if (instr->arg[0]->type == VALUE_LABEL) {
|
||||
char name[128];
|
||||
x64_backend_label_name(name, sizeof(name), instr->arg[1]);
|
||||
x64_backend_label_name(name, sizeof(name), instr->arg[0]);
|
||||
e.jz(name);
|
||||
} else {
|
||||
void *dst = (void *)instr->arg[1]->i64;
|
||||
void *dst = (void *)instr->arg[0]->i64;
|
||||
e.jz(dst);
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(BRANCH_TRUE) {
|
||||
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[0]);
|
||||
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[1]);
|
||||
|
||||
e.test(cond, cond);
|
||||
|
||||
if (instr->arg[1]->type == VALUE_LABEL) {
|
||||
if (instr->arg[0]->type == VALUE_LABEL) {
|
||||
char name[128];
|
||||
x64_backend_label_name(name, sizeof(name), instr->arg[1]);
|
||||
x64_backend_label_name(name, sizeof(name), instr->arg[0]);
|
||||
e.jnz(name);
|
||||
} else {
|
||||
void *dst = (void *)instr->arg[1]->i64;
|
||||
void *dst = (void *)instr->arg[0]->i64;
|
||||
e.jnz(dst);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,8 @@ static emit_cb emit_callbacks[NUM_SH4_OPS] = {
|
|||
#define load_pr() ir_load_pr(ir)
|
||||
#define store_pr(v) ir_store_pr(ir, v)
|
||||
#define branch(addr) ir_branch_guest(frontend, ir, addr)
|
||||
#define branch_false(cond, addr) ir_branch_false_guest(frontend, ir, cond, addr)
|
||||
#define branch_true(cond, addr) ir_branch_true_guest(frontend, ir, cond, addr)
|
||||
#define branch_false(addr, cond) ir_branch_false_guest(frontend, ir, addr, cond)
|
||||
#define branch_true(addr, cond) ir_branch_true_guest(frontend, ir, addr, cond)
|
||||
|
||||
static struct ir_value *ir_load_guest(struct ir *ir, int flags,
|
||||
struct ir_value *addr,
|
||||
|
@ -198,18 +198,18 @@ static void ir_branch_guest(struct sh4_frontend *frontend, struct ir *ir,
|
|||
}
|
||||
|
||||
static void ir_branch_false_guest(struct sh4_frontend *frontend, struct ir *ir,
|
||||
struct ir_value *cond,
|
||||
struct ir_value *addr) {
|
||||
struct ir_value *addr,
|
||||
struct ir_value *cond) {
|
||||
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", addr);
|
||||
ir_branch_true(ir, cond, skip);
|
||||
ir_branch_true(ir, skip, cond);
|
||||
ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr);
|
||||
ir_label(ir, skip);
|
||||
}
|
||||
|
||||
static void ir_branch_true_guest(struct sh4_frontend *frontend, struct ir *ir,
|
||||
struct ir_value *cond, struct ir_value *addr) {
|
||||
struct ir_value *addr, struct ir_value *cond) {
|
||||
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", addr);
|
||||
ir_branch_false(ir, cond, skip);
|
||||
ir_branch_false(ir, skip, cond);
|
||||
ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr);
|
||||
ir_label(ir, skip);
|
||||
}
|
||||
|
@ -1203,7 +1203,7 @@ EMITTER(SHLR16) {
|
|||
EMITTER(BF) {
|
||||
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
|
||||
struct ir_value *cond = load_t();
|
||||
branch_false(cond, ir_alloc_i32(ir, dest_addr));
|
||||
branch_false(ir_alloc_i32(ir, dest_addr), cond);
|
||||
}
|
||||
|
||||
// code cycles t-bit
|
||||
|
@ -1213,7 +1213,7 @@ EMITTER(BFS) {
|
|||
struct ir_value *cond = load_t();
|
||||
emit_delay_instr();
|
||||
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
|
||||
branch_false(cond, ir_alloc_i32(ir, dest_addr));
|
||||
branch_false(ir_alloc_i32(ir, dest_addr), cond);
|
||||
}
|
||||
|
||||
// code cycles t-bit
|
||||
|
@ -1222,7 +1222,7 @@ EMITTER(BFS) {
|
|||
EMITTER(BT) {
|
||||
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
|
||||
struct ir_value *cond = load_t();
|
||||
branch_true(cond, ir_alloc_i32(ir, dest_addr));
|
||||
branch_true(ir_alloc_i32(ir, dest_addr), cond);
|
||||
}
|
||||
|
||||
// code cycles t-bit
|
||||
|
@ -1232,7 +1232,7 @@ EMITTER(BTS) {
|
|||
struct ir_value *cond = load_t();
|
||||
emit_delay_instr();
|
||||
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
|
||||
branch_true(cond, ir_alloc_i32(ir, dest_addr));
|
||||
branch_true(ir_alloc_i32(ir, dest_addr), cond);
|
||||
}
|
||||
|
||||
// code cycles t-bit
|
||||
|
@ -1504,7 +1504,7 @@ EMITTER(PREF) {
|
|||
struct ir_value *cond = ir_lshr(ir, addr, ir_alloc_i32(ir, 26));
|
||||
cond = ir_cmp_ne(ir, cond, ir_alloc_i32(ir, 0x38));
|
||||
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", cond);
|
||||
ir_branch_true(ir, cond, skip);
|
||||
ir_branch_true(ir, skip, cond);
|
||||
|
||||
struct ir_value *data = ir_alloc_ptr(ir, frontend->data);
|
||||
struct ir_value *sq_prefetch = ir_alloc_ptr(ir, frontend->sq_prefetch);
|
||||
|
|
|
@ -778,22 +778,22 @@ void ir_branch(struct ir *ir, struct ir_value *dst) {
|
|||
ir_set_arg0(ir, instr, dst);
|
||||
}
|
||||
|
||||
void ir_branch_false(struct ir *ir, struct ir_value *cond,
|
||||
struct ir_value *dst) {
|
||||
void ir_branch_false(struct ir *ir, struct ir_value *dst,
|
||||
struct ir_value *cond) {
|
||||
CHECK(dst->type == VALUE_LABEL || dst->type == VALUE_I64);
|
||||
|
||||
struct ir_instr *instr = ir_append_instr(ir, OP_BRANCH_FALSE, VALUE_V);
|
||||
ir_set_arg0(ir, instr, cond);
|
||||
ir_set_arg1(ir, instr, dst);
|
||||
ir_set_arg0(ir, instr, dst);
|
||||
ir_set_arg1(ir, instr, cond);
|
||||
}
|
||||
|
||||
void ir_branch_true(struct ir *ir, struct ir_value *cond,
|
||||
struct ir_value *dst) {
|
||||
void ir_branch_true(struct ir *ir, struct ir_value *dst,
|
||||
struct ir_value *cond) {
|
||||
CHECK(dst->type == VALUE_LABEL || dst->type == VALUE_I64);
|
||||
|
||||
struct ir_instr *instr = ir_append_instr(ir, OP_BRANCH_TRUE, VALUE_V);
|
||||
ir_set_arg0(ir, instr, cond);
|
||||
ir_set_arg1(ir, instr, dst);
|
||||
ir_set_arg0(ir, instr, dst);
|
||||
ir_set_arg1(ir, instr, cond);
|
||||
}
|
||||
|
||||
void ir_call(struct ir *ir, struct ir_value *fn) {
|
||||
|
|
|
@ -328,9 +328,9 @@ struct ir_value *ir_lshd(struct ir *ir, struct ir_value *a, struct ir_value *n);
|
|||
/* branches */
|
||||
void ir_label(struct ir *ir, struct ir_value *lbl);
|
||||
void ir_branch(struct ir *ir, struct ir_value *dst);
|
||||
void ir_branch_false(struct ir *ir, struct ir_value *cond,
|
||||
struct ir_value *dst);
|
||||
void ir_branch_true(struct ir *ir, struct ir_value *cond, struct ir_value *dst);
|
||||
void ir_branch_false(struct ir *ir, struct ir_value *dst,
|
||||
struct ir_value *cond);
|
||||
void ir_branch_true(struct ir *ir, struct ir_value *dst, struct ir_value *cond);
|
||||
|
||||
/* calls */
|
||||
void ir_call(struct ir *ir, struct ir_value *fn);
|
||||
|
|
|
@ -39,6 +39,21 @@ static int get_num_instrs(const struct ir *ir) {
|
|||
return n;
|
||||
}
|
||||
|
||||
static void sanitize_ir(struct ir *ir) {
|
||||
list_for_each_entry(instr, &ir->instrs, struct ir_instr, it) {
|
||||
if (instr->op != OP_BRANCH && instr->op != OP_BRANCH_FALSE &&
|
||||
instr->op != OP_BRANCH_TRUE && instr->op != OP_CALL &&
|
||||
instr->op != OP_CALL_FALLBACK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ensure that address are within 2 GB of the code buffer */
|
||||
uint64_t addr = instr->arg[0]->i64;
|
||||
addr = (uint64_t)code | (addr & 0x7fffffff);
|
||||
ir_set_arg0(ir, instr, ir_alloc_i64(ir, addr));
|
||||
}
|
||||
}
|
||||
|
||||
static void process_file(struct jit *jit, const char *filename,
|
||||
int disable_dumps) {
|
||||
struct ir ir = {0};
|
||||
|
@ -52,6 +67,9 @@ static void process_file(struct jit *jit, const char *filename,
|
|||
fclose(input);
|
||||
CHECK(r);
|
||||
|
||||
/* sanitize absolute addresses in the ir */
|
||||
sanitize_ir(&ir);
|
||||
|
||||
/* calculate number of guest instructions */
|
||||
int guest_num_instrs = 0;
|
||||
list_for_each_entry(instr, &ir.instrs, struct ir_instr, it) {
|
||||
|
@ -164,10 +182,21 @@ int main(int argc, char **argv) {
|
|||
|
||||
const char *path = argv[1];
|
||||
|
||||
/* initailize jit, stubbing out guest interfaces that are used during
|
||||
assembly to a valid address */
|
||||
struct jit *jit = jit_create("recc");
|
||||
|
||||
struct jit_guest guest = {0};
|
||||
guest.r8 = (void *)code;
|
||||
guest.r16 = (void *)code;
|
||||
guest.r32 = (void *)code;
|
||||
guest.w8 = (void *)code;
|
||||
guest.w16 = (void *)code;
|
||||
guest.w32 = (void *)code;
|
||||
|
||||
struct jit_backend *backend =
|
||||
x64_backend_create(jit, code, code_size, stack_size);
|
||||
|
||||
CHECK(jit_init(jit, &guest, NULL, backend));
|
||||
|
||||
if (fs_isfile(path)) {
|
||||
|
|
Loading…
Reference in New Issue