diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 119 |
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 | { |