diff options
| author | 2014-12-27 17:06:19 -0500 | |
|---|---|---|
| committer | 2014-12-27 17:06:19 -0500 | |
| commit | 60523113a9301e16bae91af61063bd8833926e8c (patch) | |
| tree | 772fa7009ce417b0388fa8f1e8fbf9bab0bfc631 /src | |
| parent | Merge pull request #349 from lioncash/uhdync (diff) | |
| download | yuzu-60523113a9301e16bae91af61063bd8833926e8c.tar.gz yuzu-60523113a9301e16bae91af61063bd8833926e8c.tar.xz yuzu-60523113a9301e16bae91af61063bd8833926e8c.zip | |
armemu: Implement UQADD8, UQADD16, UQSUB16, UQASX, and UQSAX
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 67 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 41 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armemu.h | 4 |
3 files changed, 93 insertions, 19 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 9b680c1e2..5d26456c7 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -6117,26 +6117,55 @@ L_stm_s_takeabort: | |||
| 6117 | } | 6117 | } |
| 6118 | printf("Unhandled v6 insn: uasx/usax\n"); | 6118 | printf("Unhandled v6 insn: uasx/usax\n"); |
| 6119 | break; | 6119 | break; |
| 6120 | case 0x66: | 6120 | case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8 |
| 6121 | if ((instr & 0x0FF00FF0) == 0x06600FF0) { //uqsub8 | 6121 | { |
| 6122 | u32 rd = (instr >> 12) & 0xF; | 6122 | const u8 rd_idx = BITS(12, 15); |
| 6123 | u32 rm = (instr >> 16) & 0xF; | 6123 | const u8 rm_idx = BITS(0, 3); |
| 6124 | u32 rn = (instr >> 0) & 0xF; | 6124 | const u8 rn_idx = BITS(16, 19); |
| 6125 | u32 subfrom = state->Reg[rm]; | 6125 | const u8 op2 = BITS(5, 7); |
| 6126 | u32 tosub = state->Reg[rn]; | 6126 | const u32 rm_val = state->Reg[rm_idx]; |
| 6127 | 6127 | const u32 rn_val = state->Reg[rn_idx]; | |
| 6128 | u8 b1 = (u8)((u8)(subfrom)-(u8)(tosub)); | 6128 | |
| 6129 | if (b1 > (u8)(subfrom)) b1 = 0; | 6129 | u16 lo_val = 0; |
| 6130 | u8 b2 = (u8)((u8)(subfrom >> 8) - (u8)(tosub >> 8)); | 6130 | u16 hi_val = 0; |
| 6131 | if (b2 > (u8)(subfrom >> 8)) b2 = 0; | 6131 | |
| 6132 | u8 b3 = (u8)((u8)(subfrom >> 16) - (u8)(tosub >> 16)); | 6132 | // UQADD16 |
| 6133 | if (b3 > (u8)(subfrom >> 16)) b3 = 0; | 6133 | if (op2 == 0x00) { |
| 6134 | u8 b4 = (u8)((u8)(subfrom >> 24) - (u8)(tosub >> 24)); | 6134 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); |
| 6135 | if (b4 > (u8)(subfrom >> 24)) b4 = 0; | 6135 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); |
| 6136 | state->Reg[rd] = (u32)(b1 | b2 << 8 | b3 << 16 | b4 << 24); | 6136 | } |
| 6137 | // UQASX | ||
| 6138 | else if (op2 == 0x01) { | ||
| 6139 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6140 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6141 | } | ||
| 6142 | // UQSAX | ||
| 6143 | else if (op2 == 0x02) { | ||
| 6144 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6145 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6146 | } | ||
| 6147 | // UQSUB16 | ||
| 6148 | else if (op2 == 0x03) { | ||
| 6149 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 6150 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6151 | } | ||
| 6152 | // UQADD8 | ||
| 6153 | else if (op2 == 0x04) { | ||
| 6154 | lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | | ||
| 6155 | ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6156 | hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | | ||
| 6157 | ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6158 | } | ||
| 6159 | // UQSUB8 | ||
| 6160 | else { | ||
| 6161 | lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | | ||
| 6162 | ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6163 | hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | | ||
| 6164 | ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6165 | } | ||
| 6166 | |||
| 6167 | state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16); | ||
| 6137 | return 1; | 6168 | return 1; |
| 6138 | } else { | ||
| 6139 | printf ("Unhandled v6 insn: uqsub16\n"); | ||
| 6140 | } | 6169 | } |
| 6141 | break; | 6170 | break; |
| 6142 | case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8. | 6171 | case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8. |
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 6774f8a74..186b1bd73 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp | |||
| @@ -469,6 +469,47 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | |||
| 469 | ASSIGNV (SubOverflow (a, b, result)); | 469 | ASSIGNV (SubOverflow (a, b, result)); |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | /* 8-bit unsigned saturated addition */ | ||
| 473 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | ||
| 474 | { | ||
| 475 | u8 result = left + right; | ||
| 476 | |||
| 477 | if (result < left) | ||
| 478 | result = 0xFF; | ||
| 479 | |||
| 480 | return result; | ||
| 481 | } | ||
| 482 | |||
| 483 | /* 16-bit unsigned saturated addition */ | ||
| 484 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | ||
| 485 | { | ||
| 486 | u16 result = left + right; | ||
| 487 | |||
| 488 | if (result < left) | ||
| 489 | result = 0xFFFF; | ||
| 490 | |||
| 491 | return result; | ||
| 492 | } | ||
| 493 | |||
| 494 | /* 8-bit unsigned saturated subtraction */ | ||
| 495 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | ||
| 496 | { | ||
| 497 | if (left <= right) | ||
| 498 | return 0; | ||
| 499 | |||
| 500 | return left - right; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* 16-bit unsigned saturated subtraction */ | ||
| 504 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | ||
| 505 | { | ||
| 506 | if (left <= right) | ||
| 507 | return 0; | ||
| 508 | |||
| 509 | return left - right; | ||
| 510 | } | ||
| 511 | |||
| 512 | |||
| 472 | /* This function does the work of generating the addresses used in an | 513 | /* This function does the work of generating the addresses used in an |
| 473 | LDC instruction. The code here is always post-indexed, it's up to the | 514 | LDC instruction. The code here is always post-indexed, it's up to the |
| 474 | caller to get the input address correct and to handle base register | 515 | caller to get the input address correct and to handle base register |
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h index 3ea14b5a3..0b87dd39c 100644 --- a/src/core/arm/skyeye_common/armemu.h +++ b/src/core/arm/skyeye_common/armemu.h | |||
| @@ -603,6 +603,10 @@ extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); | |||
| 603 | extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); | 603 | extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); |
| 604 | extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); | 604 | extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); |
| 605 | extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword); | 605 | extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword); |
| 606 | extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); | ||
| 607 | extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); | ||
| 608 | extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); | ||
| 609 | extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); | ||
| 606 | extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); | 610 | extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); |
| 607 | extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); | 611 | extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); |
| 608 | extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); | 612 | extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); |