diff options
author | bunnei <bunneidev@gmail.com> | 2015-07-30 16:44:50 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2015-07-30 16:44:50 +0200 |
commit | ce65925bc384632a39bb066e5ff581100d1beb69 (patch) | |
tree | 63c5ea1e9d315ee21ca5731dd4404d0a8e9b6b11 /src/core/arm | |
parent | Merge pull request #1006 from yuriks/fb-commit-profile (diff) | |
parent | dyncom: Handle the case where PC is the source register for STR/VSTM/VLDM (diff) | |
download | yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar.gz yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar.bz2 yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar.lz yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar.xz yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.tar.zst yuzu-ce65925bc384632a39bb066e5ff581100d1beb69.zip |
Diffstat (limited to 'src/core/arm')
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 7 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 54 |
2 files changed, 40 insertions, 21 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index bb0cbb4dc..b88b74752 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -5994,7 +5994,12 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; + unsigned int reg = BITS(inst_cream->inst, 12, 15); + unsigned int value = cpu->Reg[reg]; + + if (reg == 15) + value += 2 * cpu->GetInstructionSize(); + cpu->WriteMemory32(addr, value); } cpu->Reg[15] += cpu->GetInstructionSize(); diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 9b99fc5bc..49298d7ba 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp @@ -1511,19 +1511,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) #ifdef VFP_INTERPRETER_IMPL VSTM_INST: /* encoding 1 */ { - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { CHECK_VFP_ENABLED; - vstm_inst *inst_cream = (vstm_inst *)inst_base->component; + vstm_inst* inst_cream = (vstm_inst*)inst_base->component; + + u32 address = cpu->Reg[inst_cream->n]; - addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); + // Only possible in ARM mode, where PC accesses have an 8 byte offset. + if (inst_cream->n == 15) + address += 8; + + if (inst_cream->add == 0) + address -= inst_cream->imm32; for (unsigned int i = 0; i < inst_cream->regs; i++) { if (inst_cream->single) { - cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); - addr += 4; + cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d+i]); + address += 4; } else { @@ -1531,17 +1538,17 @@ VSTM_INST: /* encoding 1 */ const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; if (cpu->InBigEndianMode()) { - cpu->WriteMemory32(addr + 0, word2); - cpu->WriteMemory32(addr + 4, word1); + cpu->WriteMemory32(address + 0, word2); + cpu->WriteMemory32(address + 4, word1); } else { - cpu->WriteMemory32(addr + 0, word1); - cpu->WriteMemory32(addr + 4, word2); + cpu->WriteMemory32(address + 0, word1); + cpu->WriteMemory32(address + 4, word2); } - addr += 8; + address += 8; } } - if (inst_cream->wback){ + if (inst_cream->wback) { cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : cpu->Reg[inst_cream->n] - inst_cream->imm32); } @@ -1731,24 +1738,31 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) #ifdef VFP_INTERPRETER_IMPL VLDM_INST: { - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { CHECK_VFP_ENABLED; - vldm_inst *inst_cream = (vldm_inst *)inst_base->component; + vldm_inst* inst_cream = (vldm_inst*)inst_base->component; + + u32 address = cpu->Reg[inst_cream->n]; + + // Only possible in ARM mode, where PC accesses have an 8 byte offset. + if (inst_cream->n == 15) + address += 8; - addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); + if (inst_cream->add == 0) + address -= inst_cream->imm32; for (unsigned int i = 0; i < inst_cream->regs; i++) { if (inst_cream->single) { - cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); - addr += 4; + cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(address); + address += 4; } else { - const u32 word1 = cpu->ReadMemory32(addr + 0); - const u32 word2 = cpu->ReadMemory32(addr + 4); + const u32 word1 = cpu->ReadMemory32(address + 0); + const u32 word2 = cpu->ReadMemory32(address + 4); if (cpu->InBigEndianMode()) { cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; @@ -1758,10 +1772,10 @@ VLDM_INST: cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; } - addr += 8; + address += 8; } } - if (inst_cream->wback){ + if (inst_cream->wback) { cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : cpu->Reg[inst_cream->n] - inst_cream->imm32); } |