diff options
| author | 2014-12-25 13:33:49 -0500 | |
|---|---|---|
| committer | 2014-12-25 13:52:46 -0500 | |
| commit | 35dbfc7ab0514e04c4aec4514167bba875d01285 (patch) | |
| tree | 6389636a53f6002959ad11dc7dbc1fb79974ff7f /src/core | |
| parent | Merge pull request #328 from archshift/writeable (diff) | |
| download | yuzu-35dbfc7ab0514e04c4aec4514167bba875d01285.tar.gz yuzu-35dbfc7ab0514e04c4aec4514167bba875d01285.tar.xz yuzu-35dbfc7ab0514e04c4aec4514167bba875d01285.zip | |
armemu: Implement SMMUL, SMMLA, and SMMLS.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index b2f671f94..8d803a0af 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -6506,8 +6506,36 @@ L_stm_s_takeabort: | |||
| 6506 | case 0x74: | 6506 | case 0x74: |
| 6507 | printf ("Unhandled v6 insn: smlald/smlsld\n"); | 6507 | printf ("Unhandled v6 insn: smlald/smlsld\n"); |
| 6508 | break; | 6508 | break; |
| 6509 | case 0x75: | 6509 | case 0x75: // SMMLA, SMMUL, and SMMLS |
| 6510 | printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); | 6510 | { |
| 6511 | const u8 rm_idx = BITS(8, 11); | ||
| 6512 | const u8 rn_idx = BITS(0, 3); | ||
| 6513 | const u8 ra_idx = BITS(12, 15); | ||
| 6514 | const u8 rd_idx = BITS(16, 19); | ||
| 6515 | const bool do_round = (BIT(5) == 1); | ||
| 6516 | |||
| 6517 | const u32 rm_val = state->Reg[rm_idx]; | ||
| 6518 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 6519 | |||
| 6520 | // Assume SMMUL by default. | ||
| 6521 | s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; | ||
| 6522 | |||
| 6523 | if (ra_idx != 15) { | ||
| 6524 | const u32 ra_val = state->Reg[ra_idx]; | ||
| 6525 | |||
| 6526 | // SMMLA, otherwise SMMLS | ||
| 6527 | if (BIT(6) == 0) | ||
| 6528 | result += ((s64)ra_val << 32); | ||
| 6529 | else | ||
| 6530 | result = ((s64)ra_val << 32) - result; | ||
| 6531 | } | ||
| 6532 | |||
| 6533 | if (do_round) | ||
| 6534 | result += 0x80000000; | ||
| 6535 | |||
| 6536 | state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF); | ||
| 6537 | return 1; | ||
| 6538 | } | ||
| 6511 | break; | 6539 | break; |
| 6512 | case 0x78: | 6540 | case 0x78: |
| 6513 | if (BITS(20, 24) == 0x18) | 6541 | if (BITS(20, 24) == 0x18) |