mirror of https://github.com/inolen/redream.git
move guest functionality outside of frontend struct
This commit is contained in:
parent
eb2e1b6bcd
commit
47a47d15dc
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
Loading…
Reference in New Issue