summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp48
-rw-r--r--src/core/arm/interpreter/armsupp.cpp8
-rw-r--r--src/core/arm/skyeye_common/armemu.h1
3 files changed, 36 insertions, 21 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 578d71380..b2f671f94 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -1670,7 +1670,7 @@ mainswitch:
1670 op1 *= op2; 1670 op1 *= op2;
1671 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); 1671 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn);
1672 if (AddOverflow(op1, Rn, op1 + Rn)) 1672 if (AddOverflow(op1, Rn, op1 + Rn))
1673 SETS; 1673 SETQ;
1674 state->Reg[BITS (16, 19)] = op1 + Rn; 1674 state->Reg[BITS (16, 19)] = op1 + Rn;
1675 break; 1675 break;
1676 } 1676 }
@@ -1682,7 +1682,7 @@ mainswitch:
1682 ARMword result = op1 + op2; 1682 ARMword result = op1 + op2;
1683 if (AddOverflow(op1, op2, result)) { 1683 if (AddOverflow(op1, op2, result)) {
1684 result = POS (result) ? 0x80000000 : 0x7fffffff; 1684 result = POS (result) ? 0x80000000 : 0x7fffffff;
1685 SETS; 1685 SETQ;
1686 } 1686 }
1687 state->Reg[BITS (12, 15)] = result; 1687 state->Reg[BITS (12, 15)] = result;
1688 break; 1688 break;
@@ -1795,7 +1795,7 @@ mainswitch:
1795 ARMword Rn = state->Reg[BITS(12, 15)]; 1795 ARMword Rn = state->Reg[BITS(12, 15)];
1796 1796
1797 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) 1797 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn)))
1798 SETS; 1798 SETQ;
1799 result += Rn; 1799 result += Rn;
1800 } 1800 }
1801 state->Reg[BITS (16, 19)] = (ARMword)result; 1801 state->Reg[BITS (16, 19)] = (ARMword)result;
@@ -1811,7 +1811,7 @@ mainswitch:
1811 if (SubOverflow 1811 if (SubOverflow
1812 (op1, op2, result)) { 1812 (op1, op2, result)) {
1813 result = POS (result) ? 0x80000000 : 0x7fffffff; 1813 result = POS (result) ? 0x80000000 : 0x7fffffff;
1814 SETS; 1814 SETQ;
1815 } 1815 }
1816 1816
1817 state->Reg[BITS (12, 15)] = result; 1817 state->Reg[BITS (12, 15)] = result;
@@ -1934,13 +1934,13 @@ mainswitch:
1934 1934
1935 if (AddOverflow 1935 if (AddOverflow
1936 (op2, op2, op2d)) { 1936 (op2, op2, op2d)) {
1937 SETS; 1937 SETQ;
1938 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 1938 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1939 } 1939 }
1940 1940
1941 result = op1 + op2d; 1941 result = op1 + op2d;
1942 if (AddOverflow(op1, op2d, result)) { 1942 if (AddOverflow(op1, op2d, result)) {
1943 SETS; 1943 SETQ;
1944 result = POS (result) ? 0x80000000 : 0x7fffffff; 1944 result = POS (result) ? 0x80000000 : 0x7fffffff;
1945 } 1945 }
1946 1946
@@ -2053,13 +2053,13 @@ mainswitch:
2053 ARMword result; 2053 ARMword result;
2054 2054
2055 if (AddOverflow(op2, op2, op2d)) { 2055 if (AddOverflow(op2, op2, op2d)) {
2056 SETS; 2056 SETQ;
2057 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 2057 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2058 } 2058 }
2059 2059
2060 result = op1 - op2d; 2060 result = op1 - op2d;
2061 if (SubOverflow(op1, op2d, result)) { 2061 if (SubOverflow(op1, op2d, result)) {
2062 SETS; 2062 SETQ;
2063 result = POS (result) ? 0x80000000 : 0x7fffffff; 2063 result = POS (result) ? 0x80000000 : 0x7fffffff;
2064 } 2064 }
2065 2065
@@ -6478,22 +6478,28 @@ L_stm_s_takeabort:
6478 const s16 rn_lo = (rn_val & 0xFFFF); 6478 const s16 rn_lo = (rn_val & 0xFFFF);
6479 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); 6479 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
6480 6480
6481 // SMUAD 6481 const u32 product1 = (rn_lo * rm_lo);
6482 if ((instr & 0xf0d0) == 0xf010) { 6482 const u32 product2 = (rn_hi * rm_hi);
6483 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi); 6483
6484 } 6484 // SMUAD and SMLAD
6485 // SMUSD 6485 if (BIT(6) == 0) {
6486 else if ((instr & 0xf0d0) == 0xf050) { 6486 state->Reg[rd_idx] = product1 + product2;
6487 state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi); 6487
6488 } 6488 if (BITS(12, 15) != 15) {
6489 // SMLAD 6489 state->Reg[rd_idx] += state->Reg[ra_idx];
6490 else if ((instr & 0xd0) == 0x10) { 6490 ARMul_AddOverflowQ(state, product1 + product2, state->Reg[ra_idx]);
6491 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx]; 6491 }
6492
6493 ARMul_AddOverflowQ(state, product1, product2);
6492 } 6494 }
6493 // SMLSD 6495 // SMUSD and SMLSD
6494 else { 6496 else {
6495 state->Reg[rd_idx] = ((rn_lo * rm_lo) - (rn_hi * rm_hi)) + (s32)state->Reg[ra_idx]; 6497 state->Reg[rd_idx] = product1 - product2;
6498
6499 if (BITS(12, 15) != 15)
6500 state->Reg[rd_idx] += state->Reg[ra_idx];
6496 } 6501 }
6502
6497 return 1; 6503 return 1;
6498 } 6504 }
6499 break; 6505 break;
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index b31c0ea24..6774f8a74 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -444,6 +444,14 @@ ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
444 ASSIGNV (AddOverflow (a, b, result)); 444 ASSIGNV (AddOverflow (a, b, result));
445} 445}
446 446
447/* Assigns the Q flag if the given result is considered an overflow from the addition of a and b */
448void ARMul_AddOverflowQ(ARMul_State* state, ARMword a, ARMword b)
449{
450 u32 result = a + b;
451 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
452 SETQ;
453}
454
447/* Assigns the C flag after an subtraction of a and b to give result. */ 455/* Assigns the C flag after an subtraction of a and b to give result. */
448 456
449void 457void
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index e1b286f0f..3ea14b5a3 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -602,6 +602,7 @@ extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
602extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); 602extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
603extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); 603extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
604extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); 604extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
605extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword);
605extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); 606extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
606extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); 607extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
607extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); 608extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);