summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bunnei2014-12-27 00:34:39 -0500
committerGravatar bunnei2014-12-27 00:34:39 -0500
commitb48ca7878b8e56b3a819fbf532e5ed3681fda477 (patch)
treef17801a29270200ab5adcceeac8be06922c56346 /src/core
parentMerge pull request #327 from Apology11/master (diff)
parentarmemu: Implement UHADD8, UHADD16, UHSUB8, UHSUB16, UHASX, and UHSAX (diff)
downloadyuzu-b48ca7878b8e56b3a819fbf532e5ed3681fda477.tar.gz
yuzu-b48ca7878b8e56b3a819fbf532e5ed3681fda477.tar.xz
yuzu-b48ca7878b8e56b3a819fbf532e5ed3681fda477.zip
Merge pull request #348 from lioncash/uhops
armemu: Implement UHADD8, UHADD16, UHSUB8, UHSUB16, UHASX, and UHSAX
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/interpreter/armemu.cpp75
1 files changed, 73 insertions, 2 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index d54dbeac5..9b680c1e2 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6139,8 +6139,79 @@ L_stm_s_takeabort:
6139 printf ("Unhandled v6 insn: uqsub16\n"); 6139 printf ("Unhandled v6 insn: uqsub16\n");
6140 } 6140 }
6141 break; 6141 break;
6142 case 0x67: 6142 case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8.
6143 printf ("Unhandled v6 insn: uhadd/uhsub\n"); 6143 {
6144 const u8 op2 = BITS(5, 7);
6145
6146 const u8 rm_idx = BITS(0, 3);
6147 const u8 rn_idx = BITS(16, 19);
6148 const u8 rd_idx = BITS(12, 15);
6149
6150 const u32 rm_val = state->Reg[rm_idx];
6151 const u32 rn_val = state->Reg[rn_idx];
6152
6153 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
6154 {
6155 u32 lo_val = 0;
6156 u32 hi_val = 0;
6157
6158 // UHADD16
6159 if (op2 == 0x00) {
6160 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
6161 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6162 }
6163 // UHASX
6164 else if (op2 == 0x01) {
6165 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6166 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
6167 }
6168 // UHSAX
6169 else if (op2 == 0x02) {
6170 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6171 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
6172 }
6173 // UHSUB16
6174 else if (op2 == 0x03) {
6175 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
6176 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6177 }
6178
6179 lo_val >>= 1;
6180 hi_val >>= 1;
6181
6182 state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
6183 return 1;
6184 }
6185 else if (op2 == 0x04 || op2 == 0x07) {
6186 u32 sum1;
6187 u32 sum2;
6188 u32 sum3;
6189 u32 sum4;
6190
6191 // UHADD8
6192 if (op2 == 0x04) {
6193 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
6194 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
6195 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
6196 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
6197 }
6198 // UHSUB8
6199 else {
6200 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
6201 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
6202 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
6203 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
6204 }
6205
6206 sum1 >>= 1;
6207 sum2 >>= 1;
6208 sum3 >>= 1;
6209 sum4 >>= 1;
6210
6211 state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
6212 return 1;
6213 }
6214 }
6144 break; 6215 break;
6145 case 0x68: 6216 case 0x68:
6146 { 6217 {