diff options
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 68 |
1 files changed, 35 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: |