From 34097906684a80f1e131653ebb13659090c5233c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 9 Nov 2014 01:26:03 -0500 Subject: ARM: Fixed several dyncom bugs. - Fixed NZCVT flags to properly save state when function returns. - Fixed counter to keep track of the actual number of instructions executed. - Fixed single-step mode to only execute one instruction at a time. - DefaultIni: Removed comment that no longer applied to dyncom. --- src/citra/default_ini.h | 2 +- src/core/arm/dyncom/arm_dyncom.cpp | 7 ++++-- src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 33 +++++++++++++++----------- src/core/arm/dyncom/arm_dyncom_interpreter.h | 2 +- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 7352c70c..557da881 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -28,7 +28,7 @@ pad_sright = [Core] cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental) -gpu_refresh_rate = ## 60 (default), 1024 or 2048 may work better on the FastInterpreter +gpu_refresh_rate = ## 60 (default) [Data Storage] use_virtual_sd = diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 669b612f..0b5dcccb 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -110,9 +110,12 @@ u64 ARM_DynCom::GetTicks() const { * @param num_instructions Number of instructions to executes */ void ARM_DynCom::ExecuteInstructions(int num_instructions) { - ticks += num_instructions; state->NumInstrsToExecute = num_instructions; - InterpreterMainLoop(state.get()); + + // Dyncom only breaks on instruction dispatch. This only happens on every instruction when + // executing one instruction at a time. Otherwise, if a block is being executed, more + // instructions may actually be executed than specified. + ticks += InterpreterMainLoop(state.get()); } /** diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index fe1501b5..f56a8451 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -3718,7 +3718,7 @@ static bool InAPrivilegedMode(arm_core_t *core) } /* r15 = r15 + 8 */ -void InterpreterMainLoop(ARMul_State* state) +unsigned InterpreterMainLoop(ARMul_State* state) { #define CRn inst_cream->crn #define OPCODE_2 inst_cream->opcode_2 @@ -3754,9 +3754,15 @@ void InterpreterMainLoop(ARMul_State* state) // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a // clunky switch statement. #if defined __GNUC__ || defined __clang__ -#define GOTO_NEXT_INST goto *InstLabel[inst_base->idx] +#define GOTO_NEXT_INST \ + if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ + num_instrs++; \ + goto *InstLabel[inst_base->idx] #else -#define GOTO_NEXT_INST switch(inst_base->idx) { \ +#define GOTO_NEXT_INST \ + if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ + num_instrs++; \ + switch(inst_base->idx) { \ case 0: goto VMLA_INST; \ case 1: goto VMLS_INST; \ case 2: goto VNMLA_INST; \ @@ -4028,20 +4034,15 @@ void InterpreterMainLoop(ARMul_State* state) unsigned int addr; unsigned int phys_addr; unsigned int last_pc = 0; + unsigned int num_instrs = 0; fault_t fault; static unsigned int last_physical_base = 0, last_logical_base = 0; int ptr; + bool single_step = (cpu->NumInstrsToExecute == 1); LOAD_NZCVT; DISPATCH: { - if (cpu->NumInstrsToExecute == 0) - return; - - cpu->NumInstrsToExecute--; - - //NOTICE_LOG(ARM11, "instr!"); - if (!cpu->NirqSig) { if (!(cpu->Cpsr & 0x80)) { goto END; @@ -4393,7 +4394,8 @@ void InterpreterMainLoop(ARMul_State* state) #define CP_ACCESS_ALLOW 0 if(CP_ACCESS_ALLOW){ /* undefined instruction here */ - return; + cpu->NumInstrsToExecute = 0; + return num_instrs; } ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); @@ -6532,12 +6534,14 @@ void InterpreterMainLoop(ARMul_State* state) cpu->AbortAddr = addr; cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; - return; + cpu->NumInstrsToExecute = 0; + return num_instrs; } END: { SAVE_NZCVT; - return; + cpu->NumInstrsToExecute = 0; + return num_instrs; } INIT_INST_LENGTH: { @@ -6557,7 +6561,8 @@ void InterpreterMainLoop(ARMul_State* state) DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]); DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]); #endif - return; + cpu->NumInstrsToExecute = 0; + return num_instrs; } } diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index d73f8f65..c65eb23f 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h @@ -4,4 +4,4 @@ #pragma once -void InterpreterMainLoop(ARMul_State* state); +unsigned InterpreterMainLoop(ARMul_State* state); -- cgit v1.2.3