summaryrefslogtreecommitdiff
path: root/src/core/arm/interpreter/armemu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
-rw-r--r--src/core/arm/interpreter/armemu.cpp101
1 files changed, 87 insertions, 14 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 7a319b635..610e04f10 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5824,9 +5824,9 @@ L_stm_s_takeabort:
5824 case 0x3f: 5824 case 0x3f:
5825 printf ("Unhandled v6 insn: rbit\n"); 5825 printf ("Unhandled v6 insn: rbit\n");
5826 break; 5826 break;
5827 case 0x61: // SSUB16, SADD16, SSAX, and SASX 5827 case 0x61: // SADD16, SASX, SSAX, and SSUB16
5828 if ((instr & 0xFF0) == 0xf70 || (instr & 0xFF0) == 0xf10 || 5828 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5829 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf30) 5829 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5830 { 5830 {
5831 const u8 rd_idx = BITS(12, 15); 5831 const u8 rd_idx = BITS(12, 15);
5832 const u8 rm_idx = BITS(0, 3); 5832 const u8 rm_idx = BITS(0, 3);
@@ -5839,25 +5839,25 @@ L_stm_s_takeabort:
5839 s32 lo_result; 5839 s32 lo_result;
5840 s32 hi_result; 5840 s32 hi_result;
5841 5841
5842 // SSUB16
5843 if ((instr & 0xFF0) == 0xf70) {
5844 lo_result = (rn_lo - rm_lo);
5845 hi_result = (rn_hi - rm_hi);
5846 }
5847 // SADD16 5842 // SADD16
5848 else if ((instr & 0xFF0) == 0xf10) { 5843 if ((instr & 0xFF0) == 0xf10) {
5849 lo_result = (rn_lo + rm_lo); 5844 lo_result = (rn_lo + rm_lo);
5850 hi_result = (rn_hi + rm_hi); 5845 hi_result = (rn_hi + rm_hi);
5851 } 5846 }
5847 // SASX
5848 else if ((instr & 0xFF0) == 0xf30) {
5849 lo_result = (rn_lo - rm_hi);
5850 hi_result = (rn_hi + rm_lo);
5851 }
5852 // SSAX 5852 // SSAX
5853 else if ((instr & 0xFF0) == 0xf50) { 5853 else if ((instr & 0xFF0) == 0xf50) {
5854 lo_result = (rn_lo + rm_hi); 5854 lo_result = (rn_lo + rm_hi);
5855 hi_result = (rn_hi - rm_lo); 5855 hi_result = (rn_hi - rm_lo);
5856 } 5856 }
5857 // SASX 5857 // SSUB16
5858 else { 5858 else {
5859 lo_result = (rn_lo - rm_hi); 5859 lo_result = (rn_lo - rm_lo);
5860 hi_result = (rn_hi + rm_lo); 5860 hi_result = (rn_hi - rm_hi);
5861 } 5861 }
5862 5862
5863 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 5863 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
@@ -5878,8 +5878,81 @@ L_stm_s_takeabort:
5878 state->Cpsr &= ~(1 << 19); 5878 state->Cpsr &= ~(1 << 19);
5879 } 5879 }
5880 return 1; 5880 return 1;
5881 } else { 5881 }
5882 printf("Unhandled v6 insn: %08x", BITS(20, 27)); 5882 // SADD8/SSUB8
5883 else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0)
5884 {
5885 const u8 rd_idx = BITS(12, 15);
5886 const u8 rm_idx = BITS(0, 3);
5887 const u8 rn_idx = BITS(16, 19);
5888 const u32 rm_val = state->Reg[rm_idx];
5889 const u32 rn_val = state->Reg[rn_idx];
5890
5891 u8 lo_val1;
5892 u8 lo_val2;
5893 u8 hi_val1;
5894 u8 hi_val2;
5895
5896 // SADD8
5897 if ((instr & 0xFF0) == 0xf90) {
5898 lo_val1 = (u8)((rn_val & 0xFF) + (rm_val & 0xFF));
5899 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF));
5900 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF));
5901 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));
5902
5903 if (lo_val1 & 0x80)
5904 state->Cpsr |= (1 << 16);
5905 else
5906 state->Cpsr &= ~(1 << 16);
5907
5908 if (lo_val2 & 0x80)
5909 state->Cpsr |= (1 << 17);
5910 else
5911 state->Cpsr &= ~(1 << 17);
5912
5913 if (hi_val1 & 0x80)
5914 state->Cpsr |= (1 << 18);
5915 else
5916 state->Cpsr &= ~(1 << 18);
5917
5918 if (hi_val2 & 0x80)
5919 state->Cpsr |= (1 << 19);
5920 else
5921 state->Cpsr &= ~(1 << 19);
5922 }
5923 // SSUB8
5924 else {
5925 lo_val1 = (u8)((rn_val & 0xFF) - (rm_val & 0xFF));
5926 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF));
5927 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF));
5928 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
5929
5930 if (!(lo_val1 & 0x80))
5931 state->Cpsr |= (1 << 16);
5932 else
5933 state->Cpsr &= ~(1 << 16);
5934
5935 if (!(lo_val2 & 0x80))
5936 state->Cpsr |= (1 << 17);
5937 else
5938 state->Cpsr &= ~(1 << 17);
5939
5940 if (!(hi_val1 & 0x80))
5941 state->Cpsr |= (1 << 18);
5942 else
5943 state->Cpsr &= ~(1 << 18);
5944
5945 if (!(hi_val2 & 0x80))
5946 state->Cpsr |= (1 << 19);
5947 else
5948 state->Cpsr &= ~(1 << 19);
5949 }
5950
5951 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24);
5952 return 1;
5953 }
5954 else {
5955 printf("Unhandled v6 insn: %08x", instr);
5883 } 5956 }
5884 break; 5957 break;
5885 case 0x62: // QADD16, QASX, QSAX, and QSUB16 5958 case 0x62: // QADD16, QASX, QSAX, and QSUB16