move guest functionality outside of frontend struct

This commit is contained in:
Anthony Pesch 2017-05-13 22:43:24 -04:00
parent eb2e1b6bcd
commit 47a47d15dc
17 changed files with 208 additions and 174 deletions

View File

@ -10,6 +10,7 @@
#include "jit/frontend/armv3/armv3_context.h" #include "jit/frontend/armv3/armv3_context.h"
#include "jit/frontend/armv3/armv3_disasm.h" #include "jit/frontend/armv3/armv3_disasm.h"
#include "jit/frontend/armv3/armv3_frontend.h" #include "jit/frontend/armv3/armv3_frontend.h"
#include "jit/frontend/armv3/armv3_guest.h"
#include "jit/frontend/armv3/armv3_translate.h" #include "jit/frontend/armv3/armv3_translate.h"
#include "jit/ir/ir.h" #include "jit/ir/ir.h"
#include "jit/jit.h" #include "jit/jit.h"
@ -24,7 +25,7 @@ struct arm7 {
/* jit */ /* jit */
struct jit *jit; struct jit *jit;
struct jit_guest guest; struct armv3_guest *guest;
struct armv3_frontend *frontend; struct armv3_frontend *frontend;
struct x64_backend *backend; struct x64_backend *backend;
@ -153,7 +154,7 @@ static void arm7_translate(void *data, uint32_t addr, struct ir *ir, int flags,
struct arm7 *arm = data; struct arm7 *arm = data;
int size; int size;
armv3_analyze_block(arm->jit, addr, &flags, &size); armv3_analyze_block(arm->guest, addr, &flags, &size);
/* cycle check */ /* cycle check */
struct ir_value *remaining_cycles = ir_load_context( struct ir_value *remaining_cycles = ir_load_context(
@ -217,34 +218,31 @@ static int arm7_init(struct device *dev) {
{ arm7_dispatch_init(arm, arm->jit, &arm->ctx, arm->memory_if->space->base); } { arm7_dispatch_init(arm, arm->jit, &arm->ctx, arm->memory_if->space->base); }
{ {
arm->guest.ctx = &arm->ctx; arm->guest = armv3_guest_create();
arm->guest.mem = arm->memory_if->space->base; arm->guest->data = arm;
arm->guest.space = arm->memory_if->space; arm->guest->switch_mode = &arm7_switch_mode;
arm->guest.lookup_code = &arm7_dispatch_lookup_code; arm->guest->restore_mode = &arm7_restore_mode;
arm->guest.cache_code = &arm7_dispatch_cache_code; arm->guest->software_interrupt = &arm7_software_interrupt;
arm->guest.invalidate_code = &arm7_dispatch_invalidate_code; arm->guest->ctx = &arm->ctx;
arm->guest.patch_edge = &arm7_dispatch_patch_edge; arm->guest->mem = arm->memory_if->space->base;
arm->guest.restore_edge = &arm7_dispatch_restore_edge; arm->guest->space = arm->memory_if->space;
arm->guest.r8 = &as_read8; arm->guest->lookup_code = &arm7_dispatch_lookup_code;
arm->guest.r16 = &as_read16; arm->guest->cache_code = &arm7_dispatch_cache_code;
arm->guest.r32 = &as_read32; arm->guest->invalidate_code = &arm7_dispatch_invalidate_code;
arm->guest.w8 = &as_write8; arm->guest->patch_edge = &arm7_dispatch_patch_edge;
arm->guest.w16 = &as_write16; arm->guest->restore_edge = &arm7_dispatch_restore_edge;
arm->guest.w32 = &as_write32; arm->guest->r8 = &as_read8;
arm->guest->r16 = &as_read16;
arm->guest->r32 = &as_read32;
arm->guest->w8 = &as_write8;
arm->guest->w16 = &as_write16;
arm->guest->w32 = &as_write32;
} }
{ {
arm->frontend = armv3_frontend_create(arm->jit); arm->frontend = armv3_frontend_create(arm->jit);
if (!arm->frontend) {
return 0;
}
arm->frontend->data = arm; arm->frontend->data = arm;
arm->frontend->translate = &arm7_translate; arm->frontend->translate = &arm7_translate;
arm->frontend->switch_mode = &arm7_switch_mode;
arm->frontend->restore_mode = &arm7_restore_mode;
arm->frontend->software_interrupt = &arm7_software_interrupt;
} }
{ {
@ -252,7 +250,7 @@ static int arm7_init(struct device *dev) {
arm7_stack_size); arm7_stack_size);
} }
if (!jit_init(arm->jit, &arm->guest, (struct jit_frontend *)arm->frontend, if (!jit_init(arm->jit, (struct jit_guest *)arm->guest, (struct jit_frontend *)arm->frontend,
(struct jit_backend *)arm->backend)) { (struct jit_backend *)arm->backend)) {
return 0; return 0;
} }
@ -263,17 +261,10 @@ static int arm7_init(struct device *dev) {
} }
void arm7_destroy(struct arm7 *arm) { void arm7_destroy(struct arm7 *arm) {
if (arm->jit) { jit_destroy(arm->jit);
jit_destroy(arm->jit); armv3_frontend_destroy(arm->frontend);
} x64_backend_destroy(arm->backend);
armv3_guest_destroy(arm->guest);
if (arm->backend) {
x64_backend_destroy(arm->backend);
}
if (arm->frontend) {
armv3_frontend_destroy(arm->frontend);
}
dc_destroy_memory_interface(arm->memory_if); dc_destroy_memory_interface(arm->memory_if);
dc_destroy_execute_interface(arm->execute_if); dc_destroy_execute_interface(arm->execute_if);

View File

@ -16,6 +16,7 @@
#include "jit/frontend/sh4/sh4_analyze.h" #include "jit/frontend/sh4/sh4_analyze.h"
#include "jit/frontend/sh4/sh4_disasm.h" #include "jit/frontend/sh4/sh4_disasm.h"
#include "jit/frontend/sh4/sh4_frontend.h" #include "jit/frontend/sh4/sh4_frontend.h"
#include "jit/frontend/sh4/sh4_guest.h"
#include "jit/frontend/sh4/sh4_translate.h" #include "jit/frontend/sh4/sh4_translate.h"
#include "jit/ir/ir.h" #include "jit/ir/ir.h"
#include "jit/jit.h" #include "jit/jit.h"
@ -77,7 +78,7 @@ void sh4_fpscr_updated(void *data, uint32_t old_fpscr) {
struct sh4 *sh4 = data; struct sh4 *sh4 = data;
struct sh4_ctx *ctx = &sh4->ctx; struct sh4_ctx *ctx = &sh4->ctx;
if ((ctx->fpscr & FR) != (old_fpscr & FR)) { if ((ctx->fpscr & FR_MASK) != (old_fpscr & FR_MASK)) {
sh4_swap_fpr_bank(sh4); sh4_swap_fpr_bank(sh4);
} }
} }
@ -113,10 +114,10 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
if (fastmem) { if (fastmem) {
as.flags |= SH4_FASTMEM; as.flags |= SH4_FASTMEM;
} }
if (sh4->ctx.fpscr & PR) { if (sh4->ctx.fpscr & PR_MASK) {
as.flags |= SH4_DOUBLE_PR; as.flags |= SH4_DOUBLE_PR;
} }
if (sh4->ctx.fpscr & SZ) { if (sh4->ctx.fpscr & SZ_MASK) {
as.flags |= SH4_DOUBLE_SZ; as.flags |= SH4_DOUBLE_SZ;
} }
sh4_analyze_block(sh4->jit, &as); sh4_analyze_block(sh4->jit, &as);
@ -165,7 +166,7 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
i += 2; i += 2;
} }
sh4_emit_instr(sh4->frontend, ir, as.flags, &instr, &delay_instr); sh4_emit_instr(sh4->guest, ir, as.flags, &instr, &delay_instr);
} }
/* if the block terminates before a branch, fallthrough to the next pc */ /* if the block terminates before a branch, fallthrough to the next pc */
@ -191,7 +192,8 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
continue; continue;
} }
int direct = ir_is_constant(instr->arg[1]); int direct =
instr->op == OP_STORE_CONTEXT && ir_is_constant(instr->arg[1]);
/* insert dispatch call immediately after pc store */ /* insert dispatch call immediately after pc store */
ir_set_current_instr(ir, instr); ir_set_current_instr(ir, instr);
@ -205,16 +207,6 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
} }
} }
void sh4_implode_sr(struct sh4 *sh4) {
sh4->ctx.sr &= ~(S_MASK | T_MASK);
sh4->ctx.sr |= (sh4->ctx.sr_s << S_BIT) | (sh4->ctx.sr_t << T_BIT);
}
void sh4_explode_sr(struct sh4 *sh4) {
sh4->ctx.sr_t = (sh4->ctx.sr & T_MASK) >> T_BIT;
sh4->ctx.sr_s = (sh4->ctx.sr & S_MASK) >> S_BIT;
}
void sh4_clear_interrupt(struct sh4 *sh4, enum sh4_interrupt intr) { void sh4_clear_interrupt(struct sh4 *sh4, enum sh4_interrupt intr) {
sh4->requested_interrupts &= ~sh4->sort_id[intr]; sh4->requested_interrupts &= ~sh4->sort_id[intr];
sh4_intc_update_pending(sh4); sh4_intc_update_pending(sh4);
@ -302,47 +294,41 @@ static int sh4_init(struct device *dev) {
{ sh4_dispatch_init(sh4, sh4->jit, &sh4->ctx, sh4->memory_if->space->base); } { sh4_dispatch_init(sh4, sh4->jit, &sh4->ctx, sh4->memory_if->space->base); }
{ {
sh4->guest.ctx = &sh4->ctx; sh4->guest = sh4_guest_create();
sh4->guest.mem = sh4->memory_if->space->base; sh4->guest->data = sh4;
sh4->guest.space = sh4->memory_if->space; sh4->guest->invalid_instr = &sh4_invalid_instr;
sh4->guest.lookup_code = &sh4_dispatch_lookup_code; sh4->guest->sq_prefetch = &sh4_ccn_sq_prefetch;
sh4->guest.cache_code = &sh4_dispatch_cache_code; sh4->guest->sr_updated = &sh4_sr_updated;
sh4->guest.invalidate_code = &sh4_dispatch_invalidate_code; sh4->guest->fpscr_updated = &sh4_fpscr_updated;
sh4->guest.patch_edge = &sh4_dispatch_patch_edge; sh4->guest->ctx = &sh4->ctx;
sh4->guest.restore_edge = &sh4_dispatch_restore_edge; sh4->guest->mem = sh4->memory_if->space->base;
sh4->guest.r8 = &as_read8; sh4->guest->space = sh4->memory_if->space;
sh4->guest.r16 = &as_read16; sh4->guest->lookup_code = &sh4_dispatch_lookup_code;
sh4->guest.r32 = &as_read32; sh4->guest->cache_code = &sh4_dispatch_cache_code;
sh4->guest.w8 = &as_write8; sh4->guest->invalidate_code = &sh4_dispatch_invalidate_code;
sh4->guest.w16 = &as_write16; sh4->guest->patch_edge = &sh4_dispatch_patch_edge;
sh4->guest.w32 = &as_write32; sh4->guest->restore_edge = &sh4_dispatch_restore_edge;
sh4->guest->r8 = &as_read8;
sh4->guest->r16 = &as_read16;
sh4->guest->r32 = &as_read32;
sh4->guest->w8 = &as_write8;
sh4->guest->w16 = &as_write16;
sh4->guest->w32 = &as_write32;
} }
{ {
sh4->frontend = sh4_frontend_create(sh4->jit); sh4->frontend = sh4_frontend_create(sh4->jit);
if (!sh4->frontend) {
return 0;
}
sh4->frontend->data = sh4; sh4->frontend->data = sh4;
sh4->frontend->translate = &sh4_translate; sh4->frontend->translate = &sh4_translate;
sh4->frontend->invalid_instr = &sh4_invalid_instr;
sh4->frontend->sq_prefetch = &sh4_ccn_sq_prefetch;
sh4->frontend->sr_updated = &sh4_sr_updated;
sh4->frontend->fpscr_updated = &sh4_fpscr_updated;
} }
{ {
sh4->backend = sh4->backend =
x64_backend_create(sh4->jit, sh4_code, sh4_code_size, sh4_stack_size); x64_backend_create(sh4->jit, sh4_code, sh4_code_size, sh4_stack_size);
if (!sh4->backend) {
return 0;
}
} }
if (!jit_init(sh4->jit, &sh4->guest, (struct jit_frontend *)sh4->frontend, if (!jit_init(sh4->jit, (struct jit_guest *)sh4->guest,
(struct jit_frontend *)sh4->frontend,
(struct jit_backend *)sh4->backend)) { (struct jit_backend *)sh4->backend)) {
return 0; return 0;
} }
@ -351,17 +337,10 @@ static int sh4_init(struct device *dev) {
} }
void sh4_destroy(struct sh4 *sh4) { void sh4_destroy(struct sh4 *sh4) {
if (sh4->jit) { jit_destroy(sh4->jit);
jit_destroy(sh4->jit); sh4_frontend_destroy(sh4->frontend);
} x64_backend_destroy(sh4->backend);
sh4_guest_destroy(sh4->guest);
if (sh4->backend) {
x64_backend_destroy(sh4->backend);
}
if (sh4->frontend) {
sh4_frontend_destroy(sh4->frontend);
}
dc_destroy_memory_interface(sh4->memory_if); dc_destroy_memory_interface(sh4->memory_if);
dc_destroy_execute_interface(sh4->execute_if); dc_destroy_execute_interface(sh4->execute_if);

View File

@ -10,8 +10,8 @@
struct dreamcast; struct dreamcast;
struct jit; struct jit;
struct jit_guest;
struct sh4_frontend; struct sh4_frontend;
struct sh4_guest;
struct x64_backend; struct x64_backend;
#define SH4_CLOCK_FREQ INT64_C(200000000) #define SH4_CLOCK_FREQ INT64_C(200000000)
@ -47,7 +47,7 @@ struct sh4 {
/* jit */ /* jit */
struct jit *jit; struct jit *jit;
struct jit_guest guest; struct sh4_guest *guest;
struct sh4_frontend *frontend; struct sh4_frontend *frontend;
struct x64_backend *backend; struct x64_backend *backend;
@ -87,8 +87,6 @@ void sh4_destroy(struct sh4 *sh);
void sh4_reset(struct sh4 *sh4, uint32_t pc); void sh4_reset(struct sh4 *sh4, uint32_t pc);
void sh4_raise_interrupt(struct sh4 *sh, enum sh4_interrupt intr); void sh4_raise_interrupt(struct sh4 *sh, enum sh4_interrupt intr);
void sh4_clear_interrupt(struct sh4 *sh, enum sh4_interrupt intr); void sh4_clear_interrupt(struct sh4 *sh, enum sh4_interrupt intr);
void sh4_explode_sr(struct sh4 *sh4);
void sh4_implode_sr(struct sh4 *sh4);
void sh4_sr_updated(void *data, uint32_t old_sr); void sh4_sr_updated(void *data, uint32_t old_sr);
void sh4_fpscr_updated(void *data, uint32_t old_fpscr); void sh4_fpscr_updated(void *data, uint32_t old_fpscr);

View File

@ -29,7 +29,7 @@ int sh4_intc_check_pending(struct sh4 *sh4) {
struct sh4_interrupt_info *int_info = &sh4_interrupts[intr]; struct sh4_interrupt_info *int_info = &sh4_interrupts[intr];
/* ensure sr is up to date */ /* ensure sr is up to date */
sh4_implode_sr(sh4); sh4_implode_sr(&sh4->ctx);
*sh4->INTEVT = int_info->intevt; *sh4->INTEVT = int_info->intevt;
sh4->ctx.ssr = sh4->ctx.sr; sh4->ctx.ssr = sh4->ctx.sr;

View File

@ -655,11 +655,12 @@ static void x64_backend_reset(struct jit_backend *base) {
} }
EMITTER(FALLBACK) { EMITTER(FALLBACK) {
struct jit_guest *guest = backend->base.jit->guest;
void *fallback = (void *)instr->arg[0]->i64; void *fallback = (void *)instr->arg[0]->i64;
uint32_t addr = instr->arg[1]->i32; uint32_t addr = instr->arg[1]->i32;
uint32_t raw_instr = instr->arg[2]->i32; uint32_t raw_instr = instr->arg[2]->i32;
e.mov(arg0, reinterpret_cast<uint64_t>(backend->base.jit)); e.mov(arg0, (uint64_t)guest);
e.mov(arg1, addr); e.mov(arg1, addr);
e.mov(arg2, raw_instr); e.mov(arg2, raw_instr);
e.call(fallback); e.call(fallback);

View File

@ -3,11 +3,10 @@
#include "core/log.h" #include "core/log.h"
#include "jit/frontend/armv3/armv3_disasm.h" #include "jit/frontend/armv3/armv3_disasm.h"
#include "jit/frontend/armv3/armv3_frontend.h" #include "jit/frontend/armv3/armv3_frontend.h"
#include "jit/frontend/armv3/armv3_guest.h"
void armv3_analyze_block(const struct jit *jit, uint32_t addr, int *flags, void armv3_analyze_block(const struct armv3_guest *guest, uint32_t addr, int *flags,
int *size) { int *size) {
const struct jit_guest *guest = jit->guest;
*size = 0; *size = 0;
while (1) { while (1) {

View File

@ -3,9 +3,9 @@
#include <stdint.h> #include <stdint.h>
struct jit; struct armv3_guest;
void armv3_analyze_block(const struct jit *jit, uint32_t addr, int *flags, void armv3_analyze_block(const struct armv3_guest *guest, uint32_t addr, int *flags,
int *size); int *size);
#endif #endif

View File

@ -4,11 +4,11 @@
#include "core/math.h" #include "core/math.h"
#include "jit/frontend/armv3/armv3_context.h" #include "jit/frontend/armv3/armv3_context.h"
#include "jit/frontend/armv3/armv3_disasm.h" #include "jit/frontend/armv3/armv3_disasm.h"
#include "jit/frontend/armv3/armv3_frontend.h" #include "jit/frontend/armv3/armv3_guest.h"
/* forward declare each fallback */ /* forward declare each fallback */
#define ARMV3_INSTR(name, desc, sig, cycles, flags) \ #define ARMV3_INSTR(name, desc, sig, cycles, flags) \
static void armv3_fallback_##name(struct jit *jit, uint32_t addr, \ static void armv3_fallback_##name(struct armv3_guest *guest, uint32_t addr, \
union armv3_instr i); union armv3_instr i);
#include "armv3_instr.inc" #include "armv3_instr.inc"
#undef ARMV3_INSTR #undef ARMV3_INSTR
@ -22,11 +22,11 @@ void *fallbacks[NUM_ARMV3_OPS] = {
}; };
/* helper functions / macros for writing fallbacks */ /* helper functions / macros for writing fallbacks */
#define FALLBACK(op) \ #define FALLBACK(op) \
void armv3_fallback_##op(struct jit *jit, uint32_t addr, union armv3_instr i) void armv3_fallback_##op(struct armv3_guest *guest, uint32_t addr, \
union armv3_instr i)
#define CTX ((struct armv3_context *)jit->guest->ctx) #define CTX ((struct armv3_context *)guest->ctx)
#define FRONTEND ((struct armv3_frontend *)jit->frontend)
#define REG(n) (CTX->r[n]) #define REG(n) (CTX->r[n])
#define MODE() (CTX->r[CPSR] & M_MASK) #define MODE() (CTX->r[CPSR] & M_MASK)
@ -235,7 +235,7 @@ FALLBACK(BL) {
if (i.data.s) { \ if (i.data.s) { \
armv3_fallback_update_flags_logical(CTX, res, carry); \ armv3_fallback_update_flags_logical(CTX, res, carry); \
if (i.data.rd == 15) { \ if (i.data.rd == 15) { \
FRONTEND->restore_mode(FRONTEND->data); \ guest->restore_mode(guest->data); \
} \ } \
} }
@ -243,7 +243,7 @@ FALLBACK(BL) {
if (i.data.s) { \ if (i.data.s) { \
armv3_fallback_update_flags_sub(CTX, lhs, rhs, res); \ armv3_fallback_update_flags_sub(CTX, lhs, rhs, res); \
if (i.data.rd == 15) { \ if (i.data.rd == 15) { \
FRONTEND->restore_mode(FRONTEND->data); \ guest->restore_mode(guest->data); \
} \ } \
} }
@ -251,7 +251,7 @@ FALLBACK(BL) {
if (i.data.s) { \ if (i.data.s) { \
armv3_fallback_update_flags_add(CTX, lhs, rhs, res); \ armv3_fallback_update_flags_add(CTX, lhs, rhs, res); \
if (i.data.rd == 15) { \ if (i.data.rd == 15) { \
FRONTEND->restore_mode(FRONTEND->data); \ guest->restore_mode(guest->data); \
} \ } \
} }
@ -555,7 +555,7 @@ FALLBACK(MSR) {
newsr = (newsr & 0xf0000000) | (oldsr & 0x0fffffff); newsr = (newsr & 0xf0000000) | (oldsr & 0x0fffffff);
} }
FRONTEND->switch_mode(FRONTEND->data, newsr); guest->switch_mode(guest->data, newsr);
} }
REG(15) = addr + 4; REG(15) = addr + 4;
@ -607,10 +607,8 @@ FALLBACK(MLA) {
/* /*
* single data transfer * single data transfer
*/ */
static inline void armv3_fallback_memop(struct jit *jit, uint32_t addr, static inline void armv3_fallback_memop(struct armv3_guest *guest,
union armv3_instr i) { uint32_t addr, union armv3_instr i) {
struct jit_guest *guest = jit->guest;
CHECK_COND(); CHECK_COND();
/* parse offset */ /* parse offset */
@ -660,19 +658,17 @@ static inline void armv3_fallback_memop(struct jit *jit, uint32_t addr,
} }
FALLBACK(LDR) { FALLBACK(LDR) {
armv3_fallback_memop(jit, addr, i); armv3_fallback_memop(guest, addr, i);
} }
FALLBACK(STR) { FALLBACK(STR) {
armv3_fallback_memop(jit, addr, i); armv3_fallback_memop(guest, addr, i);
} }
/* /*
* block data transfer * block data transfer
*/ */
FALLBACK(LDM) { FALLBACK(LDM) {
struct jit_guest *guest = jit->guest;
CHECK_COND(); CHECK_COND();
uint32_t base = LOAD_RN(i.blk.rn); uint32_t base = LOAD_RN(i.blk.rn);
@ -716,13 +712,11 @@ FALLBACK(LDM) {
if ((i.blk.rlist & 0x8000) && i.blk.s) { if ((i.blk.rlist & 0x8000) && i.blk.s) {
/* move SPSR into CPSR */ /* move SPSR into CPSR */
FRONTEND->restore_mode(FRONTEND->data); guest->restore_mode(guest->data);
} }
} }
FALLBACK(STM) { FALLBACK(STM) {
struct jit_guest *guest = jit->guest;
CHECK_COND(); CHECK_COND();
uint32_t base = LOAD_RN(i.blk.rn); uint32_t base = LOAD_RN(i.blk.rn);
@ -778,8 +772,6 @@ FALLBACK(STM) {
* single data swap * single data swap
*/ */
FALLBACK(SWP) { FALLBACK(SWP) {
struct jit_guest *guest = jit->guest;
CHECK_COND(); CHECK_COND();
uint32_t ea = REG(i.swp.rn); uint32_t ea = REG(i.swp.rn);
@ -806,7 +798,7 @@ FALLBACK(SWI) {
CHECK_COND(); CHECK_COND();
REG(15) = addr + 4; REG(15) = addr + 4;
FRONTEND->software_interrupt(FRONTEND->data); guest->software_interrupt(guest->data);
} }
void *armv3_fallback(uint32_t instr) { void *armv3_fallback(uint32_t instr) {

View File

@ -2,7 +2,8 @@
#define ARMV3_FRONTEND_H #define ARMV3_FRONTEND_H
#include "jit/frontend/jit_frontend.h" #include "jit/frontend/jit_frontend.h"
#include "jit/jit.h"
struct jit;
enum armv3_block_flags { enum armv3_block_flags {
PC_SET = 0x1, PC_SET = 0x1,
@ -14,9 +15,6 @@ struct armv3_frontend {
/* runtime interface */ /* runtime interface */
void *data; void *data;
void (*translate)(void *, uint32_t, struct ir *, int, int *); void (*translate)(void *, uint32_t, struct ir *, int, int *);
void (*switch_mode)(void *, uint32_t);
void (*restore_mode)(void *);
void (*software_interrupt)(void *);
}; };
struct armv3_frontend *armv3_frontend_create(struct jit *jit); struct armv3_frontend *armv3_frontend_create(struct jit *jit);

View File

@ -0,0 +1,24 @@
#ifndef ARMV3_GUEST_H
#define ARMV3_GUEST_H
#include "jit/jit.h"
struct armv3_guest {
struct jit_guest;
/* runtime interface */
void *data;
void (*switch_mode)(void *, uint32_t);
void (*restore_mode)(void *);
void (*software_interrupt)(void *);
};
static inline struct armv3_guest *armv3_guest_create() {
return calloc(1, sizeof(struct armv3_guest));
}
static inline void armv3_guest_destroy(struct armv3_guest *guest) {
free(guest);
}
#endif

View File

@ -35,13 +35,21 @@
#define MD_MASK (1u << MD_BIT) #define MD_MASK (1u << MD_BIT)
/* FPSCR bits */ /* FPSCR bits */
enum {
RM = 0x00000003, /* denormalization mode */
DN = 0x00040000, #define DN_BIT 18
PR = 0x00080000, /* precision mode */
SZ = 0x00100000, #define PR_BIT 19
FR = 0x00200000 /* transfer size mode */
}; #define SZ_BIT 20
/* floating-point register bank */
#define FR_BIT 21
#define RM_MASK 0x3
#define DN_MASK (1u << DN_BIT)
#define PR_MASK (1u << PR_BIT)
#define SZ_MASK (1u << SZ_BIT)
#define FR_MASK (1u << FR_BIT)
struct sh4_ctx { struct sh4_ctx {
/* there are 24 32-bit general registers, r0_bank0-r7_bank0, r0_bank1-r7_bank1 /* there are 24 32-bit general registers, r0_bank0-r7_bank0, r0_bank1-r7_bank1
@ -90,4 +98,14 @@ struct sh4_ctx {
uint8_t cache[0x2000]; uint8_t cache[0x2000];
}; };
static inline void sh4_implode_sr(struct sh4_ctx *ctx) {
ctx->sr &= ~(S_MASK | T_MASK);
ctx->sr |= (ctx->sr_s << S_BIT) | (ctx->sr_t << T_BIT);
}
static inline void sh4_explode_sr(struct sh4_ctx *ctx) {
ctx->sr_t = (ctx->sr & T_MASK) >> T_BIT;
ctx->sr_s = (ctx->sr & S_MASK) >> S_BIT;
}
#endif #endif

View File

@ -7,6 +7,13 @@
#include "jit/ir/ir.h" #include "jit/ir/ir.h"
#include "jit/jit.h" #include "jit/jit.h"
/*
* fsca estimate lookup table, used by the jit and interpreter
*/
uint32_t sh4_fsca_table[0x20000] = {
#include "jit/frontend/sh4/sh4_fsca.inc"
};
static void sh4_frontend_translate_code(struct jit_frontend *base, static void sh4_frontend_translate_code(struct jit_frontend *base,
uint32_t addr, struct ir *ir, uint32_t addr, struct ir *ir,
int fastmem, int *size) { int fastmem, int *size) {

View File

@ -18,12 +18,10 @@ struct sh4_frontend {
/* runtime interface */ /* runtime interface */
void *data; void *data;
void (*translate)(void *, uint32_t, struct ir *, int, int *); void (*translate)(void *, uint32_t, struct ir *, int, int *);
void (*invalid_instr)(void *, uint32_t);
void (*sq_prefetch)(void *, uint32_t);
void (*sr_updated)(void *, uint32_t);
void (*fpscr_updated)(void *, uint32_t);
}; };
extern uint32_t sh4_fsca_table[];
struct sh4_frontend *sh4_frontend_create(struct jit *jit); struct sh4_frontend *sh4_frontend_create(struct jit *jit);
void sh4_frontend_destroy(struct sh4_frontend *frontend); void sh4_frontend_destroy(struct sh4_frontend *frontend);

View File

@ -0,0 +1,26 @@
#ifndef SH4_GUEST_H
#define SH4_GUEST_H
#include "jit/jit.h"
struct sh4_guest {
struct jit_guest;
/* runtime interface */
void *data;
void (*translate)(void *, uint32_t, struct ir *, int, int *);
void (*invalid_instr)(void *, uint32_t);
void (*sq_prefetch)(void *, uint32_t);
void (*sr_updated)(void *, uint32_t);
void (*fpscr_updated)(void *, uint32_t);
};
static inline struct sh4_guest *sh4_guest_create() {
return calloc(1, sizeof(struct sh4_guest));
}
static inline void sh4_guest_destroy(struct sh4_guest *guest) {
free(guest);
}
#endif

View File

@ -5,6 +5,7 @@
#include "jit/frontend/sh4/sh4_context.h" #include "jit/frontend/sh4/sh4_context.h"
#include "jit/frontend/sh4/sh4_disasm.h" #include "jit/frontend/sh4/sh4_disasm.h"
#include "jit/frontend/sh4/sh4_frontend.h" #include "jit/frontend/sh4/sh4_frontend.h"
#include "jit/frontend/sh4/sh4_guest.h"
#include "jit/ir/ir.h" #include "jit/ir/ir.h"
#include "jit/jit.h" #include "jit/jit.h"
@ -18,11 +19,11 @@ static uint32_t s_fsca_table[0x20000] = {
/* /*
* callbacks for translating each sh4 op * callbacks for translating each sh4 op
*/ */
typedef void (*emit_cb)(struct sh4_frontend *frontend, struct ir *, int, typedef void (*emit_cb)(struct sh4_guest *guest, struct ir *, int,
const struct sh4_instr *, const struct sh4_instr *); const struct sh4_instr *, const struct sh4_instr *);
#define EMITTER(name) \ #define EMITTER(name) \
void sh4_emit_OP_##name(struct sh4_frontend *frontend, struct ir *ir, \ void sh4_emit_OP_##name(struct sh4_guest *guest, struct ir *ir, \
int flags, const struct sh4_instr *i, \ int flags, const struct sh4_instr *i, \
const struct sh4_instr *delay) const struct sh4_instr *delay)
@ -43,7 +44,7 @@ static emit_cb emit_callbacks[NUM_SH4_OPS] = {
/* swizzle 32-bit fp loads, see notes in sh4_context.h */ /* swizzle 32-bit fp loads, see notes in sh4_context.h */
#define swizzle_fpr(n, type) (ir_type_size(type) == 4 ? ((n) ^ 1) : (n)) #define swizzle_fpr(n, type) (ir_type_size(type) == 4 ? ((n) ^ 1) : (n))
#define emit_delay_instr() sh4_emit_instr(frontend, ir, flags, delay, NULL) #define emit_delay_instr() sh4_emit_instr(guest, ir, flags, delay, NULL)
#define load_guest(addr, type) ir_load_guest(ir, flags, addr, type) #define load_guest(addr, type) ir_load_guest(ir, flags, addr, type)
#define store_guest(addr, v) ir_store_guest(ir, flags, addr, v) #define store_guest(addr, v) ir_store_guest(ir, flags, addr, v)
#define load_gpr(n, type) ir_load_gpr(ir, n, type) #define load_gpr(n, type) ir_load_gpr(ir, n, type)
@ -53,20 +54,20 @@ static emit_cb emit_callbacks[NUM_SH4_OPS] = {
#define load_xfr(n, type) ir_load_xfr(ir, n, type) #define load_xfr(n, type) ir_load_xfr(ir, n, type)
#define store_xfr(n, v) ir_store_xfr(ir, n, v) #define store_xfr(n, v) ir_store_xfr(ir, n, v)
#define load_sr() ir_load_sr(ir) #define load_sr() ir_load_sr(ir)
#define store_sr(v) ir_store_sr(frontend, ir, v) #define store_sr(v) ir_store_sr(guest, ir, v)
#define load_t() ir_load_t(ir) #define load_t() ir_load_t(ir)
#define store_t(v) ir_store_t(frontend, ir, v) #define store_t(v) ir_store_t(guest, ir, v)
#define load_s() ir_load_s(ir) #define load_s() ir_load_s(ir)
#define store_s(v) ir_store_s(frontend, ir, v) #define store_s(v) ir_store_s(guest, ir, v)
#define load_gbr() ir_load_gbr(ir) #define load_gbr() ir_load_gbr(ir)
#define store_gbr(v) ir_store_gbr(ir, v) #define store_gbr(v) ir_store_gbr(ir, v)
#define load_fpscr() ir_load_fpscr(ir) #define load_fpscr() ir_load_fpscr(ir)
#define store_fpscr(v) ir_store_fpscr(frontend, ir, v) #define store_fpscr(v) ir_store_fpscr(guest, ir, v)
#define load_pr() ir_load_pr(ir) #define load_pr() ir_load_pr(ir)
#define store_pr(v) ir_store_pr(ir, v) #define store_pr(v) ir_store_pr(ir, v)
#define branch(addr) ir_branch_guest(frontend, ir, addr) #define branch(addr) ir_branch_guest(guest, ir, addr)
#define branch_false(addr, cond) ir_branch_false_guest(frontend, ir, addr, cond) #define branch_false(addr, cond) ir_branch_false_guest(guest, ir, addr, cond)
#define branch_true(addr, cond) ir_branch_true_guest(frontend, ir, addr, cond) #define branch_true(addr, cond) ir_branch_true_guest(guest, ir, addr, cond)
static struct ir_value *ir_load_guest(struct ir *ir, int flags, static struct ir_value *ir_load_guest(struct ir *ir, int flags,
struct ir_value *addr, struct ir_value *addr,
@ -133,12 +134,12 @@ static struct ir_value *ir_load_sr(struct ir *ir) {
return sr; return sr;
} }
static void ir_store_sr(struct sh4_frontend *frontend, struct ir *ir, static void ir_store_sr(struct sh4_guest *guest, struct ir *ir,
struct ir_value *sr) { struct ir_value *sr) {
CHECK_EQ(sr->type, VALUE_I32); CHECK_EQ(sr->type, VALUE_I32);
struct ir_value *sr_updated = ir_alloc_ptr(ir, frontend->sr_updated); struct ir_value *sr_updated = ir_alloc_ptr(ir, guest->sr_updated);
struct ir_value *data = ir_alloc_ptr(ir, frontend->data); struct ir_value *data = ir_alloc_ptr(ir, guest->data);
struct ir_value *old_sr = load_sr(); struct ir_value *old_sr = load_sr();
ir_store_context(ir, offsetof(struct sh4_ctx, sr), sr); ir_store_context(ir, offsetof(struct sh4_ctx, sr), sr);
@ -158,7 +159,7 @@ static struct ir_value *ir_load_t(struct ir *ir) {
return ir_load_context(ir, offsetof(struct sh4_ctx, sr_t), VALUE_I32); return ir_load_context(ir, offsetof(struct sh4_ctx, sr_t), VALUE_I32);
} }
static void ir_store_t(struct sh4_frontend *frontend, struct ir *ir, static void ir_store_t(struct sh4_guest *guest, struct ir *ir,
struct ir_value *v) { struct ir_value *v) {
/* zext the results of ir_cmp_* */ /* zext the results of ir_cmp_* */
if (v->type != VALUE_I32) { if (v->type != VALUE_I32) {
@ -171,7 +172,7 @@ static struct ir_value *ir_load_s(struct ir *ir) {
return ir_load_context(ir, offsetof(struct sh4_ctx, sr_s), VALUE_I32); return ir_load_context(ir, offsetof(struct sh4_ctx, sr_s), VALUE_I32);
} }
static void ir_store_s(struct sh4_frontend *frontend, struct ir *ir, static void ir_store_s(struct sh4_guest *guest, struct ir *ir,
struct ir_value *v) { struct ir_value *v) {
CHECK_EQ(v->type, VALUE_I32); CHECK_EQ(v->type, VALUE_I32);
ir_store_context(ir, offsetof(struct sh4_ctx, sr_s), v); ir_store_context(ir, offsetof(struct sh4_ctx, sr_s), v);
@ -191,13 +192,13 @@ static struct ir_value *ir_load_fpscr(struct ir *ir) {
return ir_and(ir, fpscr, ir_alloc_i32(ir, 0x003fffff)); return ir_and(ir, fpscr, ir_alloc_i32(ir, 0x003fffff));
} }
static void ir_store_fpscr(struct sh4_frontend *frontend, struct ir *ir, static void ir_store_fpscr(struct sh4_guest *guest, struct ir *ir,
struct ir_value *v) { struct ir_value *v) {
CHECK_EQ(v->type, VALUE_I32); CHECK_EQ(v->type, VALUE_I32);
v = ir_and(ir, v, ir_alloc_i32(ir, 0x003fffff)); v = ir_and(ir, v, ir_alloc_i32(ir, 0x003fffff));
struct ir_value *fpscr_updated = ir_alloc_ptr(ir, frontend->fpscr_updated); struct ir_value *fpscr_updated = ir_alloc_ptr(ir, guest->fpscr_updated);
struct ir_value *data = ir_alloc_ptr(ir, frontend->data); struct ir_value *data = ir_alloc_ptr(ir, guest->data);
struct ir_value *old_fpscr = load_fpscr(); struct ir_value *old_fpscr = load_fpscr();
ir_store_context(ir, offsetof(struct sh4_ctx, fpscr), v); ir_store_context(ir, offsetof(struct sh4_ctx, fpscr), v);
ir_call_2(ir, fpscr_updated, data, old_fpscr); ir_call_2(ir, fpscr_updated, data, old_fpscr);
@ -212,12 +213,12 @@ static void ir_store_pr(struct ir *ir, struct ir_value *v) {
ir_store_context(ir, offsetof(struct sh4_ctx, pr), v); ir_store_context(ir, offsetof(struct sh4_ctx, pr), v);
} }
static void ir_branch_guest(struct sh4_frontend *frontend, struct ir *ir, static void ir_branch_guest(struct sh4_guest *guest, struct ir *ir,
struct ir_value *addr) { struct ir_value *addr) {
ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr); ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr);
} }
static void ir_branch_false_guest(struct sh4_frontend *frontend, struct ir *ir, static void ir_branch_false_guest(struct sh4_guest *guest, struct ir *ir,
struct ir_value *addr, struct ir_value *addr,
struct ir_value *cond) { struct ir_value *cond) {
struct ir_value *skip = ir_alloc_str(ir, "skip_%p", addr); struct ir_value *skip = ir_alloc_str(ir, "skip_%p", addr);
@ -226,7 +227,7 @@ static void ir_branch_false_guest(struct sh4_frontend *frontend, struct ir *ir,
ir_label(ir, skip); ir_label(ir, skip);
} }
static void ir_branch_true_guest(struct sh4_frontend *frontend, struct ir *ir, static void ir_branch_true_guest(struct sh4_guest *guest, struct ir *ir,
struct ir_value *addr, struct ir_value *cond) { struct ir_value *addr, struct ir_value *cond) {
struct ir_value *skip = ir_alloc_str(ir, "skip_%p", addr); struct ir_value *skip = ir_alloc_str(ir, "skip_%p", addr);
ir_branch_false(ir, skip, cond); ir_branch_false(ir, skip, cond);
@ -234,22 +235,24 @@ static void ir_branch_true_guest(struct sh4_frontend *frontend, struct ir *ir,
ir_label(ir, skip); ir_label(ir, skip);
} }
void sh4_emit_instr(struct sh4_frontend *frontend, struct ir *ir, int flags, void sh4_emit_instr(struct sh4_guest *guest, struct ir *ir, int flags,
const struct sh4_instr *instr, const struct sh4_instr *instr,
const struct sh4_instr *delay) { const struct sh4_instr *delay) {
#if 0
/* emit extra debug info for recc */ /* emit extra debug info for recc */
if (frontend->jit->dump_blocks) { if (guest->jit->dump_blocks) {
const char *name = sh4_opdefs[instr->op].name; const char *name = sh4_opdefs[instr->op].name;
ir_debug_info(ir, name, instr->addr, instr->opcode); ir_debug_info(ir, name, instr->addr, instr->opcode);
} }
#endif
(emit_callbacks[instr->op])(frontend, ir, flags, instr, delay); (emit_callbacks[instr->op])(guest, ir, flags, instr, delay);
} }
// INVALID // INVALID
EMITTER(INVALID) { EMITTER(INVALID) {
struct ir_value *invalid_instr = ir_alloc_ptr(ir, frontend->invalid_instr); struct ir_value *invalid_instr = ir_alloc_ptr(ir, guest->invalid_instr);
struct ir_value *data = ir_alloc_ptr(ir, frontend->data); struct ir_value *data = ir_alloc_ptr(ir, guest->data);
ir_call_2(ir, invalid_instr, data, ir_alloc_i32(ir, i->addr)); ir_call_2(ir, invalid_instr, data, ir_alloc_i32(ir, i->addr));
} }
@ -1536,8 +1539,8 @@ EMITTER(PREF) {
struct ir_value *skip = ir_alloc_str(ir, "skip_%p", cond); struct ir_value *skip = ir_alloc_str(ir, "skip_%p", cond);
ir_branch_true(ir, skip, cond); ir_branch_true(ir, skip, cond);
struct ir_value *data = ir_alloc_ptr(ir, frontend->data); struct ir_value *data = ir_alloc_ptr(ir, guest->data);
struct ir_value *sq_prefetch = ir_alloc_ptr(ir, frontend->sq_prefetch); struct ir_value *sq_prefetch = ir_alloc_ptr(ir, guest->sq_prefetch);
ir_call_2(ir, sq_prefetch, data, addr); ir_call_2(ir, sq_prefetch, data, addr);
ir_label(ir, skip); ir_label(ir, skip);
} }
@ -2288,13 +2291,13 @@ EMITTER(FTRV) {
// FRCHG 1111101111111101 // FRCHG 1111101111111101
EMITTER(FRCHG) { EMITTER(FRCHG) {
struct ir_value *fpscr = load_fpscr(); struct ir_value *fpscr = load_fpscr();
struct ir_value *v = ir_xor(ir, fpscr, ir_alloc_i32(ir, FR)); struct ir_value *v = ir_xor(ir, fpscr, ir_alloc_i32(ir, FR_MASK));
store_fpscr(v); store_fpscr(v);
} }
// FSCHG 1111001111111101 // FSCHG 1111001111111101
EMITTER(FSCHG) { EMITTER(FSCHG) {
struct ir_value *fpscr = load_fpscr(); struct ir_value *fpscr = load_fpscr();
struct ir_value *v = ir_xor(ir, fpscr, ir_alloc_i32(ir, SZ)); struct ir_value *v = ir_xor(ir, fpscr, ir_alloc_i32(ir, SZ_MASK));
store_fpscr(v); store_fpscr(v);
} }

View File

@ -2,10 +2,10 @@
#define SH4_TRANSLATE_H #define SH4_TRANSLATE_H
struct ir; struct ir;
struct sh4_guest;
struct sh4_instr; struct sh4_instr;
struct sh4_frontend;
void sh4_emit_instr(struct sh4_frontend *frontend, struct ir *ir, int flags, void sh4_emit_instr(struct sh4_guest *guest, struct ir *ir, int flags,
const struct sh4_instr *instr, const struct sh4_instr *instr,
const struct sh4_instr *delay); const struct sh4_instr *delay);

View File

@ -108,7 +108,7 @@ static void run_sh4_test(struct dreamcast *dc, const struct sh4_test *test) {
} }
/* ensure sh4 sr is up to date before testing against it */ /* ensure sh4 sr is up to date before testing against it */
sh4_implode_sr(dc->sh4); sh4_implode_sr(&dc->sh4->ctx);
/* validate out registers */ /* validate out registers */
for (int i = 0; i < sh4_num_test_regs; i++) { for (int i = 0; i < sh4_num_test_regs; i++) {