diff options
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 1412 |
1 files changed, 903 insertions, 509 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 73223874e..b9c2aa6c2 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -949,7 +949,7 @@ ARMul_Emulate26 (ARMul_State * state) | |||
| 949 | //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp); | 949 | //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp); |
| 950 | 950 | ||
| 951 | if (armOp == 0xDEADC0DE) { | 951 | if (armOp == 0xDEADC0DE) { |
| 952 | DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc); | 952 | LOG_ERROR(Core_ARM11, "Failed to decode thumb opcode %04X at %08X", instr, pc); |
| 953 | } | 953 | } |
| 954 | 954 | ||
| 955 | instr = armOp; | 955 | instr = armOp; |
| @@ -1166,7 +1166,7 @@ mainswitch: | |||
| 1166 | else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) { | 1166 | else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) { |
| 1167 | //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) | 1167 | //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) |
| 1168 | unsigned msb ,tmp_rn, tmp_rd, dst; | 1168 | unsigned msb ,tmp_rn, tmp_rd, dst; |
| 1169 | msb = tmp_rd = tmp_rn = dst = 0; | 1169 | tmp_rd = tmp_rn = dst = 0; |
| 1170 | Rd = BITS(12, 15); | 1170 | Rd = BITS(12, 15); |
| 1171 | Rn = BITS(0, 3); | 1171 | Rn = BITS(0, 3); |
| 1172 | lsb = BITS(7, 11); | 1172 | lsb = BITS(7, 11); |
| @@ -1356,7 +1356,13 @@ mainswitch: | |||
| 1356 | } | 1356 | } |
| 1357 | break; | 1357 | break; |
| 1358 | 1358 | ||
| 1359 | case 0x04: /* SUB reg */ | 1359 | case 0x04: /* SUB reg */ |
| 1360 | // Signifies UMAAL | ||
| 1361 | if (state->is_v6 && BITS(4, 7) == 0x09) { | ||
| 1362 | if (handle_v6_insn(state, instr)) | ||
| 1363 | break; | ||
| 1364 | } | ||
| 1365 | |||
| 1360 | #ifdef MODET | 1366 | #ifdef MODET |
| 1361 | if (BITS (4, 7) == 0xB) { | 1367 | if (BITS (4, 7) == 0xB) { |
| 1362 | /* STRH immediate offset, no write-back, down, post indexed. */ | 1368 | /* STRH immediate offset, no write-back, down, post indexed. */ |
| @@ -1664,7 +1670,7 @@ mainswitch: | |||
| 1664 | op1 *= op2; | 1670 | op1 *= op2; |
| 1665 | //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); | 1671 | //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); |
| 1666 | if (AddOverflow(op1, Rn, op1 + Rn)) | 1672 | if (AddOverflow(op1, Rn, op1 + Rn)) |
| 1667 | SETS; | 1673 | SETQ; |
| 1668 | state->Reg[BITS (16, 19)] = op1 + Rn; | 1674 | state->Reg[BITS (16, 19)] = op1 + Rn; |
| 1669 | break; | 1675 | break; |
| 1670 | } | 1676 | } |
| @@ -1676,7 +1682,7 @@ mainswitch: | |||
| 1676 | ARMword result = op1 + op2; | 1682 | ARMword result = op1 + op2; |
| 1677 | if (AddOverflow(op1, op2, result)) { | 1683 | if (AddOverflow(op1, op2, result)) { |
| 1678 | result = POS (result) ? 0x80000000 : 0x7fffffff; | 1684 | result = POS (result) ? 0x80000000 : 0x7fffffff; |
| 1679 | SETS; | 1685 | SETQ; |
| 1680 | } | 1686 | } |
| 1681 | state->Reg[BITS (12, 15)] = result; | 1687 | state->Reg[BITS (12, 15)] = result; |
| 1682 | break; | 1688 | break; |
| @@ -1718,7 +1724,7 @@ mainswitch: | |||
| 1718 | TAKEABORT; | 1724 | TAKEABORT; |
| 1719 | } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */ | 1725 | } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */ |
| 1720 | UNDEF_MRSPC; | 1726 | UNDEF_MRSPC; |
| 1721 | DEST = ECC | EINT | EMODE; | 1727 | DEST = ARMul_GetCPSR(state); |
| 1722 | } else { | 1728 | } else { |
| 1723 | UNDEF_Test; | 1729 | UNDEF_Test; |
| 1724 | } | 1730 | } |
| @@ -1737,7 +1743,7 @@ mainswitch: | |||
| 1737 | //chy 2006-02-15 if in user mode, can not set cpsr 0:23 | 1743 | //chy 2006-02-15 if in user mode, can not set cpsr 0:23 |
| 1738 | //from p165 of ARMARM book | 1744 | //from p165 of ARMARM book |
| 1739 | state->Cpsr = GETSPSR (state->Bank); | 1745 | state->Cpsr = GETSPSR (state->Bank); |
| 1740 | //ARMul_CPSRAltered (state); | 1746 | ARMul_CPSRAltered (state); |
| 1741 | #else | 1747 | #else |
| 1742 | rhs = DPRegRHS; | 1748 | rhs = DPRegRHS; |
| 1743 | temp = LHS & rhs; | 1749 | temp = LHS & rhs; |
| @@ -1789,7 +1795,7 @@ mainswitch: | |||
| 1789 | ARMword Rn = state->Reg[BITS(12, 15)]; | 1795 | ARMword Rn = state->Reg[BITS(12, 15)]; |
| 1790 | 1796 | ||
| 1791 | if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) | 1797 | if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) |
| 1792 | SETS; | 1798 | SETQ; |
| 1793 | result += Rn; | 1799 | result += Rn; |
| 1794 | } | 1800 | } |
| 1795 | state->Reg[BITS (16, 19)] = (ARMword)result; | 1801 | state->Reg[BITS (16, 19)] = (ARMword)result; |
| @@ -1805,7 +1811,7 @@ mainswitch: | |||
| 1805 | if (SubOverflow | 1811 | if (SubOverflow |
| 1806 | (op1, op2, result)) { | 1812 | (op1, op2, result)) { |
| 1807 | result = POS (result) ? 0x80000000 : 0x7fffffff; | 1813 | result = POS (result) ? 0x80000000 : 0x7fffffff; |
| 1808 | SETS; | 1814 | SETQ; |
| 1809 | } | 1815 | } |
| 1810 | 1816 | ||
| 1811 | state->Reg[BITS (12, 15)] = result; | 1817 | state->Reg[BITS (12, 15)] = result; |
| @@ -1877,7 +1883,7 @@ mainswitch: | |||
| 1877 | /* TEQP reg */ | 1883 | /* TEQP reg */ |
| 1878 | #ifdef MODE32 | 1884 | #ifdef MODE32 |
| 1879 | state->Cpsr = GETSPSR (state->Bank); | 1885 | state->Cpsr = GETSPSR (state->Bank); |
| 1880 | //ARMul_CPSRAltered (state); | 1886 | ARMul_CPSRAltered (state); |
| 1881 | #else | 1887 | #else |
| 1882 | rhs = DPRegRHS; | 1888 | rhs = DPRegRHS; |
| 1883 | temp = LHS ^ rhs; | 1889 | temp = LHS ^ rhs; |
| @@ -1928,13 +1934,13 @@ mainswitch: | |||
| 1928 | 1934 | ||
| 1929 | if (AddOverflow | 1935 | if (AddOverflow |
| 1930 | (op2, op2, op2d)) { | 1936 | (op2, op2, op2d)) { |
| 1931 | SETS; | 1937 | SETQ; |
| 1932 | op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; | 1938 | op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; |
| 1933 | } | 1939 | } |
| 1934 | 1940 | ||
| 1935 | result = op1 + op2d; | 1941 | result = op1 + op2d; |
| 1936 | if (AddOverflow(op1, op2d, result)) { | 1942 | if (AddOverflow(op1, op2d, result)) { |
| 1937 | SETS; | 1943 | SETQ; |
| 1938 | result = POS (result) ? 0x80000000 : 0x7fffffff; | 1944 | result = POS (result) ? 0x80000000 : 0x7fffffff; |
| 1939 | } | 1945 | } |
| 1940 | 1946 | ||
| @@ -1993,7 +1999,7 @@ mainswitch: | |||
| 1993 | /* CMPP reg. */ | 1999 | /* CMPP reg. */ |
| 1994 | #ifdef MODE32 | 2000 | #ifdef MODE32 |
| 1995 | state->Cpsr = GETSPSR (state->Bank); | 2001 | state->Cpsr = GETSPSR (state->Bank); |
| 1996 | //ARMul_CPSRAltered (state); | 2002 | ARMul_CPSRAltered (state); |
| 1997 | #else | 2003 | #else |
| 1998 | rhs = DPRegRHS; | 2004 | rhs = DPRegRHS; |
| 1999 | temp = LHS - rhs; | 2005 | temp = LHS - rhs; |
| @@ -2047,13 +2053,13 @@ mainswitch: | |||
| 2047 | ARMword result; | 2053 | ARMword result; |
| 2048 | 2054 | ||
| 2049 | if (AddOverflow(op2, op2, op2d)) { | 2055 | if (AddOverflow(op2, op2, op2d)) { |
| 2050 | SETS; | 2056 | SETQ; |
| 2051 | op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; | 2057 | op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; |
| 2052 | } | 2058 | } |
| 2053 | 2059 | ||
| 2054 | result = op1 - op2d; | 2060 | result = op1 - op2d; |
| 2055 | if (SubOverflow(op1, op2d, result)) { | 2061 | if (SubOverflow(op1, op2d, result)) { |
| 2056 | SETS; | 2062 | SETQ; |
| 2057 | result = POS (result) ? 0x80000000 : 0x7fffffff; | 2063 | result = POS (result) ? 0x80000000 : 0x7fffffff; |
| 2058 | } | 2064 | } |
| 2059 | 2065 | ||
| @@ -2112,7 +2118,7 @@ mainswitch: | |||
| 2112 | if (DESTReg == 15) { | 2118 | if (DESTReg == 15) { |
| 2113 | #ifdef MODE32 | 2119 | #ifdef MODE32 |
| 2114 | state->Cpsr = GETSPSR (state->Bank); | 2120 | state->Cpsr = GETSPSR (state->Bank); |
| 2115 | //ARMul_CPSRAltered (state); | 2121 | ARMul_CPSRAltered (state); |
| 2116 | #else | 2122 | #else |
| 2117 | rhs = DPRegRHS; | 2123 | rhs = DPRegRHS; |
| 2118 | temp = LHS + rhs; | 2124 | temp = LHS + rhs; |
| @@ -2200,17 +2206,57 @@ mainswitch: | |||
| 2200 | Handle_Store_Double (state, instr); | 2206 | Handle_Store_Double (state, instr); |
| 2201 | break; | 2207 | break; |
| 2202 | } | 2208 | } |
| 2209 | if (BITS(4, 11) == 0xF9) { //strexd | ||
| 2210 | u32 l = LHSReg; | ||
| 2211 | |||
| 2212 | bool enter = false; | ||
| 2213 | |||
| 2214 | if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr)&& | ||
| 2215 | state->currentexvald == (u32)ARMul_ReadWord(state, state->currentexaddr + 4)) | ||
| 2216 | enter = true; | ||
| 2217 | |||
| 2218 | |||
| 2219 | //todo bug this and STREXD and LDREXD http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDGJGGC.html | ||
| 2220 | |||
| 2221 | |||
| 2222 | if (enter) { | ||
| 2223 | ARMul_StoreWordN(state, LHS, state->Reg[RHSReg]); | ||
| 2224 | ARMul_StoreWordN(state,LHS + 4 , state->Reg[RHSReg + 1]); | ||
| 2225 | state->Reg[DESTReg] = 0; | ||
| 2226 | } else { | ||
| 2227 | state->Reg[DESTReg] = 1; | ||
| 2228 | } | ||
| 2229 | |||
| 2230 | break; | ||
| 2231 | } | ||
| 2203 | #endif | 2232 | #endif |
| 2204 | dest = DPRegRHS; | 2233 | dest = DPRegRHS; |
| 2205 | WRITEDEST (dest); | 2234 | WRITEDEST (dest); |
| 2206 | break; | 2235 | break; |
| 2207 | 2236 | ||
| 2208 | case 0x1b: /* MOVS reg */ | 2237 | case 0x1B: /* MOVS reg */ |
| 2209 | #ifdef MODET | 2238 | #ifdef MODET |
| 2239 | /* ldrexd ichfly */ | ||
| 2240 | if (BITS(0, 11) == 0xF9F) { //strexd | ||
| 2241 | lhs = LHS; | ||
| 2242 | |||
| 2243 | state->currentexaddr = lhs; | ||
| 2244 | state->currentexval = (u32)ARMul_ReadWord(state, lhs); | ||
| 2245 | state->currentexvald = (u32)ARMul_ReadWord(state, lhs + 4); | ||
| 2246 | |||
| 2247 | state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs); | ||
| 2248 | state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs + 4); | ||
| 2249 | break; | ||
| 2250 | } | ||
| 2251 | |||
| 2210 | if ((BITS (4, 11) & 0xF9) == 0x9) | 2252 | if ((BITS (4, 11) & 0xF9) == 0x9) |
| 2211 | /* LDR register offset, write-back, up, pre indexed. */ | 2253 | /* LDR register offset, write-back, up, pre indexed. */ |
| 2212 | LHPREUPWB (); | 2254 | LHPREUPWB (); |
| 2213 | /* Continue with remaining instruction decoding. */ | 2255 | /* Continue with remaining instruction decoding. */ |
| 2256 | |||
| 2257 | |||
| 2258 | |||
| 2259 | |||
| 2214 | #endif | 2260 | #endif |
| 2215 | dest = DPSRegRHS; | 2261 | dest = DPSRegRHS; |
| 2216 | WRITESDEST (dest); | 2262 | WRITESDEST (dest); |
| @@ -2297,12 +2343,12 @@ mainswitch: | |||
| 2297 | if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true; | 2343 | if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true; |
| 2298 | 2344 | ||
| 2299 | 2345 | ||
| 2300 | ARMul_StoreHalfWord(state, lhs, RHS); | ||
| 2301 | //StoreWord(state, lhs, RHS) | 2346 | //StoreWord(state, lhs, RHS) |
| 2302 | if (state->Aborted) { | 2347 | if (state->Aborted) { |
| 2303 | TAKEABORT; | 2348 | TAKEABORT; |
| 2304 | } | 2349 | } |
| 2305 | if (enter) { | 2350 | if (enter) { |
| 2351 | ARMul_StoreHalfWord(state, lhs, RHS); | ||
| 2306 | state->Reg[DESTReg] = 0; | 2352 | state->Reg[DESTReg] = 0; |
| 2307 | } else { | 2353 | } else { |
| 2308 | state->Reg[DESTReg] = 1; | 2354 | state->Reg[DESTReg] = 1; |
| @@ -2520,7 +2566,7 @@ mainswitch: | |||
| 2520 | /* TSTP immed. */ | 2566 | /* TSTP immed. */ |
| 2521 | #ifdef MODE32 | 2567 | #ifdef MODE32 |
| 2522 | state->Cpsr = GETSPSR (state->Bank); | 2568 | state->Cpsr = GETSPSR (state->Bank); |
| 2523 | //ARMul_CPSRAltered (state); | 2569 | ARMul_CPSRAltered (state); |
| 2524 | #else | 2570 | #else |
| 2525 | temp = LHS & DPImmRHS; | 2571 | temp = LHS & DPImmRHS; |
| 2526 | SETR15PSR (temp); | 2572 | SETR15PSR (temp); |
| @@ -2547,7 +2593,7 @@ mainswitch: | |||
| 2547 | /* TEQP immed. */ | 2593 | /* TEQP immed. */ |
| 2548 | #ifdef MODE32 | 2594 | #ifdef MODE32 |
| 2549 | state->Cpsr = GETSPSR (state->Bank); | 2595 | state->Cpsr = GETSPSR (state->Bank); |
| 2550 | //ARMul_CPSRAltered (state); | 2596 | ARMul_CPSRAltered (state); |
| 2551 | #else | 2597 | #else |
| 2552 | temp = LHS ^ DPImmRHS; | 2598 | temp = LHS ^ DPImmRHS; |
| 2553 | SETR15PSR (temp); | 2599 | SETR15PSR (temp); |
| @@ -2568,7 +2614,7 @@ mainswitch: | |||
| 2568 | /* CMPP immed. */ | 2614 | /* CMPP immed. */ |
| 2569 | #ifdef MODE32 | 2615 | #ifdef MODE32 |
| 2570 | state->Cpsr = GETSPSR (state->Bank); | 2616 | state->Cpsr = GETSPSR (state->Bank); |
| 2571 | //ARMul_CPSRAltered (state); | 2617 | ARMul_CPSRAltered (state); |
| 2572 | #else | 2618 | #else |
| 2573 | temp = LHS - DPImmRHS; | 2619 | temp = LHS - DPImmRHS; |
| 2574 | SETR15PSR (temp); | 2620 | SETR15PSR (temp); |
| @@ -2604,7 +2650,7 @@ mainswitch: | |||
| 2604 | /* CMNP immed. */ | 2650 | /* CMNP immed. */ |
| 2605 | #ifdef MODE32 | 2651 | #ifdef MODE32 |
| 2606 | state->Cpsr = GETSPSR (state->Bank); | 2652 | state->Cpsr = GETSPSR (state->Bank); |
| 2607 | //ARMul_CPSRAltered (state); | 2653 | ARMul_CPSRAltered (state); |
| 2608 | #else | 2654 | #else |
| 2609 | temp = LHS + DPImmRHS; | 2655 | temp = LHS + DPImmRHS; |
| 2610 | SETR15PSR (temp); | 2656 | SETR15PSR (temp); |
| @@ -3054,27 +3100,21 @@ mainswitch: | |||
| 3054 | break; | 3100 | break; |
| 3055 | 3101 | ||
| 3056 | case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ | 3102 | case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ |
| 3057 | //ichfly PKHBT PKHTB todo check this | 3103 | if ((instr & 0x70) == 0x10) { //pkhbt |
| 3058 | if ((instr & 0x70) == 0x10) //pkhbt | ||
| 3059 | { | ||
| 3060 | u8 idest = BITS(12, 15); | 3104 | u8 idest = BITS(12, 15); |
| 3061 | u8 rfis = BITS(16, 19); | 3105 | u8 rfis = BITS(16, 19); |
| 3062 | u8 rlast = BITS(0, 3); | 3106 | u8 rlast = BITS(0, 3); |
| 3063 | u8 ishi = BITS(7,11); | 3107 | u8 ishi = BITS(7,11); |
| 3064 | state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); | 3108 | state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); |
| 3065 | break; | 3109 | break; |
| 3066 | } | 3110 | } else if ((instr & 0x70) == 0x50) { //pkhtb |
| 3067 | else if ((instr & 0x70) == 0x50)//pkhtb | 3111 | u8 rd_idx = BITS(12, 15); |
| 3068 | { | 3112 | u8 rn_idx = BITS(16, 19); |
| 3069 | u8 idest = BITS(12, 15); | 3113 | u8 rm_idx = BITS(0, 3); |
| 3070 | u8 rfis = BITS(16, 19); | 3114 | u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31; |
| 3071 | u8 rlast = BITS(0, 3); | 3115 | state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000); |
| 3072 | u8 ishi = BITS(7, 11); | ||
| 3073 | if (ishi == 0)ishi = 0x20; | ||
| 3074 | state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000); | ||
| 3075 | break; | 3116 | break; |
| 3076 | } | 3117 | } else if (BIT (4)) { |
| 3077 | else if (BIT (4)) { | ||
| 3078 | #ifdef MODE32 | 3118 | #ifdef MODE32 |
| 3079 | if (state->is_v6 | 3119 | if (state->is_v6 |
| 3080 | && handle_v6_insn (state, instr)) | 3120 | && handle_v6_insn (state, instr)) |
| @@ -3437,7 +3477,7 @@ mainswitch: | |||
| 3437 | 3477 | ||
| 3438 | case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ | 3478 | case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ |
| 3439 | if (BIT (4)) { | 3479 | if (BIT (4)) { |
| 3440 | DEBUG("got unhandled special breakpoint\n"); | 3480 | LOG_DEBUG(Core_ARM11, "got unhandled special breakpoint"); |
| 3441 | return 1; | 3481 | return 1; |
| 3442 | } | 3482 | } |
| 3443 | UNDEF_LSRBaseEQOffWb; | 3483 | UNDEF_LSRBaseEQOffWb; |
| @@ -3686,13 +3726,11 @@ mainswitch: | |||
| 3686 | 3726 | ||
| 3687 | /* Co-Processor Data Transfers. */ | 3727 | /* Co-Processor Data Transfers. */ |
| 3688 | case 0xc4: | 3728 | case 0xc4: |
| 3689 | if ((instr & 0x0FF00FF0) == 0xC400B10) //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0 | 3729 | if ((instr & 0x0FF00FF0) == 0xC400B10) { //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0 |
| 3690 | { | ||
| 3691 | state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; | 3730 | state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; |
| 3692 | state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; | 3731 | state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; |
| 3693 | break; | 3732 | break; |
| 3694 | } | 3733 | } else if (state->is_v5) { |
| 3695 | else if (state->is_v5) { | ||
| 3696 | /* Reading from R15 is UNPREDICTABLE. */ | 3734 | /* Reading from R15 is UNPREDICTABLE. */ |
| 3697 | if (BITS (12, 15) == 15 || BITS (16, 19) == 15) | 3735 | if (BITS (12, 15) == 15 || BITS (16, 19) == 15) |
| 3698 | ARMul_UndefInstr (state, instr); | 3736 | ARMul_UndefInstr (state, instr); |
| @@ -3712,22 +3750,18 @@ mainswitch: | |||
| 3712 | break; | 3750 | break; |
| 3713 | 3751 | ||
| 3714 | case 0xc5: | 3752 | case 0xc5: |
| 3715 | if ((instr & 0x00000FF0) == 0xB10) //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0 | 3753 | if ((instr & 0x00000FF0) == 0xB10) { //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0 |
| 3716 | { | ||
| 3717 | state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; | 3754 | state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; |
| 3718 | state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; | 3755 | state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; |
| 3719 | break; | 3756 | break; |
| 3720 | } | 3757 | } else if (state->is_v5) { |
| 3721 | else if (state->is_v5) { | ||
| 3722 | /* Writes to R15 are UNPREDICATABLE. */ | 3758 | /* Writes to R15 are UNPREDICATABLE. */ |
| 3723 | if (DESTReg == 15 || LHSReg == 15) | 3759 | if (DESTReg == 15 || LHSReg == 15) |
| 3724 | ARMul_UndefInstr (state, instr); | 3760 | ARMul_UndefInstr (state, instr); |
| 3725 | /* Is access to the coprocessor allowed ? */ | 3761 | /* Is access to the coprocessor allowed ? */ |
| 3726 | else if (!CP_ACCESS_ALLOWED(state, CPNum)) | 3762 | else if (!CP_ACCESS_ALLOWED(state, CPNum)) { |
| 3727 | { | ||
| 3728 | ARMul_UndefInstr(state, instr); | 3763 | ARMul_UndefInstr(state, instr); |
| 3729 | } | 3764 | } else { |
| 3730 | else { | ||
| 3731 | /* MRRC, ARMv5TE and up */ | 3765 | /* MRRC, ARMv5TE and up */ |
| 3732 | ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); | 3766 | ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); |
| 3733 | break; | 3767 | break; |
| @@ -4565,7 +4599,7 @@ out: | |||
| 4565 | #ifdef MODE32 | 4599 | #ifdef MODE32 |
| 4566 | if (state->Bank > 0) { | 4600 | if (state->Bank > 0) { |
| 4567 | state->Cpsr = state->Spsr[state->Bank]; | 4601 | state->Cpsr = state->Spsr[state->Bank]; |
| 4568 | //ARMul_CPSRAltered (state); | 4602 | ARMul_CPSRAltered (state); |
| 4569 | } | 4603 | } |
| 4570 | #ifdef MODET | 4604 | #ifdef MODET |
| 4571 | if (TFLAG) | 4605 | if (TFLAG) |
| @@ -5256,7 +5290,7 @@ L_ldm_s_makeabort: | |||
| 5256 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | 5290 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode |
| 5257 | if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { | 5291 | if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { |
| 5258 | state->Cpsr = GETSPSR (state->Bank); | 5292 | state->Cpsr = GETSPSR (state->Bank); |
| 5259 | //ARMul_CPSRAltered (state); | 5293 | ARMul_CPSRAltered (state); |
| 5260 | } | 5294 | } |
| 5261 | 5295 | ||
| 5262 | WriteR15 (state, PC); | 5296 | WriteR15 (state, PC); |
| @@ -5639,37 +5673,29 @@ L_stm_s_takeabort: | |||
| 5639 | /* Attempt to emulate an ARMv6 instruction. | 5673 | /* Attempt to emulate an ARMv6 instruction. |
| 5640 | Returns non-zero upon success. */ | 5674 | Returns non-zero upon success. */ |
| 5641 | 5675 | ||
| 5642 | static int | 5676 | static int handle_v6_insn(ARMul_State* state, ARMword instr) { |
| 5643 | handle_v6_insn (ARMul_State * state, ARMword instr) { | 5677 | switch (BITS(20, 27)) { |
| 5644 | switch (BITS (20, 27)) { | ||
| 5645 | //ichfly | ||
| 5646 | case 0x66: //UQSUB8 | ||
| 5647 | if ((instr & 0x0FF00FF0) == 0x06600FF0) { | ||
| 5648 | u32 rd = (instr >> 12) & 0xF; | ||
| 5649 | u32 rm = (instr >> 16) & 0xF; | ||
| 5650 | u32 rn = (instr >> 0) & 0xF; | ||
| 5651 | u32 subfrom = state->Reg[rm]; | ||
| 5652 | u32 tosub = state->Reg[rn]; | ||
| 5653 | |||
| 5654 | u8 b1 = (u8)((u8)(subfrom)-(u8)(tosub)); | ||
| 5655 | if (b1 > (u8)(subfrom)) b1 = 0; | ||
| 5656 | u8 b2 = (u8)((u8)(subfrom >> 8) - (u8)(tosub >> 8)); | ||
| 5657 | if (b2 > (u8)(subfrom >> 8)) b2 = 0; | ||
| 5658 | u8 b3 = (u8)((u8)(subfrom >> 16) - (u8)(tosub >> 16)); | ||
| 5659 | if (b3 > (u8)(subfrom >> 16)) b3 = 0; | ||
| 5660 | u8 b4 = (u8)((u8)(subfrom >> 24) - (u8)(tosub >> 24)); | ||
| 5661 | if (b4 > (u8)(subfrom >> 24)) b4 = 0; | ||
| 5662 | state->Reg[rd] = (u32)(b1 | b2 << 8 | b3 << 16 | b4 << 24); | ||
| 5663 | return 1; | ||
| 5664 | } else { | ||
| 5665 | printf("UQSUB8 decoding fail %08X",instr); | ||
| 5666 | } | ||
| 5667 | #if 0 | ||
| 5668 | case 0x03: | 5678 | case 0x03: |
| 5669 | printf ("Unhandled v6 insn: ldr\n"); | 5679 | printf ("Unhandled v6 insn: ldr\n"); |
| 5670 | break; | 5680 | break; |
| 5671 | case 0x04: | 5681 | case 0x04: // UMAAL |
| 5672 | printf ("Unhandled v6 insn: umaal\n"); | 5682 | { |
| 5683 | const u8 rm_idx = BITS(8, 11); | ||
| 5684 | const u8 rn_idx = BITS(0, 3); | ||
| 5685 | const u8 rd_lo_idx = BITS(12, 15); | ||
| 5686 | const u8 rd_hi_idx = BITS(16, 19); | ||
| 5687 | |||
| 5688 | const u32 rm_val = state->Reg[rm_idx]; | ||
| 5689 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 5690 | const u32 rd_lo_val = state->Reg[rd_lo_idx]; | ||
| 5691 | const u32 rd_hi_val = state->Reg[rd_hi_idx]; | ||
| 5692 | |||
| 5693 | const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val; | ||
| 5694 | |||
| 5695 | state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF); | ||
| 5696 | state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF); | ||
| 5697 | return 1; | ||
| 5698 | } | ||
| 5673 | break; | 5699 | break; |
| 5674 | case 0x06: | 5700 | case 0x06: |
| 5675 | printf ("Unhandled v6 insn: mls/str\n"); | 5701 | printf ("Unhandled v6 insn: mls/str\n"); |
| @@ -5678,9 +5704,43 @@ L_stm_s_takeabort: | |||
| 5678 | printf ("Unhandled v6 insn: smi\n"); | 5704 | printf ("Unhandled v6 insn: smi\n"); |
| 5679 | break; | 5705 | break; |
| 5680 | case 0x18: | 5706 | case 0x18: |
| 5707 | if (BITS(4, 7) == 0x9) { | ||
| 5708 | /* strex */ | ||
| 5709 | u32 l = LHSReg; | ||
| 5710 | u32 r = RHSReg; | ||
| 5711 | u32 lhs = LHS; | ||
| 5712 | |||
| 5713 | bool enter = false; | ||
| 5714 | |||
| 5715 | if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true; | ||
| 5716 | //StoreWord(state, lhs, RHS) | ||
| 5717 | if (state->Aborted) { | ||
| 5718 | TAKEABORT; | ||
| 5719 | } | ||
| 5720 | |||
| 5721 | if (enter) { | ||
| 5722 | ARMul_StoreWordS(state, lhs, RHS); | ||
| 5723 | state->Reg[DESTReg] = 0; | ||
| 5724 | } | ||
| 5725 | else { | ||
| 5726 | state->Reg[DESTReg] = 1; | ||
| 5727 | } | ||
| 5728 | |||
| 5729 | return 1; | ||
| 5730 | } | ||
| 5681 | printf ("Unhandled v6 insn: strex\n"); | 5731 | printf ("Unhandled v6 insn: strex\n"); |
| 5682 | break; | 5732 | break; |
| 5683 | case 0x19: | 5733 | case 0x19: |
| 5734 | /* ldrex */ | ||
| 5735 | if (BITS(4, 7) == 0x9) { | ||
| 5736 | u32 lhs = LHS; | ||
| 5737 | |||
| 5738 | state->currentexaddr = lhs; | ||
| 5739 | state->currentexval = ARMul_ReadWord(state, lhs); | ||
| 5740 | |||
| 5741 | LoadWord(state, instr, lhs); | ||
| 5742 | return 1; | ||
| 5743 | } | ||
| 5684 | printf ("Unhandled v6 insn: ldrex\n"); | 5744 | printf ("Unhandled v6 insn: ldrex\n"); |
| 5685 | break; | 5745 | break; |
| 5686 | case 0x1a: | 5746 | case 0x1a: |
| @@ -5690,9 +5750,52 @@ L_stm_s_takeabort: | |||
| 5690 | printf ("Unhandled v6 insn: ldrexd\n"); | 5750 | printf ("Unhandled v6 insn: ldrexd\n"); |
| 5691 | break; | 5751 | break; |
| 5692 | case 0x1c: | 5752 | case 0x1c: |
| 5753 | if (BITS(4, 7) == 0x9) { | ||
| 5754 | /* strexb */ | ||
| 5755 | u32 lhs = LHS; | ||
| 5756 | |||
| 5757 | bool enter = false; | ||
| 5758 | |||
| 5759 | if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true; | ||
| 5760 | |||
| 5761 | BUSUSEDINCPCN; | ||
| 5762 | if (state->Aborted) { | ||
| 5763 | TAKEABORT; | ||
| 5764 | } | ||
| 5765 | |||
| 5766 | |||
| 5767 | if (enter) { | ||
| 5768 | ARMul_StoreByte(state, lhs, RHS); | ||
| 5769 | state->Reg[DESTReg] = 0; | ||
| 5770 | } | ||
| 5771 | else { | ||
| 5772 | state->Reg[DESTReg] = 1; | ||
| 5773 | } | ||
| 5774 | |||
| 5775 | //printf("In %s, strexb not implemented\n", __FUNCTION__); | ||
| 5776 | UNDEF_LSRBPC; | ||
| 5777 | /* WRITESDEST (dest); */ | ||
| 5778 | return 1; | ||
| 5779 | } | ||
| 5693 | printf ("Unhandled v6 insn: strexb\n"); | 5780 | printf ("Unhandled v6 insn: strexb\n"); |
| 5694 | break; | 5781 | break; |
| 5695 | case 0x1d: | 5782 | case 0x1d: |
| 5783 | if ((BITS(4, 7)) == 0x9) { | ||
| 5784 | /* ldrexb */ | ||
| 5785 | u32 lhs = LHS; | ||
| 5786 | LoadByte(state, instr, lhs, LUNSIGNED); | ||
| 5787 | |||
| 5788 | state->currentexaddr = lhs; | ||
| 5789 | state->currentexval = (u32)ARMul_ReadByte(state, lhs); | ||
| 5790 | |||
| 5791 | //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]); | ||
| 5792 | //printf("ldrexb\n"); | ||
| 5793 | //printf("instr is %x rm is %d\n", instr, BITS(16, 19)); | ||
| 5794 | //exit(-1); | ||
| 5795 | |||
| 5796 | //printf("In %s, ldrexb not implemented\n", __FUNCTION__); | ||
| 5797 | return 1; | ||
| 5798 | } | ||
| 5696 | printf ("Unhandled v6 insn: ldrexb\n"); | 5799 | printf ("Unhandled v6 insn: ldrexb\n"); |
| 5697 | break; | 5800 | break; |
| 5698 | case 0x1e: | 5801 | case 0x1e: |
| @@ -5713,510 +5816,801 @@ L_stm_s_takeabort: | |||
| 5713 | case 0x3f: | 5816 | case 0x3f: |
| 5714 | printf ("Unhandled v6 insn: rbit\n"); | 5817 | printf ("Unhandled v6 insn: rbit\n"); |
| 5715 | break; | 5818 | break; |
| 5716 | #endif | 5819 | case 0x61: // SADD16, SASX, SSAX, and SSUB16 |
| 5717 | case 0x61: | 5820 | if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 || |
| 5718 | if ((instr & 0xFF0) == 0xf70)//ssub16 | 5821 | (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70) |
| 5719 | { | ||
| 5720 | u8 tar = BITS(12, 15); | ||
| 5721 | u8 src1 = BITS(16, 19); | ||
| 5722 | u8 src2 = BITS(0, 3); | ||
| 5723 | s16 a1 = (state->Reg[src1] & 0xFFFF); | ||
| 5724 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||
| 5725 | s16 b1 = (state->Reg[src2] & 0xFFFF); | ||
| 5726 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||
| 5727 | state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10); | ||
| 5728 | return 1; | ||
| 5729 | } | ||
| 5730 | else if ((instr & 0xFF0) == 0xf10)//sadd16 | ||
| 5731 | { | 5822 | { |
| 5732 | u8 tar = BITS(12, 15); | 5823 | const u8 rd_idx = BITS(12, 15); |
| 5733 | u8 src1 = BITS(16, 19); | 5824 | const u8 rm_idx = BITS(0, 3); |
| 5734 | u8 src2 = BITS(0, 3); | 5825 | const u8 rn_idx = BITS(16, 19); |
| 5735 | s16 a1 = (state->Reg[src1] & 0xFFFF); | 5826 | const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); |
| 5736 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | 5827 | const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF); |
| 5737 | s16 b1 = (state->Reg[src2] & 0xFFFF); | 5828 | const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); |
| 5738 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | 5829 | const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF); |
| 5739 | state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10); | 5830 | |
| 5831 | s32 lo_result; | ||
| 5832 | s32 hi_result; | ||
| 5833 | |||
| 5834 | // SADD16 | ||
| 5835 | if ((instr & 0xFF0) == 0xf10) { | ||
| 5836 | lo_result = (rn_lo + rm_lo); | ||
| 5837 | hi_result = (rn_hi + rm_hi); | ||
| 5838 | } | ||
| 5839 | // SASX | ||
| 5840 | else if ((instr & 0xFF0) == 0xf30) { | ||
| 5841 | lo_result = (rn_lo - rm_hi); | ||
| 5842 | hi_result = (rn_hi + rm_lo); | ||
| 5843 | } | ||
| 5844 | // SSAX | ||
| 5845 | else if ((instr & 0xFF0) == 0xf50) { | ||
| 5846 | lo_result = (rn_lo + rm_hi); | ||
| 5847 | hi_result = (rn_hi - rm_lo); | ||
| 5848 | } | ||
| 5849 | // SSUB16 | ||
| 5850 | else { | ||
| 5851 | lo_result = (rn_lo - rm_lo); | ||
| 5852 | hi_result = (rn_hi - rm_hi); | ||
| 5853 | } | ||
| 5854 | |||
| 5855 | state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | ||
| 5856 | |||
| 5857 | if (lo_result >= 0) { | ||
| 5858 | state->GEFlag |= (1 << 16); | ||
| 5859 | state->GEFlag |= (1 << 17); | ||
| 5860 | } else { | ||
| 5861 | state->GEFlag &= ~(1 << 16); | ||
| 5862 | state->GEFlag &= ~(1 << 17); | ||
| 5863 | } | ||
| 5864 | |||
| 5865 | if (hi_result >= 0) { | ||
| 5866 | state->GEFlag |= (1 << 18); | ||
| 5867 | state->GEFlag |= (1 << 19); | ||
| 5868 | } else { | ||
| 5869 | state->GEFlag &= ~(1 << 18); | ||
| 5870 | state->GEFlag &= ~(1 << 19); | ||
| 5871 | } | ||
| 5872 | |||
| 5740 | return 1; | 5873 | return 1; |
| 5741 | } | 5874 | } |
| 5742 | else if ((instr & 0xFF0) == 0xf50)//ssax | 5875 | // SADD8/SSUB8 |
| 5876 | else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0) | ||
| 5743 | { | 5877 | { |
| 5744 | u8 tar = BITS(12, 15); | 5878 | const u8 rd_idx = BITS(12, 15); |
| 5745 | u8 src1 = BITS(16, 19); | 5879 | const u8 rm_idx = BITS(0, 3); |
| 5746 | u8 src2 = BITS(0, 3); | 5880 | const u8 rn_idx = BITS(16, 19); |
| 5747 | s16 a1 = (state->Reg[src1] & 0xFFFF); | 5881 | const u32 rm_val = state->Reg[rm_idx]; |
| 5748 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | 5882 | const u32 rn_val = state->Reg[rn_idx]; |
| 5749 | s16 b1 = (state->Reg[src2] & 0xFFFF); | 5883 | |
| 5750 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | 5884 | u8 lo_val1; |
| 5751 | state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); | 5885 | u8 lo_val2; |
| 5886 | u8 hi_val1; | ||
| 5887 | u8 hi_val2; | ||
| 5888 | |||
| 5889 | // SADD8 | ||
| 5890 | if ((instr & 0xFF0) == 0xf90) { | ||
| 5891 | lo_val1 = (u8)((rn_val & 0xFF) + (rm_val & 0xFF)); | ||
| 5892 | lo_val2 = (u8)(((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF)); | ||
| 5893 | hi_val1 = (u8)(((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF)); | ||
| 5894 | hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF)); | ||
| 5895 | |||
| 5896 | if (lo_val1 & 0x80) | ||
| 5897 | state->GEFlag |= (1 << 16); | ||
| 5898 | else | ||
| 5899 | state->GEFlag &= ~(1 << 16); | ||
| 5900 | |||
| 5901 | if (lo_val2 & 0x80) | ||
| 5902 | state->GEFlag |= (1 << 17); | ||
| 5903 | else | ||
| 5904 | state->GEFlag &= ~(1 << 17); | ||
| 5905 | |||
| 5906 | if (hi_val1 & 0x80) | ||
| 5907 | state->GEFlag |= (1 << 18); | ||
| 5908 | else | ||
| 5909 | state->GEFlag &= ~(1 << 18); | ||
| 5910 | |||
| 5911 | if (hi_val2 & 0x80) | ||
| 5912 | state->GEFlag |= (1 << 19); | ||
| 5913 | else | ||
| 5914 | state->GEFlag &= ~(1 << 19); | ||
| 5915 | } | ||
| 5916 | // SSUB8 | ||
| 5917 | else { | ||
| 5918 | lo_val1 = (u8)((rn_val & 0xFF) - (rm_val & 0xFF)); | ||
| 5919 | lo_val2 = (u8)(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF)); | ||
| 5920 | hi_val1 = (u8)(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF)); | ||
| 5921 | hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF)); | ||
| 5922 | |||
| 5923 | if (!(lo_val1 & 0x80)) | ||
| 5924 | state->GEFlag |= (1 << 16); | ||
| 5925 | else | ||
| 5926 | state->GEFlag &= ~(1 << 16); | ||
| 5927 | |||
| 5928 | if (!(lo_val2 & 0x80)) | ||
| 5929 | state->GEFlag |= (1 << 17); | ||
| 5930 | else | ||
| 5931 | state->GEFlag &= ~(1 << 17); | ||
| 5932 | |||
| 5933 | if (!(hi_val1 & 0x80)) | ||
| 5934 | state->GEFlag |= (1 << 18); | ||
| 5935 | else | ||
| 5936 | state->GEFlag &= ~(1 << 18); | ||
| 5937 | |||
| 5938 | if (!(hi_val2 & 0x80)) | ||
| 5939 | state->GEFlag |= (1 << 19); | ||
| 5940 | else | ||
| 5941 | state->GEFlag &= ~(1 << 19); | ||
| 5942 | } | ||
| 5943 | |||
| 5944 | state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24); | ||
| 5752 | return 1; | 5945 | return 1; |
| 5753 | } | 5946 | } |
| 5754 | else if ((instr & 0xFF0) == 0xf30)//sasx | 5947 | else { |
| 5755 | { | 5948 | printf("Unhandled v6 insn: %08x", instr); |
| 5756 | u8 tar = BITS(12, 15); | ||
| 5757 | u8 src1 = BITS(16, 19); | ||
| 5758 | u8 src2 = BITS(0, 3); | ||
| 5759 | s16 a1 = (state->Reg[src1] & 0xFFFF); | ||
| 5760 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||
| 5761 | s16 b1 = (state->Reg[src2] & 0xFFFF); | ||
| 5762 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||
| 5763 | state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); | ||
| 5764 | return 1; | ||
| 5765 | } | 5949 | } |
| 5766 | else printf ("Unhandled v6 insn: sadd/ssub\n"); | ||
| 5767 | break; | 5950 | break; |
| 5768 | case 0x62: | 5951 | case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8 |
| 5769 | if ((instr & 0xFF0) == 0xf70)//QSUB16 | ||
| 5770 | { | 5952 | { |
| 5771 | u8 tar = BITS(12, 15); | 5953 | const u8 op2 = BITS(5, 7); |
| 5772 | u8 src1 = BITS(16, 19); | 5954 | |
| 5773 | u8 src2 = BITS(0, 3); | 5955 | const u8 rd_idx = BITS(12, 15); |
| 5774 | s16 a1 = (state->Reg[src1] & 0xFFFF); | 5956 | const u8 rn_idx = BITS(16, 19); |
| 5775 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | 5957 | const u8 rm_idx = BITS(0, 3); |
| 5776 | s16 b1 = (state->Reg[src2] & 0xFFFF); | 5958 | const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); |
| 5777 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | 5959 | const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); |
| 5778 | s32 res1 = (a1 - b1); | 5960 | const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); |
| 5779 | s32 res2 = (a2 - b2); | 5961 | const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); |
| 5780 | if (res1 > 0x7FFF) res1 = 0x7FFF; | 5962 | |
| 5781 | if (res2 > 0x7FFF) res2 = 0x7FFF; | 5963 | u16 lo_result = 0; |
| 5782 | if (res1 < 0x7FFF) res1 = -0x8000; | 5964 | u16 hi_result = 0; |
| 5783 | if (res2 < 0x7FFF) res2 = -0x8000; | 5965 | |
| 5784 | state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10); | 5966 | // QADD16 |
| 5785 | return 1; | 5967 | if (op2 == 0x00) { |
| 5786 | } | 5968 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); |
| 5787 | else if ((instr & 0xFF0) == 0xf10)//QADD16 | 5969 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); |
| 5788 | { | 5970 | } |
| 5789 | u8 tar = BITS(12, 15); | 5971 | // QASX |
| 5790 | u8 src1 = BITS(16, 19); | 5972 | else if (op2 == 0x01) { |
| 5791 | u8 src2 = BITS(0, 3); | 5973 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); |
| 5792 | s16 a1 = (state->Reg[src1] & 0xFFFF); | 5974 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); |
| 5793 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | 5975 | } |
| 5794 | s16 b1 = (state->Reg[src2] & 0xFFFF); | 5976 | // QSAX |
| 5795 | s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | 5977 | else if (op2 == 0x02) { |
| 5796 | s32 res1 = (a1 + b1); | 5978 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); |
| 5797 | s32 res2 = (a2 + b2); | 5979 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); |
| 5798 | if (res1 > 0x7FFF) res1 = 0x7FFF; | 5980 | } |
| 5799 | if (res2 > 0x7FFF) res2 = 0x7FFF; | 5981 | // QSUB16 |
| 5800 | if (res1 < 0x7FFF) res1 = -0x8000; | 5982 | else if (op2 == 0x03) { |
| 5801 | if (res2 < 0x7FFF) res2 = -0x8000; | 5983 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); |
| 5802 | state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10); | 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; | ||
| 5999 | } | ||
| 6000 | |||
| 6001 | state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | ||
| 5803 | return 1; | 6002 | return 1; |
| 5804 | } | 6003 | } |
| 5805 | else printf ("Unhandled v6 insn: qadd/qsub\n"); | ||
| 5806 | break; | 6004 | break; |
| 5807 | #if 0 | ||
| 5808 | case 0x63: | 6005 | case 0x63: |
| 5809 | printf ("Unhandled v6 insn: shadd/shsub\n"); | 6006 | printf ("Unhandled v6 insn: shadd/shsub\n"); |
| 5810 | break; | 6007 | break; |
| 5811 | case 0x65: | 6008 | case 0x65: |
| 5812 | printf ("Unhandled v6 insn: uadd/usub\n"); | 6009 | { |
| 5813 | break; | 6010 | u32 rd = (instr >> 12) & 0xF; |
| 5814 | case 0x66: | 6011 | u32 rn = (instr >> 16) & 0xF; |
| 5815 | printf ("Unhandled v6 insn: uqadd/uqsub\n"); | 6012 | u32 rm = (instr >> 0) & 0xF; |
| 5816 | break; | 6013 | u32 from = state->Reg[rn]; |
| 5817 | case 0x67: | 6014 | u32 to = state->Reg[rm]; |
| 5818 | printf ("Unhandled v6 insn: uhadd/uhsub\n"); | 6015 | |
| 5819 | break; | 6016 | if ((instr & 0xFF0) == 0xF10 || (instr & 0xFF0) == 0xF70) { // UADD16/USUB16 |
| 5820 | case 0x68: | 6017 | u32 h1, h2; |
| 5821 | printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); | 6018 | state->Cpsr &= 0xfff0ffff; |
| 5822 | break; | 6019 | if ((instr & 0x0F0) == 0x070) { // USUB16 |
| 5823 | #endif | 6020 | h1 = ((u16)from - (u16)to); |
| 5824 | case 0x6c: | 6021 | h2 = ((u16)(from >> 16) - (u16)(to >> 16)); |
| 5825 | if ((instr & 0xf03f0) == 0xf0070) //uxtb16 | 6022 | |
| 5826 | { | 6023 | if (!(h1 & 0xffff0000)) |
| 5827 | u8 src1 = BITS(0, 3); | 6024 | state->GEFlag |= (3 << 16); |
| 5828 | u8 tar = BITS(12, 15); | 6025 | else |
| 5829 | u32 base = state->Reg[src1]; | 6026 | state->GEFlag &= ~(3 << 16); |
| 5830 | u32 shamt = BITS(9,10)* 8; | ||
| 5831 | u32 in = ((base << (32 - shamt)) | (base >> shamt)); | ||
| 5832 | state->Reg[tar] = in & 0x00FF00FF; | ||
| 5833 | return 1; | ||
| 5834 | } | ||
| 5835 | else | ||
| 5836 | printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); | ||
| 5837 | break; | ||
| 5838 | case 0x70: | ||
| 5839 | if ((instr & 0xf0d0) == 0xf010)//smuad //ichfly | ||
| 5840 | { | ||
| 5841 | u8 tar = BITS(16, 19); | ||
| 5842 | u8 src1 = BITS(0, 3); | ||
| 5843 | u8 src2 = BITS(8, 11); | ||
| 5844 | u8 swap = BIT(5); | ||
| 5845 | s16 a1 = (state->Reg[src1] & 0xFFFF); | ||
| 5846 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||
| 5847 | s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | ||
| 5848 | s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||
| 5849 | state->Reg[tar] = a1*a2 + b1*b2; | ||
| 5850 | return 1; | ||
| 5851 | 6027 | ||
| 5852 | } | 6028 | if (!(h2 & 0xffff0000)) |
| 5853 | else if ((instr & 0xf0d0) == 0xf050)//smusd | 6029 | state->GEFlag |= (3 << 18); |
| 5854 | { | 6030 | else |
| 5855 | u8 tar = BITS(16, 19); | 6031 | state->GEFlag &= ~(3 << 18); |
| 5856 | u8 src1 = BITS(0, 3); | 6032 | } |
| 5857 | u8 src2 = BITS(8, 11); | 6033 | else { // UADD16 |
| 5858 | u8 swap = BIT(5); | 6034 | h1 = ((u16)from + (u16)to); |
| 5859 | s16 a1 = (state->Reg[src1] & 0xFFFF); | 6035 | h2 = ((u16)(from >> 16) + (u16)(to >> 16)); |
| 5860 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | 6036 | |
| 5861 | s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | 6037 | if (h1 & 0xffff0000) |
| 5862 | s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | 6038 | state->GEFlag |= (3 << 16); |
| 5863 | state->Reg[tar] = a1*a2 - b1*b2; | 6039 | else |
| 5864 | return 1; | 6040 | state->GEFlag &= ~(3 << 16); |
| 5865 | } | 6041 | |
| 5866 | else if ((instr & 0xd0) == 0x10)//smlad | 6042 | if (h2 & 0xffff0000) |
| 5867 | { | 6043 | state->GEFlag |= (3 << 18); |
| 5868 | u8 tar = BITS(16, 19); | 6044 | else |
| 5869 | u8 src1 = BITS(0, 3); | 6045 | state->GEFlag &= ~(3 << 18); |
| 5870 | u8 src2 = BITS(8, 11); | 6046 | } |
| 5871 | u8 src3 = BITS(12, 15); | 6047 | |
| 5872 | u8 swap = BIT(5); | 6048 | state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16)); |
| 5873 | |||
| 5874 | u32 a3 = state->Reg[src3]; | ||
| 5875 | |||
| 5876 | s16 a1 = (state->Reg[src1] & 0xFFFF); | ||
| 5877 | s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||
| 5878 | s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | ||
| 5879 | s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||
| 5880 | state->Reg[tar] = a1*a2 + b1*b2 + a3; | ||
| 5881 | return 1; | 6049 | return 1; |
| 5882 | } | 6050 | } |
| 5883 | else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); | 6051 | else |
| 5884 | break; | 6052 | if ((instr & 0xFF0) == 0xF90 || (instr & 0xFF0) == 0xFF0) { // UADD8/USUB8 |
| 5885 | case 0x74: | 6053 | u32 b1, b2, b3, b4; |
| 5886 | printf ("Unhandled v6 insn: smlald/smlsld\n"); | 6054 | state->Cpsr &= 0xfff0ffff; |
| 5887 | break; | 6055 | if ((instr & 0x0F0) == 0x0F0) { // USUB8 |
| 5888 | case 0x75: | 6056 | b1 = ((u8)from - (u8)to); |
| 5889 | printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); | 6057 | b2 = ((u8)(from >> 8) - (u8)(to >> 8)); |
| 5890 | break; | 6058 | b3 = ((u8)(from >> 16) - (u8)(to >> 16)); |
| 5891 | case 0x78: | 6059 | b4 = ((u8)(from >> 24) - (u8)(to >> 24)); |
| 5892 | printf ("Unhandled v6 insn: usad/usada8\n"); | 6060 | |
| 5893 | break; | 6061 | if (!(b1 & 0xffffff00)) |
| 5894 | #if 0 | 6062 | state->GEFlag |= (1 << 16); |
| 5895 | case 0x7a: | 6063 | else |
| 5896 | printf ("Unhandled v6 insn: usbfx\n"); | 6064 | state->GEFlag &= ~(1 << 16); |
| 5897 | break; | ||
| 5898 | case 0x7c: | ||
| 5899 | printf ("Unhandled v6 insn: bfc/bfi\n"); | ||
| 5900 | break; | ||
| 5901 | #endif | ||
| 5902 | 6065 | ||
| 6066 | if (!(b2 & 0xffffff00)) | ||
| 6067 | state->GEFlag |= (1 << 17); | ||
| 6068 | else | ||
| 6069 | state->GEFlag &= ~(1 << 17); | ||
| 5903 | 6070 | ||
| 5904 | /* add new instr for arm v6. */ | 6071 | if (!(b3 & 0xffffff00)) |
| 5905 | ARMword lhs, temp; | 6072 | state->GEFlag |= (1 << 18); |
| 5906 | case 0x18: { /* ORR reg */ | 6073 | else |
| 5907 | /* dyf add armv6 instr strex 2010.9.17 */ | 6074 | state->GEFlag &= ~(1 << 18); |
| 5908 | if (BITS (4, 7) == 0x9) { | ||
| 5909 | u32 l = LHSReg; | ||
| 5910 | u32 r = RHSReg; | ||
| 5911 | lhs = LHS; | ||
| 5912 | 6075 | ||
| 5913 | bool enter = false; | 6076 | if (!(b4 & 0xffffff00)) |
| 6077 | state->GEFlag |= (1 << 19); | ||
| 6078 | else | ||
| 6079 | state->GEFlag &= ~(1 << 19); | ||
| 6080 | } | ||
| 6081 | else { // UADD8 | ||
| 6082 | b1 = ((u8)from + (u8)to); | ||
| 6083 | b2 = ((u8)(from >> 8) + (u8)(to >> 8)); | ||
| 6084 | b3 = ((u8)(from >> 16) + (u8)(to >> 16)); | ||
| 6085 | b4 = ((u8)(from >> 24) + (u8)(to >> 24)); | ||
| 5914 | 6086 | ||
| 5915 | if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true; | 6087 | if (b1 & 0xffffff00) |
| 5916 | ARMul_StoreWordS(state, lhs, RHS); | 6088 | state->GEFlag |= (1 << 16); |
| 5917 | //StoreWord(state, lhs, RHS) | 6089 | else |
| 5918 | if (state->Aborted) { | 6090 | state->GEFlag &= ~(1 << 16); |
| 5919 | TAKEABORT; | ||
| 5920 | } | ||
| 5921 | 6091 | ||
| 5922 | if (enter) { | 6092 | if (b2 & 0xffffff00) |
| 5923 | state->Reg[DESTReg] = 0; | 6093 | state->GEFlag |= (1 << 17); |
| 5924 | } else { | 6094 | else |
| 5925 | state->Reg[DESTReg] = 1; | 6095 | state->GEFlag &= ~(1 << 17); |
| 5926 | } | ||
| 5927 | 6096 | ||
| 5928 | return 1; | 6097 | if (b3 & 0xffffff00) |
| 5929 | } | 6098 | state->GEFlag |= (1 << 18); |
| 5930 | break; | 6099 | else |
| 5931 | } | 6100 | state->GEFlag &= ~(1 << 18); |
| 5932 | 6101 | ||
| 5933 | case 0x19: { /* orrs reg */ | 6102 | if (b4 & 0xffffff00) |
| 5934 | /* dyf add armv6 instr ldrex */ | 6103 | state->GEFlag |= (1 << 19); |
| 5935 | if (BITS (4, 7) == 0x9) { | 6104 | else |
| 5936 | lhs = LHS; | 6105 | state->GEFlag &= ~(1 << 19); |
| 6106 | } | ||
| 5937 | 6107 | ||
| 5938 | state->currentexaddr = lhs; | 6108 | state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); |
| 5939 | state->currentexval = ARMul_ReadWord(state, lhs); | 6109 | return 1; |
| 6110 | } | ||
| 6111 | } | ||
| 6112 | printf("Unhandled v6 insn: uasx/usax\n"); | ||
| 6113 | break; | ||
| 6114 | case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8 | ||
| 6115 | { | ||
| 6116 | const u8 rd_idx = BITS(12, 15); | ||
| 6117 | const u8 rm_idx = BITS(0, 3); | ||
| 6118 | const u8 rn_idx = BITS(16, 19); | ||
| 6119 | const u8 op2 = BITS(5, 7); | ||
| 6120 | const u32 rm_val = state->Reg[rm_idx]; | ||
| 6121 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 6122 | |||
| 6123 | u16 lo_val = 0; | ||
| 6124 | u16 hi_val = 0; | ||
| 6125 | |||
| 6126 | // UQADD16 | ||
| 6127 | if (op2 == 0x00) { | ||
| 6128 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 6129 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6130 | } | ||
| 6131 | // UQASX | ||
| 6132 | else if (op2 == 0x01) { | ||
| 6133 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6134 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6135 | } | ||
| 6136 | // UQSAX | ||
| 6137 | else if (op2 == 0x02) { | ||
| 6138 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6139 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6140 | } | ||
| 6141 | // UQSUB16 | ||
| 6142 | else if (op2 == 0x03) { | ||
| 6143 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 6144 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6145 | } | ||
| 6146 | // UQADD8 | ||
| 6147 | else if (op2 == 0x04) { | ||
| 6148 | lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | | ||
| 6149 | ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6150 | hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | | ||
| 6151 | ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6152 | } | ||
| 6153 | // UQSUB8 | ||
| 6154 | else { | ||
| 6155 | lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | | ||
| 6156 | ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6157 | hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | | ||
| 6158 | ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6159 | } | ||
| 5940 | 6160 | ||
| 5941 | LoadWord (state, instr, lhs); | 6161 | state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16); |
| 5942 | return 1; | 6162 | return 1; |
| 5943 | } | 6163 | } |
| 5944 | break; | 6164 | break; |
| 5945 | } | 6165 | case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8. |
| 6166 | { | ||
| 6167 | const u8 op2 = BITS(5, 7); | ||
| 5946 | 6168 | ||
| 5947 | case 0x1c: { /* BIC reg */ | 6169 | const u8 rm_idx = BITS(0, 3); |
| 5948 | /* dyf add for STREXB */ | 6170 | const u8 rn_idx = BITS(16, 19); |
| 5949 | if (BITS (4, 7) == 0x9) { | 6171 | const u8 rd_idx = BITS(12, 15); |
| 5950 | lhs = LHS; | ||
| 5951 | 6172 | ||
| 5952 | bool enter = false; | 6173 | const u32 rm_val = state->Reg[rm_idx]; |
| 6174 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 5953 | 6175 | ||
| 5954 | if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true; | 6176 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) |
| 6177 | { | ||
| 6178 | u32 lo_val = 0; | ||
| 6179 | u32 hi_val = 0; | ||
| 5955 | 6180 | ||
| 5956 | ARMul_StoreByte (state, lhs, RHS); | 6181 | // UHADD16 |
| 5957 | BUSUSEDINCPCN; | 6182 | if (op2 == 0x00) { |
| 5958 | if (state->Aborted) { | 6183 | lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); |
| 5959 | TAKEABORT; | 6184 | hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); |
| 5960 | } | 6185 | } |
| 6186 | // UHASX | ||
| 6187 | else if (op2 == 0x01) { | ||
| 6188 | lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 6189 | hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 6190 | } | ||
| 6191 | // UHSAX | ||
| 6192 | else if (op2 == 0x02) { | ||
| 6193 | lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 6194 | hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 6195 | } | ||
| 6196 | // UHSUB16 | ||
| 6197 | else if (op2 == 0x03) { | ||
| 6198 | lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 6199 | hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 6200 | } | ||
| 5961 | 6201 | ||
| 6202 | lo_val >>= 1; | ||
| 6203 | hi_val >>= 1; | ||
| 5962 | 6204 | ||
| 5963 | if (enter) { | 6205 | state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); |
| 5964 | state->Reg[DESTReg] = 0; | 6206 | return 1; |
| 5965 | } else { | 6207 | } |
| 5966 | state->Reg[DESTReg] = 1; | 6208 | else if (op2 == 0x04 || op2 == 0x07) { |
| 6209 | u32 sum1; | ||
| 6210 | u32 sum2; | ||
| 6211 | u32 sum3; | ||
| 6212 | u32 sum4; | ||
| 6213 | |||
| 6214 | // UHADD8 | ||
| 6215 | if (op2 == 0x04) { | ||
| 6216 | sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); | ||
| 6217 | sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); | ||
| 6218 | sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); | ||
| 6219 | sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); | ||
| 6220 | } | ||
| 6221 | // UHSUB8 | ||
| 6222 | else { | ||
| 6223 | sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); | ||
| 6224 | sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); | ||
| 6225 | sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); | ||
| 6226 | sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); | ||
| 6227 | } | ||
| 6228 | |||
| 6229 | sum1 >>= 1; | ||
| 6230 | sum2 >>= 1; | ||
| 6231 | sum3 >>= 1; | ||
| 6232 | sum4 >>= 1; | ||
| 6233 | |||
| 6234 | state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); | ||
| 6235 | return 1; | ||
| 5967 | } | 6236 | } |
| 5968 | |||
| 5969 | //printf("In %s, strexb not implemented\n", __FUNCTION__); | ||
| 5970 | UNDEF_LSRBPC; | ||
| 5971 | /* WRITESDEST (dest); */ | ||
| 5972 | return 1; | ||
| 5973 | } | 6237 | } |
| 5974 | break; | 6238 | break; |
| 6239 | case 0x68: | ||
| 6240 | { | ||
| 6241 | u32 rd = (instr >> 12) & 0xF; | ||
| 6242 | u32 rn = (instr >> 16) & 0xF; | ||
| 6243 | u32 rm = (instr >> 0) & 0xF; | ||
| 6244 | u32 from = state->Reg[rn]; | ||
| 6245 | u32 to = state->Reg[rm]; | ||
| 6246 | u32 cpsr = ARMul_GetCPSR(state); | ||
| 6247 | if ((instr & 0xFF0) == 0xFB0) { // SEL | ||
| 6248 | u32 result; | ||
| 6249 | if (cpsr & (1 << 16)) | ||
| 6250 | result = from & 0xff; | ||
| 6251 | else | ||
| 6252 | result = to & 0xff; | ||
| 6253 | if (cpsr & (1 << 17)) | ||
| 6254 | result |= from & 0x0000ff00; | ||
| 6255 | else | ||
| 6256 | result |= to & 0x0000ff00; | ||
| 6257 | if (cpsr & (1 << 18)) | ||
| 6258 | result |= from & 0x00ff0000; | ||
| 6259 | else | ||
| 6260 | result |= to & 0x00ff0000; | ||
| 6261 | if (cpsr & (1 << 19)) | ||
| 6262 | result |= from & 0xff000000; | ||
| 6263 | else | ||
| 6264 | result |= to & 0xff000000; | ||
| 6265 | state->Reg[rd] = result; | ||
| 6266 | return 1; | ||
| 6267 | } | ||
| 5975 | } | 6268 | } |
| 6269 | printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); | ||
| 6270 | break; | ||
| 6271 | |||
| 6272 | case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB | ||
| 6273 | { | ||
| 6274 | const u8 op2 = BITS(5, 7); | ||
| 6275 | |||
| 6276 | // SSAT16 | ||
| 6277 | if (op2 == 0x01) { | ||
| 6278 | const u8 rd_idx = BITS(12, 15); | ||
| 6279 | const u8 rn_idx = BITS(0, 3); | ||
| 6280 | const u8 num_bits = BITS(16, 19) + 1; | ||
| 6281 | const s16 min = -(0x8000 >> (16 - num_bits)); | ||
| 6282 | const s16 max = (0x7FFF >> (16 - num_bits)); | ||
| 6283 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6284 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6285 | |||
| 6286 | if (rn_lo > max) { | ||
| 6287 | rn_lo = max; | ||
| 6288 | SETQ; | ||
| 6289 | } else if (rn_lo < min) { | ||
| 6290 | rn_lo = min; | ||
| 6291 | SETQ; | ||
| 6292 | } | ||
| 6293 | |||
| 6294 | if (rn_hi > max) { | ||
| 6295 | rn_hi = max; | ||
| 6296 | SETQ; | ||
| 6297 | } else if (rn_hi < min) { | ||
| 6298 | rn_hi = min; | ||
| 6299 | SETQ; | ||
| 6300 | } | ||
| 6301 | |||
| 6302 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); | ||
| 6303 | return 1; | ||
| 6304 | } | ||
| 6305 | else if (op2 == 0x03) { | ||
| 6306 | const u8 rotation = BITS(10, 11) * 8; | ||
| 6307 | u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF); | ||
| 6308 | if (rm & 0x80) | ||
| 6309 | rm |= 0xffffff00; | ||
| 6310 | |||
| 6311 | // SXTB, otherwise SXTAB | ||
| 6312 | if (BITS(16, 19) == 0xf) | ||
| 6313 | state->Reg[BITS(12, 15)] = rm; | ||
| 6314 | else | ||
| 6315 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6316 | |||
| 6317 | return 1; | ||
| 6318 | } | ||
| 6319 | else { | ||
| 6320 | printf("Unimplemented op: SSAT"); | ||
| 6321 | } | ||
| 6322 | } | ||
| 6323 | break; | ||
| 6324 | |||
| 6325 | case 0x6b: // REV, REV16, SXTH, and SXTAH | ||
| 6326 | { | ||
| 6327 | const u8 op2 = BITS(5, 7); | ||
| 6328 | |||
| 6329 | // REV | ||
| 6330 | if (op2 == 0x01) { | ||
| 6331 | DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); | ||
| 6332 | return 1; | ||
| 6333 | } | ||
| 6334 | // REV16 | ||
| 6335 | else if (op2 == 0x05) { | ||
| 6336 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); | ||
| 6337 | return 1; | ||
| 6338 | } | ||
| 6339 | else if (op2 == 0x03) { | ||
| 6340 | const u8 rotate = BITS(10, 11) * 8; | ||
| 6341 | |||
| 6342 | u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); | ||
| 6343 | if (rm & 0x8000) | ||
| 6344 | rm |= 0xffff0000; | ||
| 6345 | |||
| 6346 | // SXTH, otherwise SXTAH | ||
| 6347 | if (BITS(16, 19) == 15) | ||
| 6348 | state->Reg[BITS(12, 15)] = rm; | ||
| 6349 | else | ||
| 6350 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6351 | |||
| 6352 | return 1; | ||
| 6353 | } | ||
| 6354 | } | ||
| 6355 | break; | ||
| 6356 | |||
| 6357 | case 0x6c: // UXTB16 and UXTAB16 | ||
| 6358 | { | ||
| 6359 | const u8 rm_idx = BITS(0, 3); | ||
| 6360 | const u8 rn_idx = BITS(16, 19); | ||
| 6361 | const u8 rd_idx = BITS(12, 15); | ||
| 6362 | const u32 rm_val = state->Reg[rm_idx]; | ||
| 6363 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 6364 | const u32 rotation = BITS(10, 11) * 8; | ||
| 6365 | const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | ||
| 6366 | |||
| 6367 | // UXTB16 | ||
| 6368 | if ((instr & 0xf03f0) == 0xf0070) { | ||
| 6369 | state->Reg[rd_idx] = rotated_rm & 0x00FF00FF; | ||
| 6370 | } | ||
| 6371 | else { // UXTAB16 | ||
| 6372 | const u8 lo_rotated = (rotated_rm & 0xFF); | ||
| 6373 | const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; | ||
| 6374 | |||
| 6375 | const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; | ||
| 6376 | const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; | ||
| 6377 | |||
| 6378 | state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF)); | ||
| 6379 | } | ||
| 6380 | |||
| 6381 | return 1; | ||
| 6382 | } | ||
| 6383 | break; | ||
| 6384 | case 0x6e: // USAT, USAT16, UXTB, and UXTAB | ||
| 6385 | { | ||
| 6386 | const u8 op2 = BITS(5, 7); | ||
| 6387 | |||
| 6388 | // USAT16 | ||
| 6389 | if (op2 == 0x01) { | ||
| 6390 | const u8 rd_idx = BITS(12, 15); | ||
| 6391 | const u8 rn_idx = BITS(0, 3); | ||
| 6392 | const u8 num_bits = BITS(16, 19); | ||
| 6393 | const s16 max = 0xFFFF >> (16 - num_bits); | ||
| 6394 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6395 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6396 | |||
| 6397 | if (max < rn_lo) { | ||
| 6398 | rn_lo = max; | ||
| 6399 | SETQ; | ||
| 6400 | } else if (rn_lo < 0) { | ||
| 6401 | rn_lo = 0; | ||
| 6402 | SETQ; | ||
| 6403 | } | ||
| 6404 | |||
| 6405 | if (max < rn_hi) { | ||
| 6406 | rn_hi = max; | ||
| 6407 | SETQ; | ||
| 6408 | } else if (rn_hi < 0) { | ||
| 6409 | rn_hi = 0; | ||
| 6410 | SETQ; | ||
| 6411 | } | ||
| 6412 | |||
| 6413 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); | ||
| 6414 | return 1; | ||
| 6415 | } | ||
| 6416 | else if (op2 == 0x03) { | ||
| 6417 | const u8 rotate = BITS(10, 11) * 8; | ||
| 6418 | const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF); | ||
| 6419 | |||
| 6420 | if (BITS(16, 19) == 0xf) | ||
| 6421 | /* UXTB */ | ||
| 6422 | state->Reg[BITS(12, 15)] = rm; | ||
| 6423 | else | ||
| 6424 | /* UXTAB */ | ||
| 6425 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6426 | |||
| 6427 | return 1; | ||
| 6428 | } | ||
| 6429 | else { | ||
| 6430 | printf("Unimplemented op: USAT"); | ||
| 6431 | } | ||
| 6432 | } | ||
| 6433 | break; | ||
| 6434 | |||
| 6435 | case 0x6f: // UXTH, UXTAH, and REVSH. | ||
| 6436 | { | ||
| 6437 | const u8 op2 = BITS(5, 7); | ||
| 6438 | |||
| 6439 | // REVSH | ||
| 6440 | if (op2 == 0x05) { | ||
| 6441 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); | ||
| 6442 | if (DEST & 0x8000) | ||
| 6443 | DEST |= 0xffff0000; | ||
| 6444 | return 1; | ||
| 6445 | } | ||
| 6446 | // UXTH and UXTAH | ||
| 6447 | else if (op2 == 0x03) { | ||
| 6448 | const u8 rotate = BITS(10, 11) * 8; | ||
| 6449 | const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); | ||
| 6450 | |||
| 6451 | // UXTH | ||
| 6452 | if (BITS(16, 19) == 0xf) { | ||
| 6453 | state->Reg[BITS(12, 15)] = rm; | ||
| 6454 | } | ||
| 6455 | // UXTAH | ||
| 6456 | else { | ||
| 6457 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6458 | } | ||
| 6459 | |||
| 6460 | return 1; | ||
| 6461 | } | ||
| 6462 | } | ||
| 6463 | case 0x70: | ||
| 6464 | // ichfly | ||
| 6465 | // SMUAD, SMUSD, SMLAD, and SMLSD | ||
| 6466 | if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 || | ||
| 6467 | (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50) | ||
| 6468 | { | ||
| 6469 | const u8 rd_idx = BITS(16, 19); | ||
| 6470 | const u8 rn_idx = BITS(0, 3); | ||
| 6471 | const u8 rm_idx = BITS(8, 11); | ||
| 6472 | const u8 ra_idx = BITS(12, 15); | ||
| 6473 | const bool do_swap = (BIT(5) == 1); | ||
| 5976 | 6474 | ||
| 5977 | case 0x1d: { /* BICS reg */ | 6475 | u32 rm_val = state->Reg[rm_idx]; |
| 5978 | if ((BITS (4, 7)) == 0x9) { | 6476 | const u32 rn_val = state->Reg[rn_idx]; |
| 5979 | /* ldrexb */ | ||
| 5980 | temp = LHS; | ||
| 5981 | LoadByte (state, instr, temp, LUNSIGNED); | ||
| 5982 | 6477 | ||
| 5983 | state->currentexaddr = temp; | 6478 | if (do_swap) |
| 5984 | state->currentexval = (u32)ARMul_ReadByte(state, temp); | 6479 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); |
| 5985 | 6480 | ||
| 5986 | //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]); | 6481 | const s16 rm_lo = (rm_val & 0xFFFF); |
| 5987 | //printf("ldrexb\n"); | 6482 | const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); |
| 5988 | //printf("instr is %x rm is %d\n", instr, BITS(16, 19)); | 6483 | const s16 rn_lo = (rn_val & 0xFFFF); |
| 5989 | //exit(-1); | 6484 | const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); |
| 5990 | 6485 | ||
| 5991 | //printf("In %s, ldrexb not implemented\n", __FUNCTION__); | 6486 | const u32 product1 = (rn_lo * rm_lo); |
| 5992 | return 1; | 6487 | const u32 product2 = (rn_hi * rm_hi); |
| 5993 | } | ||
| 5994 | break; | ||
| 5995 | } | ||
| 5996 | /* add end */ | ||
| 5997 | 6488 | ||
| 5998 | case 0x6a: { | 6489 | // SMUAD and SMLAD |
| 5999 | ARMword Rm; | 6490 | if (BIT(6) == 0) { |
| 6000 | int ror = -1; | 6491 | state->Reg[rd_idx] = product1 + product2; |
| 6001 | 6492 | ||
| 6002 | switch (BITS (4, 11)) { | 6493 | if (BITS(12, 15) != 15) { |
| 6003 | case 0x07: | 6494 | state->Reg[rd_idx] += state->Reg[ra_idx]; |
| 6004 | ror = 0; | 6495 | ARMul_AddOverflowQ(state, product1 + product2, state->Reg[ra_idx]); |
| 6005 | break; | 6496 | } |
| 6006 | case 0x47: | ||
| 6007 | ror = 8; | ||
| 6008 | break; | ||
| 6009 | case 0x87: | ||
| 6010 | ror = 16; | ||
| 6011 | break; | ||
| 6012 | case 0xc7: | ||
| 6013 | ror = 24; | ||
| 6014 | break; | ||
| 6015 | 6497 | ||
| 6016 | case 0x01: | 6498 | ARMul_AddOverflowQ(state, product1, product2); |
| 6017 | case 0xf3: | 6499 | } |
| 6018 | //ichfly | 6500 | // SMUSD and SMLSD |
| 6019 | //SSAT16 | 6501 | else { |
| 6020 | { | 6502 | state->Reg[rd_idx] = product1 - product2; |
| 6021 | u8 tar = BITS(12,15); | 6503 | |
| 6022 | u8 src = BITS(0, 3); | 6504 | if (BITS(12, 15) != 15) |
| 6023 | u8 val = BITS(16, 19) + 1; | 6505 | state->Reg[rd_idx] += state->Reg[ra_idx]; |
| 6024 | s16 a1 = (state->Reg[src]); | 6506 | } |
| 6025 | s16 a2 = (state->Reg[src] >> 0x10); | ||
| 6026 | s16 min = (s16)(0x8000) >> (16 - val); | ||
| 6027 | s16 max = 0x7FFF >> (16 - val); | ||
| 6028 | if (min > a1) a1 = min; | ||
| 6029 | if (max < a1) a1 = max; | ||
| 6030 | if (min > a2) a2 = min; | ||
| 6031 | if (max < a2) a2 = max; | ||
| 6032 | u32 temp2 = ((u32)(a2)) << 0x10; | ||
| 6033 | state->Reg[tar] = (a1&0xFFFF) | (temp2); | ||
| 6034 | } | ||
| 6035 | 6507 | ||
| 6036 | return 1; | 6508 | return 1; |
| 6037 | default: | ||
| 6038 | break; | ||
| 6039 | } | 6509 | } |
| 6040 | 6510 | break; | |
| 6041 | if (ror == -1) { | 6511 | case 0x74: // SMLALD and SMLSLD |
| 6042 | if (BITS (4, 6) == 0x7) { | 6512 | { |
| 6043 | printf ("Unhandled v6 insn: ssat\n"); | 6513 | const u8 rm_idx = BITS(8, 11); |
| 6044 | return 0; | 6514 | const u8 rn_idx = BITS(0, 3); |
| 6515 | const u8 rdlo_idx = BITS(12, 15); | ||
| 6516 | const u8 rdhi_idx = BITS(16, 19); | ||
| 6517 | const bool do_swap = (BIT(5) == 1); | ||
| 6518 | |||
| 6519 | const u32 rdlo_val = state->Reg[rdlo_idx]; | ||
| 6520 | const u32 rdhi_val = state->Reg[rdhi_idx]; | ||
| 6521 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 6522 | u32 rm_val = state->Reg[rm_idx]; | ||
| 6523 | |||
| 6524 | if (do_swap) | ||
| 6525 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); | ||
| 6526 | |||
| 6527 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); | ||
| 6528 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); | ||
| 6529 | s64 result; | ||
| 6530 | |||
| 6531 | // SMLALD | ||
| 6532 | if (BIT(6) == 0) { | ||
| 6533 | result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 6534 | } | ||
| 6535 | // SMLSLD | ||
| 6536 | else { | ||
| 6537 | result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 6045 | } | 6538 | } |
| 6046 | break; | ||
| 6047 | } | ||
| 6048 | |||
| 6049 | Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); | ||
| 6050 | if (Rm & 0x80) | ||
| 6051 | Rm |= 0xffffff00; | ||
| 6052 | |||
| 6053 | if (BITS (16, 19) == 0xf) | ||
| 6054 | /* SXTB */ | ||
| 6055 | state->Reg[BITS (12, 15)] = Rm; | ||
| 6056 | else | ||
| 6057 | /* SXTAB */ | ||
| 6058 | state->Reg[BITS (12, 15)] += Rm; | ||
| 6059 | } | ||
| 6060 | return 1; | ||
| 6061 | |||
| 6062 | case 0x6b: { | ||
| 6063 | ARMword Rm; | ||
| 6064 | int ror = -1; | ||
| 6065 | |||
| 6066 | switch (BITS (4, 11)) { | ||
| 6067 | case 0x07: | ||
| 6068 | ror = 0; | ||
| 6069 | break; | ||
| 6070 | case 0x47: | ||
| 6071 | ror = 8; | ||
| 6072 | break; | ||
| 6073 | case 0x87: | ||
| 6074 | ror = 16; | ||
| 6075 | break; | ||
| 6076 | case 0xc7: | ||
| 6077 | ror = 24; | ||
| 6078 | break; | ||
| 6079 | 6539 | ||
| 6080 | case 0xf3: | 6540 | state->Reg[rdlo_idx] = (result & 0xFFFFFFFF); |
| 6081 | DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); | 6541 | state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF); |
| 6082 | return 1; | 6542 | return 1; |
| 6083 | case 0xfb: | ||
| 6084 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); | ||
| 6085 | return 1; | ||
| 6086 | default: | ||
| 6087 | break; | ||
| 6088 | } | 6543 | } |
| 6544 | break; | ||
| 6545 | case 0x75: // SMMLA, SMMUL, and SMMLS | ||
| 6546 | { | ||
| 6547 | const u8 rm_idx = BITS(8, 11); | ||
| 6548 | const u8 rn_idx = BITS(0, 3); | ||
| 6549 | const u8 ra_idx = BITS(12, 15); | ||
| 6550 | const u8 rd_idx = BITS(16, 19); | ||
| 6551 | const bool do_round = (BIT(5) == 1); | ||
| 6089 | 6552 | ||
| 6090 | if (ror == -1) | 6553 | const u32 rm_val = state->Reg[rm_idx]; |
| 6091 | break; | 6554 | const u32 rn_val = state->Reg[rn_idx]; |
| 6092 | 6555 | ||
| 6093 | Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); | 6556 | // Assume SMMUL by default. |
| 6094 | if (Rm & 0x8000) | 6557 | s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; |
| 6095 | Rm |= 0xffff0000; | ||
| 6096 | 6558 | ||
| 6097 | if (BITS (16, 19) == 0xf) | 6559 | if (ra_idx != 15) { |
| 6098 | /* SXTH */ | 6560 | const u32 ra_val = state->Reg[ra_idx]; |
| 6099 | state->Reg[BITS (12, 15)] = Rm; | ||
| 6100 | else | ||
| 6101 | /* SXTAH */ | ||
| 6102 | state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; | ||
| 6103 | } | ||
| 6104 | return 1; | ||
| 6105 | 6561 | ||
| 6106 | case 0x6e: { | 6562 | // SMMLA, otherwise SMMLS |
| 6107 | ARMword Rm; | 6563 | if (BIT(6) == 0) |
| 6108 | int ror = -1; | 6564 | result += ((s64)ra_val << 32); |
| 6565 | else | ||
| 6566 | result = ((s64)ra_val << 32) - result; | ||
| 6567 | } | ||
| 6109 | 6568 | ||
| 6110 | switch (BITS (4, 11)) { | 6569 | if (do_round) |
| 6111 | case 0x07: | 6570 | result += 0x80000000; |
| 6112 | ror = 0; | ||
| 6113 | break; | ||
| 6114 | case 0x47: | ||
| 6115 | ror = 8; | ||
| 6116 | break; | ||
| 6117 | case 0x87: | ||
| 6118 | ror = 16; | ||
| 6119 | break; | ||
| 6120 | case 0xc7: | ||
| 6121 | ror = 24; | ||
| 6122 | break; | ||
| 6123 | 6571 | ||
| 6124 | case 0x01: | 6572 | state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF); |
| 6125 | case 0xf3: | ||
| 6126 | //ichfly | ||
| 6127 | //USAT16 | ||
| 6128 | { | ||
| 6129 | u8 tar = BITS(12, 15); | ||
| 6130 | u8 src = BITS(0, 3); | ||
| 6131 | u8 val = BITS(16, 19); | ||
| 6132 | s16 a1 = (state->Reg[src]); | ||
| 6133 | s16 a2 = (state->Reg[src] >> 0x10); | ||
| 6134 | s16 max = 0xFFFF >> (16 - val); | ||
| 6135 | if (max < a1) a1 = max; | ||
| 6136 | if (max < a2) a2 = max; | ||
| 6137 | u32 temp2 = ((u32)(a2)) << 0x10; | ||
| 6138 | state->Reg[tar] = (a1 & 0xFFFF) | (temp2); | ||
| 6139 | } | ||
| 6140 | return 1; | 6573 | return 1; |
| 6141 | default: | ||
| 6142 | break; | ||
| 6143 | } | ||
| 6144 | |||
| 6145 | if (ror == -1) { | ||
| 6146 | if (BITS (4, 6) == 0x7) { | ||
| 6147 | printf ("Unhandled v6 insn: usat\n"); | ||
| 6148 | return 0; | ||
| 6149 | } | ||
| 6150 | break; | ||
| 6151 | } | 6574 | } |
| 6575 | break; | ||
| 6576 | case 0x78: | ||
| 6577 | if (BITS(20, 24) == 0x18) | ||
| 6578 | { | ||
| 6579 | const u8 rm_idx = BITS(8, 11); | ||
| 6580 | const u8 rn_idx = BITS(0, 3); | ||
| 6581 | const u8 rd_idx = BITS(16, 19); | ||
| 6152 | 6582 | ||
| 6153 | Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); | 6583 | const u32 rm_val = state->Reg[rm_idx]; |
| 6154 | 6584 | const u32 rn_val = state->Reg[rn_idx]; | |
| 6155 | if (BITS (16, 19) == 0xf) | ||
| 6156 | /* UXTB */ | ||
| 6157 | state->Reg[BITS (12, 15)] = Rm; | ||
| 6158 | else | ||
| 6159 | /* UXTAB */ | ||
| 6160 | state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; | ||
| 6161 | } | ||
| 6162 | return 1; | ||
| 6163 | 6585 | ||
| 6164 | case 0x6f: { | 6586 | const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); |
| 6165 | ARMword Rm; | 6587 | const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); |
| 6166 | int ror = -1; | 6588 | const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); |
| 6589 | const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); | ||
| 6167 | 6590 | ||
| 6168 | switch (BITS (4, 11)) { | 6591 | u32 finalDif = (diff1 + diff2 + diff3 + diff4); |
| 6169 | case 0x07: | ||
| 6170 | ror = 0; | ||
| 6171 | break; | ||
| 6172 | case 0x47: | ||
| 6173 | ror = 8; | ||
| 6174 | break; | ||
| 6175 | case 0x87: | ||
| 6176 | ror = 16; | ||
| 6177 | break; | ||
| 6178 | case 0xc7: | ||
| 6179 | ror = 24; | ||
| 6180 | break; | ||
| 6181 | 6592 | ||
| 6182 | case 0xfb: | 6593 | // Op is USADA8 if true. |
| 6183 | printf ("Unhandled v6 insn: revsh\n"); | 6594 | const u8 ra_idx = BITS(12, 15); |
| 6184 | return 0; | 6595 | if (ra_idx != 15) |
| 6185 | default: | 6596 | finalDif += state->Reg[ra_idx]; |
| 6186 | break; | ||
| 6187 | } | ||
| 6188 | 6597 | ||
| 6189 | if (ror == -1) | 6598 | state->Reg[rd_idx] = finalDif; |
| 6190 | break; | 6599 | return 1; |
| 6191 | |||
| 6192 | Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); | ||
| 6193 | |||
| 6194 | /* UXT */ | ||
| 6195 | /* state->Reg[BITS (12, 15)] = Rm; */ | ||
| 6196 | /* dyf add */ | ||
| 6197 | if (BITS (16, 19) == 0xf) { | ||
| 6198 | state->Reg[BITS (12, 15)] = (Rm >> (8 * BITS(10, 11))) & 0x0000FFFF; | ||
| 6199 | } else { | ||
| 6200 | /* UXTAH */ | ||
| 6201 | /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */ | ||
| 6202 | // printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)] | ||
| 6203 | // , Rm, BITS(10, 11)); | ||
| 6204 | // printf("icounter is %lld\n", state->NumInstrs); | ||
| 6205 | state->Reg[BITS (12, 15)] = (state->Reg[BITS (16, 19)] >> (8 * (BITS(10, 11)))) + Rm; | ||
| 6206 | // printf("rd is %x\n", state->Reg[BITS (12, 15)]); | ||
| 6207 | // exit(-1); | ||
| 6208 | } | 6600 | } |
| 6209 | } | 6601 | break; |
| 6210 | return 1; | 6602 | case 0x7a: |
| 6211 | 6603 | printf ("Unhandled v6 insn: usbfx\n"); | |
| 6212 | #if 0 | 6604 | break; |
| 6605 | case 0x7c: | ||
| 6606 | printf ("Unhandled v6 insn: bfc/bfi\n"); | ||
| 6607 | break; | ||
| 6213 | case 0x84: | 6608 | case 0x84: |
| 6214 | printf ("Unhandled v6 insn: srs\n"); | 6609 | printf ("Unhandled v6 insn: srs\n"); |
| 6215 | break; | 6610 | break; |
| 6216 | #endif | ||
| 6217 | default: | 6611 | default: |
| 6218 | break; | 6612 | break; |
| 6219 | } | 6613 | } |
| 6220 | printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27)); | 6614 | printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27)); |
| 6221 | return 0; | 6615 | return 0; |
| 6222 | } | 6616 | } \ No newline at end of file |