summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp68
-rw-r--r--src/core/arm/interpreter/armsupp.cpp60
-rw-r--r--src/core/arm/skyeye_common/armdefs.h5
3 files changed, 100 insertions, 33 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index f0d349de7..b9c2aa6c2 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5948,56 +5948,58 @@ L_stm_s_takeabort:
5948 printf("Unhandled v6 insn: %08x", instr); 5948 printf("Unhandled v6 insn: %08x", instr);
5949 } 5949 }
5950 break; 5950 break;
5951 case 0x62: // QADD16, QASX, QSAX, and QSUB16 5951 case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8
5952 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5953 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5954 { 5952 {
5953 const u8 op2 = BITS(5, 7);
5954
5955 const u8 rd_idx = BITS(12, 15); 5955 const u8 rd_idx = BITS(12, 15);
5956 const u8 rn_idx = BITS(16, 19); 5956 const u8 rn_idx = BITS(16, 19);
5957 const u8 rm_idx = BITS(0, 3); 5957 const u8 rm_idx = BITS(0, 3);
5958 const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); 5958 const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
5959 const s16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); 5959 const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
5960 const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); 5960 const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
5961 const s16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); 5961 const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
5962 5962
5963 s32 lo_result; 5963 u16 lo_result = 0;
5964 s32 hi_result; 5964 u16 hi_result = 0;
5965 5965
5966 // QADD16 5966 // QADD16
5967 if ((instr & 0xFF0) == 0xf10) { 5967 if (op2 == 0x00) {
5968 lo_result = (rn_lo + rm_lo); 5968 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5969 hi_result = (rn_hi + rm_hi); 5969 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5970 } 5970 }
5971 // QASX 5971 // QASX
5972 else if ((instr & 0xFF0) == 0xf30) { 5972 else if (op2 == 0x01) {
5973 lo_result = (rn_lo - rm_hi); 5973 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5974 hi_result = (rn_hi + rm_lo); 5974 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5975 } 5975 }
5976 // QSAX 5976 // QSAX
5977 else if ((instr & 0xFF0) == 0xf50) { 5977 else if (op2 == 0x02) {
5978 lo_result = (rn_lo + rm_hi); 5978 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5979 hi_result = (rn_hi - rm_lo); 5979 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5980 } 5980 }
5981 // QSUB16 5981 // QSUB16
5982 else { 5982 else if (op2 == 0x03) {
5983 lo_result = (rn_lo - rm_lo); 5983 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5984 hi_result = (rn_hi - rm_hi); 5984 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5985 }
5986 // QADD8
5987 else if (op2 == 0x04) {
5988 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5989 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5990 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5991 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5992 }
5993 // QSUB8
5994 else if (op2 == 0x07) {
5995 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5996 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5997 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5998 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5985 } 5999 }
5986
5987 if (lo_result > 0x7FFF)
5988 lo_result = 0x7FFF;
5989 else if (lo_result < -0x8000)
5990 lo_result = -0x8000;
5991
5992 if (hi_result > 0x7FFF)
5993 hi_result = 0x7FFF;
5994 else if (hi_result < -0x8000)
5995 hi_result = -0x8000;
5996 6000
5997 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 6001 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5998 return 1; 6002 return 1;
5999 } else {
6000 printf("Unhandled v6 insn: %08x", BITS(20, 27));
6001 } 6003 }
6002 break; 6004 break;
6003 case 0x63: 6005 case 0x63:
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 8f158e2c8..8b3661c8f 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -478,6 +478,66 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
478 ASSIGNV (SubOverflow (a, b, result)); 478 ASSIGNV (SubOverflow (a, b, result));
479} 479}
480 480
481/* 8-bit signed saturated addition */
482u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
483{
484 u8 result = left + right;
485
486 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
487 if (left & 0x80)
488 result = 0x80;
489 else
490 result = 0x7F;
491 }
492
493 return result;
494}
495
496/* 8-bit signed saturated subtraction */
497u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
498{
499 u8 result = left - right;
500
501 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
502 if (left & 0x80)
503 result = 0x80;
504 else
505 result = 0x7F;
506 }
507
508 return result;
509}
510
511/* 16-bit signed saturated addition */
512u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
513{
514 u16 result = left + right;
515
516 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
517 if (left & 0x8000)
518 result = 0x8000;
519 else
520 result = 0x7FFF;
521 }
522
523 return result;
524}
525
526/* 16-bit signed saturated subtraction */
527u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
528{
529 u16 result = left - right;
530
531 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
532 if (left & 0x8000)
533 result = 0x8000;
534 else
535 result = 0x7FFF;
536 }
537
538 return result;
539}
540
481/* 8-bit unsigned saturated addition */ 541/* 8-bit unsigned saturated addition */
482u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) 542u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
483{ 543{
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index c7509fcb2..0f2bcbdb1 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -790,6 +790,11 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
790extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); 790extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
791extern void ARMul_SelectProcessor(ARMul_State*, unsigned); 791extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
792 792
793extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
794extern u8 ARMul_SignedSaturatedSub8(u8, u8);
795extern u16 ARMul_SignedSaturatedAdd16(u16, u16);
796extern u16 ARMul_SignedSaturatedSub16(u16, u16);
797
793extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); 798extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
794extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); 799extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
795extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); 800extern u8 ARMul_UnsignedSaturatedSub8(u8, u8);