diff options
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 101 |
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 |