Skip to content

Commit

Permalink
psxinterpreter: yet more exceptions, new config option
Browse files Browse the repository at this point in the history
  • Loading branch information
notaz committed Jul 21, 2023
1 parent f9ae4f2 commit bc7c5ac
Show file tree
Hide file tree
Showing 18 changed files with 461 additions and 234 deletions.
10 changes: 10 additions & 0 deletions frontend/libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,16 @@ static void update_variables(bool in_flight)
Config.icache_emulation = 1;
}

var.value = NULL;
var.key = "pcsx_rearmed_exception_emulation";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "enabled") == 0)
Config.PreciseExceptions = 1;
else
Config.PreciseExceptions = 0;
}

psxCpu->ApplyConfig();

// end of CPU emu config
Expand Down
16 changes: 15 additions & 1 deletion frontend/libretro_core_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,21 @@ struct retro_core_option_v2_definition option_defs_us[] = {
"pcsx_rearmed_icache_emulation",
"Instruction Cache Emulation",
NULL,
"Enable emulation of the PSX CPU instruction cache. Improves accuracy at the expense of increased performance overheads. Required for Formula One 2001, Formula One Arcade and Formula One 99. [Interpreter only and partial on lightrec, unsupported when using ARMv7 backend]",
"Enable emulation of the PSX CPU instruction cache. Improves accuracy at the expense of increased performance overheads. Required for Formula One 2001, Formula One Arcade and Formula One 99. [Interpreter only; partial on lightrec and ARM dynarecs]",
NULL,
"compat_hack",
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
},
"enabled",
},
{
"pcsx_rearmed_exception_emulation",
"Exception and Breakpoint Emulation",
NULL,
"Enable emulation of some almost never used PSX's debug features. This causes a performance hit, is not useful for games and is intended for PSX homebrew and romhack developers only. Only enable if you know what you are doing. [Interpreter only]",
NULL,
"compat_hack",
{
Expand Down
9 changes: 7 additions & 2 deletions frontend/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ static const struct {
CE_CONFIG_VAL(DisableStalls),
CE_CONFIG_VAL(Cpu),
CE_CONFIG_VAL(GpuListWalking),
CE_CONFIG_VAL(PreciseExceptions),
CE_INTVAL(region),
CE_INTVAL_V(g_scaler, 3),
CE_INTVAL(g_gamma),
Expand Down Expand Up @@ -1594,12 +1595,14 @@ static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpret
#endif
static const char h_cfg_shacks[] = "Breaks games but may give better performance";
static const char h_cfg_icache[] = "Support F1 games (only when dynarec is off)";
static const char h_cfg_gpul[] = "Try enabling this if the game is missing some graphics\n"
static const char h_cfg_exc[] = "Emulate some PSX's debug hw like breakpoints\n"
"and exceptions (slow, interpreter only, keep off)";
static const char h_cfg_gpul[] = "Try enabling this if the game misses some graphics\n"
"causes a performance hit";
static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
"(adjust this if the game is too slow/too fast/hangs)";

enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_CPU, AMO_GPUL };
enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL };

static menu_entry e_menu_adv_options[] =
{
Expand All @@ -1609,6 +1612,7 @@ static menu_entry e_menu_adv_options[] =
mee_onoff_h ("Disable XA Decoding", 0, menu_iopts[AMO_XA], 1, h_cfg_xa),
mee_onoff_h ("Disable CD Audio", 0, menu_iopts[AMO_CDDA], 1, h_cfg_cdda),
mee_onoff_h ("ICache emulation", 0, menu_iopts[AMO_IC], 1, h_cfg_icache),
mee_onoff_h ("BP exception emulation", 0, menu_iopts[AMO_BP], 1, h_cfg_exc),
mee_enum_h ("GPU l-list slow walking",0, menu_iopts[AMO_GPUL], men_gpul, h_cfg_gpul),
#if !defined(DRC_DISABLE) || defined(LIGHTREC)
mee_onoff_h ("Disable dynarec (slow!)",0, menu_iopts[AMO_CPU], 1, h_cfg_nodrc),
Expand All @@ -1628,6 +1632,7 @@ static int menu_loop_adv_options(int id, int keys)
{ &Config.Xa, &menu_iopts[AMO_XA] },
{ &Config.Cdda, &menu_iopts[AMO_CDDA] },
{ &Config.icache_emulation, &menu_iopts[AMO_IC] },
{ &Config.PreciseExceptions, &menu_iopts[AMO_BP] },
{ &Config.Cpu, &menu_iopts[AMO_CPU] },
};
int i;
Expand Down
2 changes: 2 additions & 0 deletions include/compiler_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#ifdef __GNUC__
# define likely(x) __builtin_expect((x),1)
# define unlikely(x) __builtin_expect((x),0)
# define noinline __attribute__((noinline))
#else
# define likely(x) (x)
# define unlikely(x) (x)
# define noinline
#endif

#ifndef __has_builtin
Expand Down
7 changes: 6 additions & 1 deletion libpcsxcore/new_dynarec/assem_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ static void emit_loadreg(int r, int hr)
//case HIREG: addr = &hi; break;
//case LOREG: addr = &lo; break;
case CCREG: addr = &cycle_count; break;
case CSREG: addr = &psxRegs.CP0.n.Status; break;
case CSREG: addr = &psxRegs.CP0.n.SR; break;
case INVCP: addr = &invc_ptr; break;
case ROREG: addr = &ram_offset; break;
default:
Expand Down Expand Up @@ -572,6 +572,11 @@ static void emit_addimm(u_int rs,int imm,u_int rt)
else if(rs!=rt) emit_mov(rs,rt);
}

static void emit_addimm_ptr(u_int rs, uintptr_t imm, u_int rt)
{
emit_addimm(rs, imm, rt);
}

static void emit_addimm_and_set_flags(int imm,int rt)
{
assert(imm>-65536&&imm<65536);
Expand Down
7 changes: 6 additions & 1 deletion libpcsxcore/new_dynarec/assem_arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ static void emit_loadreg(u_int r, u_int hr)
//case HIREG: addr = &hi; break;
//case LOREG: addr = &lo; break;
case CCREG: addr = &cycle_count; break;
case CSREG: addr = &psxRegs.CP0.n.Status; break;
case CSREG: addr = &psxRegs.CP0.n.SR; break;
case INVCP: addr = &invc_ptr; is64 = 1; break;
case ROREG: addr = &ram_offset; is64 = 1; break;
default:
Expand Down Expand Up @@ -629,6 +629,11 @@ static void emit_addimm64(u_int rs, uintptr_t imm, u_int rt)
emit_addimm_s(0, 1, rs, imm, rt);
}

static void emit_addimm_ptr(u_int rs, uintptr_t imm, u_int rt)
{
emit_addimm64(rs, imm, rt);
}

static void emit_addimm_and_set_flags(int imm, u_int rt)
{
emit_addimm_s(1, 0, rt, imm, rt);
Expand Down
2 changes: 1 addition & 1 deletion libpcsxcore/new_dynarec/emu_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void pcsx_mtc0(u32 reg, u32 val)
evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle);
MTC0(&psxRegs, reg, val);
gen_interupt(&psxRegs.CP0);
if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300) // possible sw irq
if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.SR & 0x0300) // possible sw irq
pending_exception = 1;
}

Expand Down
2 changes: 1 addition & 1 deletion libpcsxcore/new_dynarec/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static void irq_test(psxCP0Regs *cp0)
}
}

if ((psxHu32(0x1070) & psxHu32(0x1074)) && (cp0->n.Status & 0x401) == 0x401) {
if ((psxHu32(0x1070) & psxHu32(0x1074)) && (cp0->n.SR & 0x401) == 0x401) {
psxException(0x400, 0, cp0);
pending_exception = 1;
}
Expand Down
2 changes: 1 addition & 1 deletion libpcsxcore/new_dynarec/linkage_arm.S
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ FUNCTION(jump_break):
b call_psxException
FUNCTION(jump_syscall_ds):
mov r0, #0x20
mov r1, #1
mov r1, #2
b call_psxException
FUNCTION(jump_syscall):
mov r0, #0x20
Expand Down
2 changes: 1 addition & 1 deletion libpcsxcore/new_dynarec/linkage_arm64.S
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ FUNCTION(jump_break):
b call_psxException
FUNCTION(jump_syscall_ds):
mov w0, #0x20
mov w1, #1
mov w1, #2
b call_psxException
FUNCTION(jump_syscall):
mov w0, #0x20
Expand Down
14 changes: 10 additions & 4 deletions libpcsxcore/new_dynarec/new_dynarec.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ static void noinline *get_addr(u_int vaddr, int can_compile)
return ndrc_get_addr_ht(vaddr);

// generate an address error
psxRegs.CP0.n.Status |= 2;
psxRegs.CP0.n.SR |= 2;
psxRegs.CP0.n.Cause = (vaddr<<31) | (4<<2);
psxRegs.CP0.n.EPC = (vaddr&1) ? vaddr-5 : vaddr;
psxRegs.CP0.n.BadVAddr = vaddr & ~1;
Expand Down Expand Up @@ -3559,11 +3559,11 @@ static void cop0_assemble(int i, const struct regstat *i_regs, int ccadj_)
assert(dops[i].opcode2==0x10);
//if((source[i]&0x3f)==0x10) // RFE
{
emit_readword(&psxRegs.CP0.n.Status,0);
emit_readword(&psxRegs.CP0.n.SR,0);
emit_andimm(0,0x3c,1);
emit_andimm(0,~0xf,0);
emit_orrshr_imm(1,2,0);
emit_writeword(0,&psxRegs.CP0.n.Status);
emit_writeword(0,&psxRegs.CP0.n.SR);
}
}
}
Expand Down Expand Up @@ -4132,6 +4132,7 @@ static void call_c_cpu_handler(int i, const struct regstat *i_regs, int ccadj_,
emit_addimm(HOST_CCREG,ccadj_,HOST_CCREG);
emit_add(2,HOST_CCREG,2);
emit_writeword(2,&psxRegs.cycle);
emit_addimm_ptr(FP,(u_char *)&psxRegs - (u_char *)&dynarec_local,0);
emit_far_call(func);
emit_far_jump(jump_to_new_pc);
}
Expand All @@ -4149,9 +4150,14 @@ static void syscall_assemble(int i, const struct regstat *i_regs, int ccadj_)
emit_far_jump(func);
}

static void hlecall_bad()
{
SysPrintf("bad hlecall\n");
}

static void hlecall_assemble(int i, const struct regstat *i_regs, int ccadj_)
{
void *hlefunc = gteNULL;
void *hlefunc = hlecall_bad;
uint32_t hleCode = source[i] & 0x03ffffff;
if (hleCode < ARRAY_SIZE(psxHLEt))
hlefunc = psxHLEt[hleCode];
Expand Down
2 changes: 1 addition & 1 deletion libpcsxcore/new_dynarec/pcsxmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static u32 read_mem_dummy(u32 addr)

static void write_mem_dummy(u32 data)
{
if (!(psxRegs.CP0.n.Status & (1 << 16)))
if (!(psxRegs.CP0.n.SR & (1 << 16)))
memprintf("unmapped w %08x, %08x @%08x %u\n",
address, data, psxRegs.pc, psxRegs.cycle);
}
Expand Down
21 changes: 9 additions & 12 deletions libpcsxcore/psxbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,7 @@ void psxBios_StartPAD() { // 13
#endif
pad_stopped = 0;
psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
psxRegs.CP0.n.Status |= 0x401;
psxRegs.CP0.n.SR |= 0x401;
pc0 = ra;
}

Expand All @@ -1976,7 +1976,7 @@ void psxBios_PAD_init() { // 15
psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
pad_buf = (int *)Ra1;
*pad_buf = -1;
psxRegs.CP0.n.Status |= 0x401;
psxRegs.CP0.n.SR |= 0x401;
v0 = 2;
pc0 = ra;
}
Expand All @@ -1996,8 +1996,7 @@ void psxBios_ReturnFromException() { // 17
k0 = interrupt_r26;
if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;

psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
((psxRegs.CP0.n.Status & 0x3c) >> 2);
psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
}

void psxBios_ResetEntryInt() { // 18
Expand Down Expand Up @@ -2698,7 +2697,7 @@ void psxBios_ChangeClearRCnt() { // 0a
v0 = *ptr;
*ptr = a1;

// psxRegs.CP0.n.Status|= 0x404;
// psxRegs.CP0.n.SR|= 0x404;
pc0 = ra;
}

Expand Down Expand Up @@ -3301,21 +3300,20 @@ void psxBiosException() {
switch (a0) {
case 1: // EnterCritical - disable irq's
/* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
psxRegs.CP0.n.Status &= ~0x404;
v0 = (psxRegs.CP0.n.SR & 0x404) == 0x404;
psxRegs.CP0.n.SR &= ~0x404;
break;

case 2: // ExitCritical - enable irq's
psxRegs.CP0.n.Status |= 0x404;
psxRegs.CP0.n.SR |= 0x404;
break;
/* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
default:
break;
}
pc0 = psxRegs.CP0.n.EPC + 4;

psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
((psxRegs.CP0.n.Status & 0x3c) >> 2);
psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
return;

default:
Expand All @@ -3328,8 +3326,7 @@ void psxBiosException() {
pc0 = psxRegs.CP0.n.EPC;
if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;

psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
((psxRegs.CP0.n.Status & 0x3c) >> 2);
psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
}

#define bfreeze(ptr, size) { \
Expand Down
1 change: 1 addition & 0 deletions libpcsxcore/psxcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ typedef struct {
boolean UseNet;
boolean icache_emulation;
boolean DisableStalls;
boolean PreciseExceptions;
int GpuListWalking;
int cycle_multiplier; // 100 for 1.0
int cycle_multiplier_override;
Expand Down
Loading

0 comments on commit bc7c5ac

Please sign in to comment.