diff options
| -rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 3 | ||||
| -rw-r--r-- | src/citra_qt/debugger/disassembler.cpp | 5 | ||||
| -rw-r--r-- | src/common/break_points.cpp | 4 | ||||
| -rw-r--r-- | src/common/break_points.h | 4 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.cpp | 4 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.h | 37 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 205 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 431 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/arm_regformat.h | 90 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 4 | ||||
| -rw-r--r-- | src/core/hle/config_mem.cpp | 4 | 
11 files changed, 597 insertions, 194 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 9bb22ca2e..3742c2d38 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -27,7 +27,6 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)  void CallstackWidget::OnDebugModeEntered()  { -    ARM_Disasm* disasm = new ARM_Disasm();      ARM_Interface* app_core = Core::g_app_core;      u32 sp = app_core->GetReg(13); //stack pointer @@ -46,7 +45,7 @@ void CallstackWidget::OnDebugModeEntered()          /* TODO (mattvail) clean me, move to debugger interface */          u32 insn = Memory::Read32(call_addr); -        if (disasm->Decode(insn) == OP_BL) +        if (ARM_Disasm::Decode(insn) == OP_BL)          {              std::string name;              // ripped from disasm diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index 54d21dc90..f620687ae 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -232,11 +232,8 @@ void DisassemblerWidget::OnDebugModeEntered()  {      ARMword next_instr = Core::g_app_core->GetPC(); -    // TODO: Make BreakPoints less crappy (i.e. const-correct) so that this doesn't need a const_cast. -    if (const_cast<BreakPoints&>(model->GetBreakPoints()).IsAddressBreakPoint(next_instr)) -    { +    if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))          emu_thread.SetCpuRunning(false); -    }      model->SetNextInstruction(next_instr); diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp index 2655d3ce9..15055bd4e 100644 --- a/src/common/break_points.cpp +++ b/src/common/break_points.cpp @@ -10,14 +10,14 @@  #include <sstream>  #include <algorithm> -bool BreakPoints::IsAddressBreakPoint(u32 iAddress) +bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const  {      auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; };      auto it   = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond);      return it != m_BreakPoints.end();  } -bool BreakPoints::IsTempBreakPoint(u32 iAddress) +bool BreakPoints::IsTempBreakPoint(u32 iAddress) const  {      auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress && bp.bTemporary; };      auto it   = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); diff --git a/src/common/break_points.h b/src/common/break_points.h index 5557cd50e..4b26cf90d 100644 --- a/src/common/break_points.h +++ b/src/common/break_points.h @@ -56,8 +56,8 @@ public:      void AddFromStrings(const TBreakPointsStr& bps);      // is address breakpoint -    bool IsAddressBreakPoint(u32 iAddress); -    bool IsTempBreakPoint(u32 iAddress); +    bool IsAddressBreakPoint(u32 iAddress) const; +    bool IsTempBreakPoint(u32 iAddress) const;      // Add BreakPoint      void Add(u32 em_address, bool temp=false); diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 9f3b90fd0..12181d0ec 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp @@ -413,7 +413,7 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) {                  if (instr != arm_instruction[i].content[base + 2]) {                      break;                  } -            } else if (BITS(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) { +            } else if (BITS(instr, arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {                  break;              }              base += 3; @@ -429,7 +429,7 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) {              if (n != 0) {                  base = 0;                  while (n) { -                    if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) { +                    if (BITS(instr, arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {                          break;                      }                      base += 3; diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index ee8ff5992..4b5f5ad7e 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h @@ -4,43 +4,6 @@  #pragma once -#define BITS(a,b)   ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) -#define BIT(n)      ((instr >> (n)) & 1) - -// For MUL instructions -#define RDHi        ((instr >> 16) & 0xF) -#define RDLo        ((instr >> 12) & 0xF) -#define MUL_RD      ((instr >> 16) & 0xF) -#define MUL_RN      ((instr >> 12) & 0xF) -#define RS          ((instr >> 8) & 0xF) -#define RD          ((instr >> 12) & 0xF) -#define RN          ((instr >> 16) & 0xF) -#define RM          (instr & 0xF) - -// CP15 registers -#define OPCODE_1    BITS(21, 23) -#define CRn         BITS(16, 19) -#define CRm         BITS(0, 3) -#define OPCODE_2    BITS(5, 7) - -#define I           BIT(25) -#define S           BIT(20) - -#define             SHIFT BITS(5,6) -#define             SHIFT_IMM BITS(7,11) -#define             IMMH BITS(8,11) -#define             IMML BITS(0,3) - -#define LSPBIT      BIT(24) -#define LSUBIT      BIT(23) -#define LSBBIT      BIT(22) -#define LSWBIT      BIT(21) -#define LSLBIT      BIT(20) -#define LSSHBITS    BITS(5,6) -#define OFFSET12    BITS(0,11) -#define SBIT        BIT(20) -#define DESTReg     (BITS (12, 15)) -  int decode_arm_instr(uint32_t instr, int32_t *idx);  enum DECODE_STATUS { diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index cfa6de8fc..b0efd7194 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -2156,7 +2156,22 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index)       return INTERPRETER_TRANSLATE(rev)(inst, index);  } -static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index)   { UNIMPLEMENTED_INSTRUCTION("RFE"); } +static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) +{ +    arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); +    ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + +    inst_base->cond     = AL; +    inst_base->idx      = index; +    inst_base->br       = INDIRECT_BRANCH; +    inst_base->load_r15 = 0; + +    inst_cream->inst = inst; +    inst_cream->get_addr = get_calc_addr_op(inst); + +    return inst_base; +} +  static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)  {      arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); @@ -2570,7 +2585,23 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)          inst_base->load_r15 = 1;      return inst_base;  } -static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index)      { UNIMPLEMENTED_INSTRUCTION("SRS"); } + +static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) +{ +    arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); +    ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + +    inst_base->cond     = AL; +    inst_base->idx      = index; +    inst_base->br       = NON_BRANCH; +    inst_base->load_r15 = 0; + +    inst_cream->inst     = inst; +    inst_cream->get_addr = get_calc_addr_op(inst); + +    return inst_base; +} +  static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)  {      arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); @@ -3659,10 +3690,6 @@ static int clz(unsigned int x) {      return n;  } -static bool InAPrivilegedMode(ARMul_State* core) { -    return (core->Mode != USER32MODE); -} -  unsigned InterpreterMainLoop(ARMul_State* state) {      Common::Profiling::ScopeTimer timer_execute(profile_execute); @@ -3670,6 +3697,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {      #undef RS      #define CRn             inst_cream->crn +    #define OPCODE_1        inst_cream->opcode_1      #define OPCODE_2        inst_cream->opcode_2      #define CRm             inst_cream->crm      #define CP15_REG(n)     cpu->CP15[CP15(n)] @@ -4733,94 +4761,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {              if (inst_cream->Rd == 15) {                  DEBUG_MSG;              } else { -                if (inst_cream->cp_num == 15) { -                    if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { -                        CP15_REG(CP15_CONTROL) = RD; -                    } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { -                        CP15_REG(CP15_AUXILIARY_CONTROL) = RD; -                    } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { -                        CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { -                        CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { -                        CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { -                        CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD; -                    } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { -                        CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD; -                    } else if(CRn == MMU_CACHE_OPS){ -                        //LOG_WARNING(Core_ARM11, "cache operations have not implemented."); -                    } else if(CRn == MMU_TLB_OPS){ -                        switch (CRm) { -                        case 5: // ITLB -                            switch(OPCODE_2) { -                            case 0: // Invalidate all -                                LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate all"); -                                break; -                            case 1: // Invalidate by MVA -                                LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by mva"); -                                break; -                            case 2: // Invalidate by asid -                                LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by asid"); -                                break; -                            default: -                                break; -                            } - -                            break; -                        case 6: // DTLB -                            switch(OPCODE_2){ -                            case 0: // Invalidate all -                                LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate all"); -                                break; -                            case 1: // Invalidate by MVA -                                LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by mva"); -                                break; -                            case 2: // Invalidate by asid -                                LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by asid"); -                                break; -                            default: -                                break; -                            } -                            break; -                        case 7: // UNIFILED TLB -                            switch(OPCODE_2){ -                            case 0: // invalidate all -                                LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate all"); -                                break; -                            case 1: // Invalidate by MVA -                                LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by mva"); -                                break; -                            case 2: // Invalidate by asid -                                LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by asid"); -                                break; -                            default: -                                break; -                            } -                            break; -                        default: -                            break; -                        } -                    } else if(CRn == MMU_PID) { -                        if(OPCODE_2 == 0) { -                            CP15_REG(CP15_PID) = RD; -                        } else if(OPCODE_2 == 1) { -                            CP15_REG(CP15_CONTEXT_ID) = RD; -                        } else if (OPCODE_2 == 2) { -                            CP15_REG(CP15_THREAD_UPRW) = RD; -                        } else if(OPCODE_2 == 3) { -                            if (InAPrivilegedMode(cpu)) -                                CP15_REG(CP15_THREAD_URO) = RD; -                        } else if (OPCODE_2 == 4) { -                            if (InAPrivilegedMode(cpu)) -                                CP15_REG(CP15_THREAD_PRW) = RD; -                        } else { -                            LOG_ERROR(Core_ARM11, "mmu_mcr wrote UNKNOWN - reg %d", CRn); -                        } -                    } else { -                        LOG_ERROR(Core_ARM11, "mcr CRn=%d, CRm=%d OP2=%d is not implemented", CRn, CRm, OPCODE_2); -                    } -                } +                if (inst_cream->cp_num == 15) +                    WriteCP15Register(cpu, RD, CRn, OPCODE_1, CRm, OPCODE_2);              }          }          cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -4895,50 +4837,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {                  CITRA_IGNORE_EXIT(-1);                  goto END;              } else { -                if (inst_cream->cp_num == 15) { -                    if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { -                        RD = cpu->CP15[CP15(CP15_MAIN_ID)]; -                    } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) { -                        RD = cpu->CP15[CP15(CP15_CACHE_TYPE)]; -                    } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { -                        RD = cpu->CP15[CP15(CP15_CONTROL)]; -                    } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { -                        RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; -                    } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { -                        RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { -                        RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { -                        RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_1)]; -                    } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { -                        RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_CONTROL)]; -                    } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { -                        RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)]; -                    } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) { -                        RD = cpu->CP15[CP15(CP15_FAULT_STATUS)]; -                    } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) { -                        RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; -                    } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) { -                        RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)]; -                    } else if (CRn == 13) { -                        if(OPCODE_2 == 0) { -                            RD = CP15_REG(CP15_PID); -                        } else if(OPCODE_2 == 1) { -                            RD = CP15_REG(CP15_CONTEXT_ID); -                        } else if (OPCODE_2 == 2) { -                            RD = CP15_REG(CP15_THREAD_UPRW); -                        } else if(OPCODE_2 == 3) { -                            RD = Memory::KERNEL_MEMORY_VADDR; -                        } else if (OPCODE_2 == 4) { -                            if (InAPrivilegedMode(cpu)) -                                RD = CP15_REG(CP15_THREAD_PRW); -                        } else { -                            LOG_ERROR(Core_ARM11, "mmu_mrr wrote UNKNOWN - reg %d", CRn); -                        } -                    } else { -                        LOG_ERROR(Core_ARM11, "mrc CRn=%d, CRm=%d, OP2=%d is not implemented", CRn, CRm, OPCODE_2); -                    } -                } +                if (inst_cream->cp_num == 15) +                     RD = ReadCP15Register(cpu, CRn, OPCODE_1, CRm, OPCODE_2);              }          }          cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -5293,6 +5193,20 @@ unsigned InterpreterMainLoop(ARMul_State* state) {      }      RFE_INST: +    { +        // RFE is unconditional +        ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + +        u32 address = 0; +        inst_cream->get_addr(cpu, inst_cream->inst, address, 1); + +        cpu->Cpsr    = ReadMemory32(cpu, address); +        cpu->Reg[15] = ReadMemory32(cpu, address + 4); + +        INC_PC(sizeof(ldst_inst)); +        goto DISPATCH; +    } +      RSB_INST:      {          if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { @@ -5934,6 +5848,21 @@ unsigned InterpreterMainLoop(ARMul_State* state) {      }      SRS_INST: +    { +        // SRS is unconditional +        ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + +        u32 address = 0; +        inst_cream->get_addr(cpu, inst_cream->inst, address, 1); + +        WriteMemory32(cpu, address + 0, cpu->Reg[14]); +        WriteMemory32(cpu, address + 4, cpu->Spsr_copy); + +        cpu->Reg[15] += GET_INST_SIZE(cpu); +        INC_PC(sizeof(ldst_inst)); +        FETCH_INST; +        GOTO_NEXT_INST; +    }      SSAT_INST:      { diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index aca2bfbbd..6a11a5804 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -15,7 +15,9 @@      along with this program; if not, write to the Free Software      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "core/mem_map.h"  #include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/arm_regformat.h"  // Unsigned sum of absolute difference  u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) @@ -207,3 +209,432 @@ bool InBigEndianMode(ARMul_State* cpu)  {      return (cpu->Cpsr & (1 << 9)) != 0;  } + +// Whether or not the given CPU is in a mode other than user mode. +bool InAPrivilegedMode(ARMul_State* cpu) +{ +    return (cpu->Mode != USER32MODE); +} + +// Reads from the CP15 registers. Used with implementation of the MRC instruction. +// Note that since the 3DS does not have the hypervisor extensions, these registers +// are not implemented. +u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) +{ +    // Unprivileged registers +    if (crn == 13 && opcode_1 == 0 && crm == 0) +    { +        if (opcode_2 == 2) +            return cpu->CP15[CP15(CP15_THREAD_UPRW)]; + +        // TODO: Whenever TLS is implemented, this should return +        // "cpu->CP15[CP15(CP15_THREAD_URO)];" +        // which contains the address of the 0x200-byte TLS +        if (opcode_2 == 3) +            return Memory::KERNEL_MEMORY_VADDR; +    } + +    if (InAPrivilegedMode(cpu)) +    { +        if (crn == 0 && opcode_1 == 0) +        { +            if (crm == 0) +            { +                if (opcode_2 == 0) +                    return cpu->CP15[CP15(CP15_MAIN_ID)]; + +                if (opcode_2 == 1) +                    return cpu->CP15[CP15(CP15_CACHE_TYPE)]; + +                if (opcode_2 == 3) +                    return cpu->CP15[CP15(CP15_TLB_TYPE)]; + +                if (opcode_2 == 5) +                    return cpu->CP15[CP15(CP15_CPU_ID)]; +            } +            else if (crm == 1) +            { +                if (opcode_2 == 0) +                    return cpu->CP15[CP15(CP15_PROCESSOR_FEATURE_0)]; + +                if (opcode_2 == 1) +                    return cpu->CP15[CP15(CP15_PROCESSOR_FEATURE_1)]; + +                if (opcode_2 == 2) +                    return cpu->CP15[CP15(CP15_DEBUG_FEATURE_0)]; + +                if (opcode_2 == 4) +                    return cpu->CP15[CP15(CP15_MEMORY_MODEL_FEATURE_0)]; + +                if (opcode_2 == 5) +                    return cpu->CP15[CP15(CP15_MEMORY_MODEL_FEATURE_1)]; + +                if (opcode_2 == 6) +                    return cpu->CP15[CP15(CP15_MEMORY_MODEL_FEATURE_2)]; + +                if (opcode_2 == 7) +                    return cpu->CP15[CP15(CP15_MEMORY_MODEL_FEATURE_3)]; +            } +            else if (crm == 2) +            { +                if (opcode_2 == 0) +                    return cpu->CP15[CP15(CP15_ISA_FEATURE_0)]; + +                if (opcode_2 == 1) +                    return cpu->CP15[CP15(CP15_ISA_FEATURE_1)]; + +                if (opcode_2 == 2) +                    return cpu->CP15[CP15(CP15_ISA_FEATURE_2)]; + +                if (opcode_2 == 3) +                    return cpu->CP15[CP15(CP15_ISA_FEATURE_3)]; + +                if (opcode_2 == 4) +                    return cpu->CP15[CP15(CP15_ISA_FEATURE_4)]; +            } +        } + +        if (crn == 1 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                return cpu->CP15[CP15(CP15_CONTROL)]; + +            if (opcode_2 == 1) +                return cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; + +            if (opcode_2 == 2) +                return cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; +        } + +        if (crn == 2 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                return cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; + +            if (opcode_2 == 1) +                return cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_1)]; + +            if (opcode_2 == 2) +                return cpu->CP15[CP15(CP15_TRANSLATION_BASE_CONTROL)]; +        } + +        if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) +            return cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)]; + +        if (crn == 5 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                return cpu->CP15[CP15(CP15_FAULT_STATUS)]; + +            if (opcode_2 == 1) +                return cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; +        } + +        if (crn == 6 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                return cpu->CP15[CP15(CP15_FAULT_ADDRESS)]; + +            if (opcode_2 == 1) +                return cpu->CP15[CP15(CP15_WFAR)]; +        } + +        if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) +            return cpu->CP15[CP15(CP15_PHYS_ADDRESS)]; + +        if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) +            return cpu->CP15[CP15(CP15_DATA_CACHE_LOCKDOWN)]; + +        if (crn == 10 && opcode_1 == 0) +        { +            if (crm == 0 && opcode_2 == 0) +                return cpu->CP15[CP15(CP15_TLB_LOCKDOWN)]; + +            if (crm == 2) +            { +                if (opcode_2 == 0) +                    return cpu->CP15[CP15(CP15_PRIMARY_REGION_REMAP)]; + +                if (opcode_2 == 1) +                    return cpu->CP15[CP15(CP15_NORMAL_REGION_REMAP)]; +            } +        } + +        if (crn == 13 && crm == 0) +        { +            if (opcode_2 == 0) +                return cpu->CP15[CP15(CP15_PID)]; + +            if (opcode_2 == 1) +                return cpu->CP15[CP15(CP15_CONTEXT_ID)]; + +            if (opcode_2 == 4) +                return cpu->CP15[CP15(CP15_THREAD_PRW)]; +        } + +        if (crn == 15) +        { +            if (opcode_1 == 0 && crm == 12) +            { +                if (opcode_2 == 0) +                    return cpu->CP15[CP15(CP15_PERFORMANCE_MONITOR_CONTROL)]; + +                if (opcode_2 == 1) +                    return cpu->CP15[CP15(CP15_CYCLE_COUNTER)]; + +                if (opcode_2 == 2) +                    return cpu->CP15[CP15(CP15_COUNT_0)]; + +                if (opcode_2 == 3) +                    return cpu->CP15[CP15(CP15_COUNT_1)]; +            } + +            if (opcode_1 == 5 && opcode_2 == 2) +            { +                if (crm == 5) +                    return cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS)]; + +                if (crm == 6) +                    return cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS)]; + +                if (crm == 7) +                    return cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE)]; +            } + +            if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) +                return cpu->CP15[CP15(CP15_TLB_DEBUG_CONTROL)]; +        } +    } + +    LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); +    return 0; +} + +// Write to the CP15 registers. Used with implementation of the MCR instruction. +// Note that since the 3DS does not have the hypervisor extensions, these registers +// are not implemented. +void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) +{ +    if (InAPrivilegedMode(cpu)) +    { +        if (crn == 1 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                cpu->CP15[CP15(CP15_CONTROL)] = value; +            else if (opcode_2 == 1) +                cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)] = value; +            else if (opcode_2 == 2) +                cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)] = value; +        } +        else if (crn == 2 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)] = value; +            else if (opcode_2 == 1) +                cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_1)] = value; +            else if (opcode_2 == 2) +                cpu->CP15[CP15(CP15_TRANSLATION_BASE_CONTROL)] = value; +        } +        else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) +        { +            cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)] = value; +        } +        else if (crn == 5 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                cpu->CP15[CP15(CP15_FAULT_STATUS)] = value; +            else if (opcode_2 == 1) +                cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = value; +        } +        else if (crn == 6 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = value; +            else if (opcode_2 == 1) +                cpu->CP15[CP15(CP15_WFAR)] = value; +        } +        else if (crn == 7 && opcode_1 == 0) +        { +            LOG_WARNING(Core_ARM11, "Cache operations are not fully implemented."); + +            if (crm == 0 && opcode_2 == 4) +            { +                cpu->CP15[CP15(CP15_WAIT_FOR_INTERRUPT)] = value; +            } +            else if (crm == 4 && opcode_2 == 0) +            { +                // NOTE: Not entirely accurate. This should do permission checks. +                cpu->CP15[CP15(CP15_PHYS_ADDRESS)] = Memory::VirtualToPhysicalAddress(value); +            } +            else if (crm == 5) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_INVALIDATE_INSTR_CACHE)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_INVALIDATE_INSTR_CACHE_USING_MVA)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_INVALIDATE_INSTR_CACHE_USING_INDEX)] = value; +                else if (opcode_2 == 6) +                    cpu->CP15[CP15(CP15_FLUSH_BRANCH_TARGET_CACHE)] = value; +                else if (opcode_2 == 7) +                    cpu->CP15[CP15(CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY)] = value; +            } +            else if (crm == 6) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_INVALIDATE_DATA_CACHE)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX)] = value; +            } +            else if (crm == 7 && opcode_2 == 0) +            { +                cpu->CP15[CP15(CP15_INVALIDATE_DATA_AND_INSTR_CACHE)] = value; +            } +            else if (crm == 10) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_CLEAN_DATA_CACHE)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_CLEAN_DATA_CACHE_LINE_USING_MVA)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX)] = value; +            } +            else if (crm == 14) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_CLEAN_AND_INVALIDATE_DATA_CACHE)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX)] = value; +            } +        } +        else if (crn == 8 && opcode_1 == 0) +        { +            LOG_WARNING(Core_ARM11, "TLB operations not fully implemented."); + +            if (crm == 5) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_INVALIDATE_ITLB)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_INVALIDATE_ITLB_SINGLE_ENTRY)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH)] = value; +                else if (opcode_2 == 3) +                    cpu->CP15[CP15(CP15_INVALIDATE_ITLB_ENTRY_ON_MVA)] = value; +            } +            else if (crm == 6) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_INVALIDATE_DTLB)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_INVALIDATE_DTLB_SINGLE_ENTRY)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH)] = value; +                else if (opcode_2 == 3) +                    cpu->CP15[CP15(CP15_INVALIDATE_DTLB_ENTRY_ON_MVA)] = value; +            } +            else if (crm == 7) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_INVALIDATE_UTLB)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_INVALIDATE_UTLB_SINGLE_ENTRY)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH)] = value; +                else if (opcode_2 == 3) +                    cpu->CP15[CP15(CP15_INVALIDATE_UTLB_ENTRY_ON_MVA)] = value; +            } +        } +        else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) +        { +            cpu->CP15[CP15(CP15_DATA_CACHE_LOCKDOWN)] = value; +        } +        else if (crn == 10 && opcode_1 == 0) +        { +            if (crm == 0 && opcode_2 == 0) +            { +                cpu->CP15[CP15(CP15_TLB_LOCKDOWN)] = value; +            } +            else if (crm == 2) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_PRIMARY_REGION_REMAP)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_NORMAL_REGION_REMAP)] = value; +            } +        } +        else if (crn == 13 && opcode_1 == 0 && crm == 0) +        { +            if (opcode_2 == 0) +                cpu->CP15[CP15(CP15_PID)] = value; +            else if (opcode_2 == 1) +                cpu->CP15[CP15(CP15_CONTEXT_ID)] = value; +            else if (opcode_2 == 3) +                cpu->CP15[CP15(CP15_THREAD_URO)] = value; +            else if (opcode_2 == 4) +                cpu->CP15[CP15(CP15_THREAD_PRW)] = value; +        } +        else if (crn == 15) +        { +            if (opcode_1 == 0 && crm == 12) +            { +                if (opcode_2 == 0) +                    cpu->CP15[CP15(CP15_PERFORMANCE_MONITOR_CONTROL)] = value; +                else if (opcode_2 == 1) +                    cpu->CP15[CP15(CP15_CYCLE_COUNTER)] = value; +                else if (opcode_2 == 2) +                    cpu->CP15[CP15(CP15_COUNT_0)] = value; +                else if (opcode_2 == 3) +                    cpu->CP15[CP15(CP15_COUNT_1)] = value; +            } +            else if (opcode_1 == 5) +            { +                if (crm == 4) +                { +                    if (opcode_2 == 2) +                        cpu->CP15[CP15(CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY)] = value; +                    else if (opcode_2 == 4) +                        cpu->CP15[CP15(CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY)] = value; +                } +                else if (crm == 5 && opcode_2 == 2) +                { +                    cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS)] = value; +                } +                else if (crm == 6 && opcode_2 == 2) +                { +                    cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS)] = value; +                } +                else if (crm == 7 && opcode_2 == 2) +                { +                    cpu->CP15[CP15(CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE)] = value; +                } +            } +            else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) +            { +                cpu->CP15[CP15(CP15_TLB_DEBUG_CONTROL)] = value; +            } +        } +    } + +    // Unprivileged registers +    if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) +    { +        cpu->CP15[CP15(CP15_FLUSH_PREFETCH_BUFFER)] = value; +    } +    else if (crn == 7 && opcode_1 == 0 && crm == 10) +    { +       if (opcode_2 == 4) +           cpu->CP15[CP15(CP15_DATA_SYNC_BARRIER)] = value; +       else if (opcode_2 == 5) +           cpu->CP15[CP15(CP15_DATA_MEMORY_BARRIER)] = value; +            +    } +    else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) +    { +        cpu->CP15[CP15(CP15_THREAD_UPRW)] = value; +    } +} diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h index 5be3a561f..c232376e0 100644 --- a/src/core/arm/skyeye_common/arm_regformat.h +++ b/src/core/arm/skyeye_common/arm_regformat.h @@ -50,6 +50,8 @@ enum {      EXCLUSIVE_TAG,      EXCLUSIVE_STATE,      EXCLUSIVE_RESULT, + +    // c0 - Information registers      CP15_BASE,      CP15_C0 = CP15_BASE,      CP15_C0_C0 = CP15_C0, @@ -57,15 +59,30 @@ enum {      CP15_CACHE_TYPE,      CP15_TCM_STATUS,      CP15_TLB_TYPE, +    CP15_CPU_ID,      CP15_C0_C1,      CP15_PROCESSOR_FEATURE_0 = CP15_C0_C1,      CP15_PROCESSOR_FEATURE_1,      CP15_DEBUG_FEATURE_0,      CP15_AUXILIARY_FEATURE_0, +    CP15_MEMORY_MODEL_FEATURE_0, +    CP15_MEMORY_MODEL_FEATURE_1, +    CP15_MEMORY_MODEL_FEATURE_2, +    CP15_MEMORY_MODEL_FEATURE_3, +    CP15_C0_C2, +    CP15_ISA_FEATURE_0 = CP15_C0_C2, +    CP15_ISA_FEATURE_1, +    CP15_ISA_FEATURE_2, +    CP15_ISA_FEATURE_3, +    CP15_ISA_FEATURE_4, + +    // c1 - Control registers      CP15_C1_C0,      CP15_CONTROL = CP15_C1_C0,      CP15_AUXILIARY_CONTROL,      CP15_COPROCESSOR_ACCESS_CONTROL, + +    // c2 - Translation table registers      CP15_C2,      CP15_C2_C0 = CP15_C2,      CP15_TRANSLATION_BASE = CP15_C2_C0, @@ -74,24 +91,87 @@ enum {      CP15_TRANSLATION_BASE_CONTROL,      CP15_DOMAIN_ACCESS_CONTROL,      CP15_RESERVED, -    /* Fault status */ + +    // c5 - Fault status registers      CP15_FAULT_STATUS,      CP15_INSTR_FAULT_STATUS,      CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,      CP15_INST_FSR, -    /* Fault Address register */ + +    // c6 - Fault Address registers      CP15_FAULT_ADDRESS,      CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,      CP15_WFAR,      CP15_IFAR, + +    // c7 - Cache operation registers +    CP15_WAIT_FOR_INTERRUPT, +    CP15_PHYS_ADDRESS, +    CP15_INVALIDATE_INSTR_CACHE, +    CP15_INVALIDATE_INSTR_CACHE_USING_MVA, +    CP15_INVALIDATE_INSTR_CACHE_USING_INDEX, +    CP15_FLUSH_PREFETCH_BUFFER, +    CP15_FLUSH_BRANCH_TARGET_CACHE, +    CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY, +    CP15_INVALIDATE_DATA_CACHE, +    CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA, +    CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, +    CP15_INVALIDATE_DATA_AND_INSTR_CACHE, +    CP15_CLEAN_DATA_CACHE, +    CP15_CLEAN_DATA_CACHE_LINE_USING_MVA, +    CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX, +    CP15_DATA_SYNC_BARRIER, +    CP15_DATA_MEMORY_BARRIER, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, + +    // c8 - TLB operations +    CP15_INVALIDATE_ITLB, +    CP15_INVALIDATE_ITLB_SINGLE_ENTRY, +    CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_ITLB_ENTRY_ON_MVA, +    CP15_INVALIDATE_DTLB, +    CP15_INVALIDATE_DTLB_SINGLE_ENTRY, +    CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_DTLB_ENTRY_ON_MVA, +    CP15_INVALIDATE_UTLB, +    CP15_INVALIDATE_UTLB_SINGLE_ENTRY, +    CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_UTLB_ENTRY_ON_MVA, + +    // c9 - Data cache lockdown register +    CP15_DATA_CACHE_LOCKDOWN, + +    // c10 - TLB/Memory map registers +    CP15_TLB_LOCKDOWN, +    CP15_PRIMARY_REGION_REMAP, +    CP15_NORMAL_REGION_REMAP, + +    // c13 - Thread related registers      CP15_PID,      CP15_CONTEXT_ID,      CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write      CP15_THREAD_URO,  // Thread ID register - User Read Only (Privileged R/W)      CP15_THREAD_PRW,  // Thread ID register - Privileged R/W only. -    CP15_TLB_FAULT_ADDR, /* defined by SkyEye */ -    CP15_TLB_FAULT_STATUS, /* defined by SkyEye */ -    /* VFP registers */ + +    // c15 - Performance and TLB lockdown registers +    CP15_PERFORMANCE_MONITOR_CONTROL, +    CP15_CYCLE_COUNTER, +    CP15_COUNT_0, +    CP15_COUNT_1, +    CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY, +    CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY, +    CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS, +    CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS, +    CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE, +    CP15_TLB_DEBUG_CONTROL, + +    // Skyeye defined +    CP15_TLB_FAULT_ADDR, +    CP15_TLB_FAULT_STATUS, + +    // VFP registers      VFP_BASE,      VFP_FPSID = VFP_BASE,      VFP_FPSCR, diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index c1a19fecc..d5b0242c3 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h @@ -357,3 +357,7 @@ extern u32 ARMul_SignedSatQ(s32, u8, bool*);  extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);  extern bool InBigEndianMode(ARMul_State*); +extern bool InAPrivilegedMode(ARMul_State*); + +extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); +extern void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index b10c19d1d..40bae9346 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp @@ -65,9 +65,9 @@ void Init() {      config_mem.sys_core_ver = 0x2;      config_mem.unit_info = 0x1; // Bit 0 set for Retail      config_mem.prev_firm = 0; -    config_mem.app_mem_type = 0; // Defualt app mem type +    config_mem.app_mem_type = 0x2; // Default app mem type is 0      config_mem.unit_info = 0x1; // Bit 0 set for Retail -    config_mem.app_mem_alloc = 0x04000000; // Default app memory size is 64MB +    config_mem.app_mem_alloc = 0x06000000; // Set to 96MB, since some games use more than the default (64MB)      config_mem.base_mem_alloc = 0x01400000; // Default base memory is 20MB      config_mem.sys_mem_alloc = Memory::FCRAM_SIZE - (config_mem.app_mem_alloc + config_mem.base_mem_alloc);      config_mem.firm_unk = 0;  | 
