aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/interpreter/armemu.cpp152
1 files changed, 84 insertions, 68 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 5074542a..a36035e9 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -3109,12 +3109,18 @@ mainswitch:
state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000);
break;
} else if ((instr & 0x70) == 0x50) { //pkhtb
- u8 idest = BITS(12, 15);
- u8 rfis = BITS(16, 19);
- u8 rlast = BITS(0, 3);
- u8 ishi = BITS(7, 11);
- if (ishi == 0)ishi = 0x20;
- state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000);
+ const u8 rd_idx = BITS(12, 15);
+ const u8 rn_idx = BITS(16, 19);
+ const u8 rm_idx = BITS(0, 3);
+ const u8 imm5 = BITS(7, 11);
+
+ ARMword val;
+ if (imm5 >= 32)
+ val = (state->Reg[rm_idx] >> 31);
+ else
+ val = (state->Reg[rm_idx] >> imm5);
+
+ state->Reg[rd_idx] = (val & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
break;
} else if (BIT (4)) {
#ifdef MODE32
@@ -5823,24 +5829,25 @@ L_stm_s_takeabort:
break;
case 0x61:
if ((instr & 0xFF0) == 0xf70) { //ssub16
- u8 tar = BITS(12, 15);
- u8 src1 = BITS(16, 19);
- u8 src2 = BITS(0, 3);
- s16 a1 = (state->Reg[src1] & 0xFFFF);
- s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
- s16 b1 = (state->Reg[src2] & 0xFFFF);
- s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = ((a1 - a2) & 0xFFFF) | (((b1 - b2) & 0xFFFF) << 0x10);
+ const u8 rd_idx = BITS(12, 15);
+ const u8 rm_idx = BITS(0, 3);
+ const u8 rn_idx = BITS(16, 19);
+ const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
+ const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF);
+ const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
+ const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF);
+ state->Reg[rd_idx] = ((rn_lo - rm_lo) & 0xFFFF) | (((rn_hi - rm_hi) & 0xFFFF) << 16);
return 1;
} else if ((instr & 0xFF0) == 0xf10) { //sadd16
- u8 tar = BITS(12, 15);
- u8 src1 = BITS(16, 19);
- u8 src2 = BITS(0, 3);
- s16 a1 = (state->Reg[src1] & 0xFFFF);
- s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
- s16 b1 = (state->Reg[src2] & 0xFFFF);
- s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = ((a1 + a2) & 0xFFFF) | (((b1 + b2) & 0xFFFF) << 0x10);
+ const u8 rd_idx = BITS(12, 15);
+ const u8 rm_idx = BITS(0, 3);
+ const u8 rn_idx = BITS(16, 19);
+ const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
+ const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF);
+ const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
+ const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF);
+
+ state->Reg[rd_idx] = ((rn_lo + rm_lo) & 0xFFFF) | (((rn_hi + rm_hi) & 0xFFFF) << 16);
return 1;
} else if ((instr & 0xFF0) == 0xf50) { //ssax
u8 tar = BITS(12, 15);
@@ -5864,40 +5871,44 @@ L_stm_s_takeabort:
return 1;
} else printf ("Unhandled v6 insn: sadd/ssub/ssax/sasx\n");
break;
- case 0x62:
- if ((instr & 0xFF0) == 0xf70) { //QSUB16
- u8 tar = BITS(12, 15);
- u8 src1 = BITS(16, 19);
- u8 src2 = BITS(0, 3);
- s16 a1 = (state->Reg[src1] & 0xFFFF);
- s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
- s16 b1 = (state->Reg[src2] & 0xFFFF);
- s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- s32 res1 = (a1 - b1);
- s32 res2 = (a2 - b2);
- if (res1 > 0x7FFF) res1 = 0x7FFF;
- if (res2 > 0x7FFF) res2 = 0x7FFF;
- if (res1 < 0x7FFF) res1 = -0x8000;
- if (res2 < 0x7FFF) res2 = -0x8000;
- state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10);
- return 1;
- } else if ((instr & 0xFF0) == 0xf10) { //QADD16
- u8 tar = BITS(12, 15);
- u8 src1 = BITS(16, 19);
- u8 src2 = BITS(0, 3);
- s16 a1 = (state->Reg[src1] & 0xFFFF);
- s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
- s16 b1 = (state->Reg[src2] & 0xFFFF);
- s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- s32 res1 = (a1 + b1);
- s32 res2 = (a2 + b2);
- if (res1 > 0x7FFF) res1 = 0x7FFF;
- if (res2 > 0x7FFF) res2 = 0x7FFF;
- if (res1 < 0x7FFF) res1 = -0x8000;
- if (res2 < 0x7FFF) res2 = -0x8000;
- state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10);
+ case 0x62: // QSUB16 and QADD16
+ if ((instr & 0xFF0) == 0xf70 || (instr & 0xFF0) == 0xf10) {
+ const u8 rd_idx = BITS(12, 15);
+ const u8 rn_idx = BITS(16, 19);
+ const u8 rm_idx = BITS(0, 3);
+ const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
+ const s16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
+ const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
+ const s16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
+
+ s32 lo_result;
+ s32 hi_result;
+
+ // QSUB16
+ if ((instr & 0xFF0) == 0xf70) {
+ lo_result = (rn_lo - rm_lo);
+ hi_result = (rn_hi - rm_hi);
+ }
+ else { // QADD16
+ lo_result = (rn_lo + rm_lo);
+ hi_result = (rn_hi + rm_hi);
+ }
+
+ if (lo_result > 0x7FFF)
+ lo_result = 0x7FFF;
+ else if (lo_result < -0x8000)
+ lo_result = -0x8000;
+
+ if (hi_result > 0x7FFF)
+ hi_result = 0x7FFF;
+ else if (hi_result < -0x8000)
+ hi_result = -0x8000;
+
+ state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
return 1;
- } else printf ("Unhandled v6 insn: qadd16/qsub16\n");
+ } else {
+ printf("Unhandled v6 insn: %08x", BITS(20, 27));
+ }
break;
case 0x63:
printf ("Unhandled v6 insn: shadd/shsub\n");
@@ -6066,7 +6077,7 @@ L_stm_s_takeabort:
break;
}
- Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF);
+ Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | ((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF;
if (Rm & 0x80)
Rm |= 0xffffff00;
@@ -6075,11 +6086,12 @@ L_stm_s_takeabort:
state->Reg[BITS(12, 15)] = Rm;
else
/* SXTAB */
- state->Reg[BITS(12, 15)] += Rm;
+ state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm;
return 1;
}
- case 0x6b: {
+ case 0x6b:
+ {
ARMword Rm;
int ror = -1;
@@ -6097,10 +6109,10 @@ L_stm_s_takeabort:
ror = 24;
break;
- case 0xf3:
+ case 0xf3: // REV
DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24);
return 1;
- case 0xfb:
+ case 0xfb: // REV16
DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
return 1;
default:
@@ -6110,7 +6122,7 @@ L_stm_s_takeabort:
if (ror == -1)
break;
- Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF);
+ Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | ((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF;
if (Rm & 0x8000)
Rm |= 0xffff0000;
@@ -6197,7 +6209,7 @@ L_stm_s_takeabort:
break;
}
- Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF);
+ Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | ((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF;
if (BITS(16, 19) == 0xf)
/* UXTB */
@@ -6227,9 +6239,13 @@ L_stm_s_takeabort:
ror = 24;
break;
- case 0xfb:
- printf("Unhandled v6 insn: revsh\n");
- return 0;
+ case 0xfb: // REVSH
+ {
+ DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
+ if (DEST & 0x8000)
+ DEST |= 0xffff0000;
+ return 1;
+ }
default:
break;
}
@@ -6237,13 +6253,13 @@ L_stm_s_takeabort:
if (ror == -1)
break;
- Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF);
+ Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | ((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF;
/* UXT */
/* state->Reg[BITS (12, 15)] = Rm; */
/* dyf add */
if (BITS(16, 19) == 0xf) {
- state->Reg[BITS(12, 15)] = (Rm >> (8 * BITS(10, 11))) & 0x0000FFFF;
+ state->Reg[BITS(12, 15)] = Rm;
}
else {
/* UXTAH */
@@ -6251,7 +6267,7 @@ L_stm_s_takeabort:
// printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)]
// , Rm, BITS(10, 11));
// printf("icounter is %lld\n", state->NumInstrs);
- state->Reg[BITS(12, 15)] = (state->Reg[BITS(16, 19)] >> (8 * (BITS(10, 11)))) + Rm;
+ state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm;
// printf("rd is %x\n", state->Reg[BITS (12, 15)]);
// exit(-1);
}