summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2014-12-29 14:53:04 -0500
committerGravatar bunnei2014-12-29 14:53:04 -0500
commit2d2aa2c0beae1bc7913e043444dadfab509afa8c (patch)
treef5428b3fd197cf3f7f00002b71cc7fdc754bd890
parentMerge pull request #363 from lioncash/label (diff)
parentdyncom: Implement QADD8/QSUB8 (diff)
downloadyuzu-2d2aa2c0beae1bc7913e043444dadfab509afa8c.tar.gz
yuzu-2d2aa2c0beae1bc7913e043444dadfab509afa8c.tar.xz
yuzu-2d2aa2c0beae1bc7913e043444dadfab509afa8c.zip
Merge pull request #361 from lioncash/moreqops
dyncom/armemu: Implement QADD8/QSUB8.
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp74
-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
4 files changed, 142 insertions, 65 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 8497630b0..f58b4731a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -2419,8 +2419,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
2419 return inst_base; 2419 return inst_base;
2420} 2420}
2421ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); } 2421ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); }
2422ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD8"); } 2422ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
2423ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2424{ 2423{
2425 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 2424 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2426 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 2425 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
@@ -2438,21 +2437,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2438 2437
2439 return inst_base; 2438 return inst_base;
2440} 2439}
2440ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2441{
2442 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2443}
2441ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) 2444ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
2442{ 2445{
2443 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2446 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2444} 2447}
2445ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); } 2448ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); }
2446ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } 2449ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }
2447ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); } 2450ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); }
2448ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB8"); } 2451ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
2452{
2453 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2454}
2449ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) 2455ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
2450{ 2456{
2451 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2457 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2452} 2458}
2453ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) 2459ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
2454{ 2460{
2455 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2461 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2456} 2462}
2457ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) 2463ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
2458{ 2464{
@@ -5777,55 +5783,60 @@ unsigned InterpreterMainLoop(ARMul_State* state)
5777 GOTO_NEXT_INST; 5783 GOTO_NEXT_INST;
5778 } 5784 }
5779 QADD_INST: 5785 QADD_INST:
5780 QADD8_INST:
5781 5786
5787 QADD8_INST:
5782 QADD16_INST: 5788 QADD16_INST:
5783 QADDSUBX_INST: 5789 QADDSUBX_INST:
5790 QSUB8_INST:
5784 QSUB16_INST: 5791 QSUB16_INST:
5785 QSUBADDX_INST: 5792 QSUBADDX_INST:
5786 { 5793 {
5787 INC_ICOUNTER; 5794 INC_ICOUNTER;
5788 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 5795 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5789 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 5796 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
5790 const s16 rm_lo = (RM & 0xFFFF); 5797 const u16 rm_lo = (RM & 0xFFFF);
5791 const s16 rm_hi = ((RM >> 16) & 0xFFFF); 5798 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
5792 const s16 rn_lo = (RN & 0xFFFF); 5799 const u16 rn_lo = (RN & 0xFFFF);
5793 const s16 rn_hi = ((RN >> 16) & 0xFFFF); 5800 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
5794 const u8 op2 = inst_cream->op2; 5801 const u8 op2 = inst_cream->op2;
5795 5802
5796 s32 lo_result = 0; 5803 u16 lo_result = 0;
5797 s32 hi_result = 0; 5804 u16 hi_result = 0;
5798 5805
5799 // QADD16 5806 // QADD16
5800 if (op2 == 0x00) { 5807 if (op2 == 0x00) {
5801 lo_result = (rn_lo + rm_lo); 5808 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5802 hi_result = (rn_hi + rm_hi); 5809 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5803 } 5810 }
5804 // QASX 5811 // QASX
5805 else if (op2 == 0x01) { 5812 else if (op2 == 0x01) {
5806 lo_result = (rn_lo - rm_hi); 5813 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5807 hi_result = (rn_hi + rm_lo); 5814 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5808 } 5815 }
5809 // QSAX 5816 // QSAX
5810 else if (op2 == 0x02) { 5817 else if (op2 == 0x02) {
5811 lo_result = (rn_lo + rm_hi); 5818 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5812 hi_result = (rn_hi - rm_lo); 5819 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5813 } 5820 }
5814 // QSUB16 5821 // QSUB16
5815 else if (op2 == 0x03) { 5822 else if (op2 == 0x03) {
5816 lo_result = (rn_lo - rm_lo); 5823 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5817 hi_result = (rn_hi - rm_hi); 5824 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5825 }
5826 // QADD8
5827 else if (op2 == 0x04) {
5828 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5829 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5830 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5831 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5832 }
5833 // QSUB8
5834 else if (op2 == 0x07) {
5835 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5836 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5837 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5838 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5818 } 5839 }
5819
5820 if (lo_result > 0x7FFF)
5821 lo_result = 0x7FFF;
5822 else if (lo_result < -0x8000)
5823 lo_result = -0x8000;
5824
5825 if (hi_result > 0x7FFF)
5826 hi_result = 0x7FFF;
5827 else if (hi_result < -0x8000)
5828 hi_result = -0x8000;
5829 5840
5830 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 5841 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5831 } 5842 }
@@ -5839,7 +5850,6 @@ unsigned InterpreterMainLoop(ARMul_State* state)
5839 QDADD_INST: 5850 QDADD_INST:
5840 QDSUB_INST: 5851 QDSUB_INST:
5841 QSUB_INST: 5852 QSUB_INST:
5842 QSUB8_INST:
5843 REV_INST: 5853 REV_INST:
5844 { 5854 {
5845 INC_ICOUNTER; 5855 INC_ICOUNTER;
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);