aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2015-07-28 20:06:48 -0400
committerLioncash <mathew1800@gmail.com>2015-07-28 20:14:08 -0400
commit2182adff9e281984267d5cb56fbe92503e38a972 (patch)
tree6ad47fb5488644029f8cc9a46d7b57ad0209f212 /src
parent4ccc171db407ededaa19a1ffec61e1a9c6daf829 (diff)
dyncom: Handle left-operand PC correctly for data-processing ops
This is considered deprecated in the ARM manual (using PC as an operand), however, this is still able to be executed on the MPCore (which I'm quite sure would be rare to begin with).
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index d022546e..0c20c2bc 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -3924,9 +3924,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
adc_inst* const inst_cream = (adc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
@@ -3987,11 +3991,17 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
AND_INST:
{
- and_inst *inst_cream = (and_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ and_inst* const inst_cream = (and_inst*)inst_base->component;
+
u32 lop = RN;
u32 rop = SHIFTER_OPERAND;
+
+ if (inst_cream->Rn == 15)
+ lop += 2 * cpu->GetInstructionSize();
+
RD = lop & rop;
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4164,9 +4174,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow);
+ u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
UPDATE_NFLAG(result);
UPDATE_ZFLAG(result);
@@ -4905,6 +4919,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 lop = RN;
u32 rop = SHIFTER_OPERAND;
+
+ if (inst_cream->Rn == 15)
+ lop += 2 * cpu->GetInstructionSize();
+
RD = lop | rop;
if (inst_cream->S && (inst_cream->Rd == 15)) {
@@ -5195,9 +5213,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
@@ -5335,9 +5357,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
@@ -6171,7 +6197,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rn_val = RN;
if (inst_cream->Rn == 15)
- rn_val += 8;
+ rn_val += 2 * cpu->GetInstructionSize();
bool carry;
bool overflow;