summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2014-12-28 12:19:31 -0500
committerGravatar Lioncash2014-12-28 12:19:31 -0500
commit6ce2a38ec401019e96ab0e6896cb3cb59e64752e (patch)
treebe1aaae6bc2a879193eafdcb4c731c555d75ef58 /src
parentarmemu: Simplify REV/REV16/SXTH/SXTAH (diff)
downloadyuzu-6ce2a38ec401019e96ab0e6896cb3cb59e64752e.tar.gz
yuzu-6ce2a38ec401019e96ab0e6896cb3cb59e64752e.tar.xz
yuzu-6ce2a38ec401019e96ab0e6896cb3cb59e64752e.zip
armemu: Simplify SSAT/SSAT16/SXTB/SXTAB
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp119
1 files changed, 48 insertions, 71 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 1b3a3478d..01d4e7708 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6272,84 +6272,61 @@ L_stm_s_takeabort:
6272 return 1; 6272 return 1;
6273 } 6273 }
6274 } 6274 }
6275 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); 6275 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n");
6276 break; 6276 break;
6277 case 0x6a: {
6278 ARMword Rm;
6279 int ror = -1;
6280
6281 switch (BITS(4, 11)) {
6282 case 0x07:
6283 ror = 0;
6284 break;
6285 case 0x47:
6286 ror = 8;
6287 break;
6288 case 0x87:
6289 ror = 16;
6290 break;
6291 case 0xc7:
6292 ror = 24;
6293 break;
6294
6295 case 0x01:
6296 case 0xf3:
6297 //ichfly
6298 //SSAT16
6299 {
6300 const u8 rd_idx = BITS(12, 15);
6301 const u8 rn_idx = BITS(0, 3);
6302 const u8 num_bits = BITS(16, 19) + 1;
6303 const s16 min = -(0x8000 >> (16 - num_bits));
6304 const s16 max = (0x7FFF >> (16 - num_bits));
6305 s16 rn_lo = (state->Reg[rn_idx]);
6306 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6307
6308 if (rn_lo > max) {
6309 rn_lo = max;
6310 SETQ;
6311 } else if (rn_lo < min) {
6312 rn_lo = min;
6313 SETQ;
6314 }
6315
6316 if (rn_hi > max) {
6317 rn_hi = max;
6318 SETQ;
6319 } else if (rn_hi < min) {
6320 rn_hi = min;
6321 SETQ;
6322 }
6323
6324 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6325 return 1;
6326 }
6327 6277
6328 default: 6278 case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB
6329 break; 6279 {
6330 } 6280 const u8 op2 = BITS(5, 7);
6281
6282 // SSAT16
6283 if (op2 == 0x01) {
6284 const u8 rd_idx = BITS(12, 15);
6285 const u8 rn_idx = BITS(0, 3);
6286 const u8 num_bits = BITS(16, 19) + 1;
6287 const s16 min = -(0x8000 >> (16 - num_bits));
6288 const s16 max = (0x7FFF >> (16 - num_bits));
6289 s16 rn_lo = (state->Reg[rn_idx]);
6290 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6331 6291
6332 if (ror == -1) { 6292 if (rn_lo > max) {
6333 if (BITS(4, 6) == 0x7) { 6293 rn_lo = max;
6334 printf("Unhandled v6 insn: ssat\n"); 6294 SETQ;
6335 return 0; 6295 } else if (rn_lo < min) {
6296 rn_lo = min;
6297 SETQ;
6336 } 6298 }
6337 break;
6338 }
6339 6299
6340 Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); 6300 if (rn_hi > max) {
6341 if (Rm & 0x80) 6301 rn_hi = max;
6342 Rm |= 0xffffff00; 6302 SETQ;
6303 } else if (rn_hi < min) {
6304 rn_hi = min;
6305 SETQ;
6306 }
6343 6307
6344 if (BITS(16, 19) == 0xf) 6308 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6345 /* SXTB */ 6309 return 1;
6346 state->Reg[BITS(12, 15)] = Rm; 6310 }
6347 else 6311 else if (op2 == 0x03) {
6348 /* SXTAB */ 6312 const u8 rotation = BITS(10, 11) * 8;
6349 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; 6313 u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF);
6314 if (rm & 0x80)
6315 rm |= 0xffffff00;
6316
6317 // SXTB, otherwise SXTAB
6318 if (BITS(16, 19) == 0xf)
6319 state->Reg[BITS(12, 15)] = rm;
6320 else
6321 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6350 6322
6351 return 1; 6323 return 1;
6324 }
6325 else {
6326 printf("Unimplemented op: SSAT");
6327 }
6352 } 6328 }
6329 break;
6353 6330
6354 case 0x6b: // REV, REV16, SXTH, and SXTAH 6331 case 0x6b: // REV, REV16, SXTH, and SXTAH
6355 { 6332 {