diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index e3a8b1f6e..30f68f47a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -2053,7 +2053,37 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
 
     return inst_base;
 }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QADD"); }
+
+ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)
+{
+    arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+    generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+    inst_base->cond     = BITS(inst, 28, 31);
+    inst_base->idx      = index;
+    inst_base->br       = NON_BRANCH;
+    inst_base->load_r15 = 0;
+
+    inst_cream->op1 = BITS(inst, 21, 22);
+    inst_cream->Rm  = BITS(inst, 0, 3);
+    inst_cream->Rn  = BITS(inst, 16, 19);
+    inst_cream->Rd  = BITS(inst, 12, 15);
+
+    return inst_base;
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)
+{
+    return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)
+{
+    return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)
+{
+    return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+
 ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
 {
     arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
@@ -2080,9 +2110,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
 {
     return INTERPRETER_TRANSLATE(qadd8)(inst, index);
 }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDADD"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QSUB"); }
 ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
 {
     return INTERPRETER_TRANSLATE(qadd8)(inst, index);
@@ -5042,6 +5069,78 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
     }
 
     QADD_INST:
+    QDADD_INST:
+    QDSUB_INST:
+    QSUB_INST:
+    {
+        if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+            generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+            const u8 op1 = inst_cream->op1;
+            const u32 rm_val = RM;
+            const u32 rn_val = RN;
+
+            u32 result = 0;
+
+            // QADD
+            if (op1 == 0x00) {
+                result = rm_val + rn_val;
+
+                if (AddOverflow(rm_val, rn_val, result)) {
+                    result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+            }
+            // QSUB
+            else if (op1 == 0x01) {
+                result = rm_val - rn_val;
+
+                if (SubOverflow(rm_val, rn_val, result)) {
+                    result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+            }
+            // QDADD
+            else if (op1 == 0x02) {
+                u32 mul = (rn_val * 2);
+
+                if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
+                    mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+
+                result = mul + rm_val;
+
+                if (AddOverflow(rm_val, mul, result)) {
+                    result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+            }
+            // QDSUB
+            else if (op1 == 0x03) {
+                u32 mul = (rn_val * 2);
+
+                if (AddOverflow(rn_val, rn_val, mul)) {
+                    mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+
+                result = rm_val - mul;
+
+                if (SubOverflow(rm_val, mul, result)) {
+                    result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
+                    cpu->Cpsr |= (1 << 27);
+                }
+            }
+
+            RD = result;
+        }
+
+        cpu->Reg[15] += GET_INST_SIZE(cpu);
+        INC_PC(sizeof(generic_arm_inst));
+        FETCH_INST;
+        GOTO_NEXT_INST;
+    }
+
     QADD8_INST:
     QADD16_INST:
     QADDSUBX_INST:
@@ -5104,10 +5203,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
         GOTO_NEXT_INST;
     }
 
-    QDADD_INST:
-    QDSUB_INST:
-    QSUB_INST:
-
     REV_INST:
     REV16_INST:
     REVSH_INST:
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index eec34143e..68ac2a0ce 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -418,22 +418,18 @@ ARMul_NegZero (ARMul_State * state, ARMword result)
     }
 }
 
-/* Compute whether an addition of A and B, giving RESULT, overflowed.  */
-
-int
-AddOverflow (ARMword a, ARMword b, ARMword result)
+// Compute whether an addition of A and B, giving RESULT, overflowed.
+bool AddOverflow(ARMword a, ARMword b, ARMword result)
 {
-    return ((NEG (a) && NEG (b) && POS (result))
-            || (POS (a) && POS (b) && NEG (result)));
+    return ((NEG(a) && NEG(b) && POS(result)) ||
+            (POS(a) && POS(b) && NEG(result)));
 }
 
-/* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */
-
-int
-SubOverflow (ARMword a, ARMword b, ARMword result)
+// Compute whether a subtraction of A and B, giving RESULT, overflowed.
+bool SubOverflow(ARMword a, ARMword b, ARMword result)
 {
-    return ((NEG (a) && POS (b) && POS (result))
-            || (POS (a) && NEG (b) && NEG (result)));
+    return ((NEG(a) && POS(b) && POS(result)) ||
+            (POS(a) && NEG(b) && NEG(result)));
 }
 
 /* Assigns the C flag after an addition of a and b to give result.  */
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index c2c78cd5a..3100d7adc 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -70,6 +70,9 @@
 #define DATACACHE  1
 #define INSTCACHE  2
 
+#define POS(i) ( (~(i)) >> 31 )
+#define NEG(i) ( (i) >> 31 )
+
 #ifndef __STDC__
 typedef char *VoidStar;
 #endif
@@ -783,6 +786,8 @@ RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\
 //#define PXA250      0x69052903
 // 0x69052903;  //PXA250 B1 from intel 278522-001.pdf
 
+extern bool AddOverflow(ARMword, ARMword, ARMword);
+extern bool SubOverflow(ARMword, ARMword, ARMword);
 
 extern void ARMul_UndefInstr(ARMul_State*, ARMword);
 extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword);
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index e1b286f0f..1dfcc635a 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -42,9 +42,6 @@
 #define R15FBIT (1L << 26)
 #define R15IFBITS (3L << 26)
 
-#define POS(i) ( (~(i)) >> 31 )
-#define NEG(i) ( (i) >> 31 )
-
 #ifdef MODET			/* Thumb support.  */
 /* ??? This bit is actually in the low order bit of the PC in the hardware.
    It isn't clear if the simulator needs to model that or not.  */
@@ -561,8 +558,7 @@ tdstate;
 
 /* Prototypes for exported functions.  */
 extern unsigned ARMul_NthReg (ARMword, unsigned);
-extern int AddOverflow (ARMword, ARMword, ARMword);
-extern int SubOverflow (ARMword, ARMword, ARMword);
+
 /* Prototypes for exported functions.  */
 #ifdef __cplusplus
  extern "C" {