diff options
| author | 2014-12-27 21:15:13 -0500 | |
|---|---|---|
| committer | 2014-12-27 21:15:13 -0500 | |
| commit | 3422d81f053578e2a6806dc9ffa33c50f2c0b66d (patch) | |
| tree | 16621bd2dabe32e4a17f0014392c6c8f597e9a56 /src | |
| parent | Merge pull request #349 from lioncash/uhdync (diff) | |
| parent | dyncom: Implement UQADD8, UQADD16, UQSUB8, UQSUB16, UQASX, and UQSAX. (diff) | |
| download | yuzu-3422d81f053578e2a6806dc9ffa33c50f2c0b66d.tar.gz yuzu-3422d81f053578e2a6806dc9ffa33c50f2c0b66d.tar.xz yuzu-3422d81f053578e2a6806dc9ffa33c50f2c0b66d.zip | |
Merge pull request #350 from lioncash/qops
Implement the rest of the UQ* ops.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 105 | ||||
| -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/armdefs.h | 5 |
4 files changed, 191 insertions, 27 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 9b355fc6e..7306794fe 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -3249,12 +3249,44 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) | |||
| 3249 | return inst_base; | 3249 | return inst_base; |
| 3250 | } | 3250 | } |
| 3251 | 3251 | ||
| 3252 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD16"); } | 3252 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) |
| 3253 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD8"); } | 3253 | { |
| 3254 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADDSUBX"); } | 3254 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 3255 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB16"); } | 3255 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 3256 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB8"); } | 3256 | |
| 3257 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUBADDX"); } | 3257 | inst_base->cond = BITS(inst, 28, 31); |
| 3258 | inst_base->idx = index; | ||
| 3259 | inst_base->br = NON_BRANCH; | ||
| 3260 | inst_base->load_r15 = 0; | ||
| 3261 | |||
| 3262 | inst_cream->Rm = BITS(inst, 0, 3); | ||
| 3263 | inst_cream->Rn = BITS(inst, 16, 19); | ||
| 3264 | inst_cream->Rd = BITS(inst, 12, 15); | ||
| 3265 | inst_cream->op1 = BITS(inst, 20, 21); | ||
| 3266 | inst_cream->op2 = BITS(inst, 5, 7); | ||
| 3267 | |||
| 3268 | return inst_base; | ||
| 3269 | } | ||
| 3270 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) | ||
| 3271 | { | ||
| 3272 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | ||
| 3273 | } | ||
| 3274 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) | ||
| 3275 | { | ||
| 3276 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | ||
| 3277 | } | ||
| 3278 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) | ||
| 3279 | { | ||
| 3280 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | ||
| 3281 | } | ||
| 3282 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) | ||
| 3283 | { | ||
| 3284 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | ||
| 3285 | } | ||
| 3286 | ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) | ||
| 3287 | { | ||
| 3288 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | ||
| 3289 | } | ||
| 3258 | ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAD8"); } | 3290 | ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAD8"); } |
| 3259 | ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USADA8"); } | 3291 | ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USADA8"); } |
| 3260 | ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); } | 3292 | ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); } |
| @@ -6876,12 +6908,69 @@ unsigned InterpreterMainLoop(ARMul_State* state) | |||
| 6876 | goto DISPATCH; | 6908 | goto DISPATCH; |
| 6877 | } | 6909 | } |
| 6878 | 6910 | ||
| 6879 | UQADD16_INST: | ||
| 6880 | UQADD8_INST: | 6911 | UQADD8_INST: |
| 6912 | UQADD16_INST: | ||
| 6881 | UQADDSUBX_INST: | 6913 | UQADDSUBX_INST: |
| 6882 | UQSUB16_INST: | ||
| 6883 | UQSUB8_INST: | 6914 | UQSUB8_INST: |
| 6915 | UQSUB16_INST: | ||
| 6884 | UQSUBADDX_INST: | 6916 | UQSUBADDX_INST: |
| 6917 | { | ||
| 6918 | INC_ICOUNTER; | ||
| 6919 | |||
| 6920 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||
| 6921 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 6922 | |||
| 6923 | const u8 op2 = inst_cream->op2; | ||
| 6924 | const u32 rm_val = RM; | ||
| 6925 | const u32 rn_val = RN; | ||
| 6926 | |||
| 6927 | u16 lo_val = 0; | ||
| 6928 | u16 hi_val = 0; | ||
| 6929 | |||
| 6930 | // UQADD16 | ||
| 6931 | if (op2 == 0x00) { | ||
| 6932 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 6933 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6934 | } | ||
| 6935 | // UQASX | ||
| 6936 | else if (op2 == 0x01) { | ||
| 6937 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6938 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6939 | } | ||
| 6940 | // UQSAX | ||
| 6941 | else if (op2 == 0x02) { | ||
| 6942 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6943 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 6944 | } | ||
| 6945 | // UQSUB16 | ||
| 6946 | else if (op2 == 0x03) { | ||
| 6947 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 6948 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 6949 | } | ||
| 6950 | // UQADD8 | ||
| 6951 | else if (op2 == 0x04) { | ||
| 6952 | lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | | ||
| 6953 | ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6954 | hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | | ||
| 6955 | ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6956 | } | ||
| 6957 | // UQSUB8 | ||
| 6958 | else { | ||
| 6959 | lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | | ||
| 6960 | ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 6961 | hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | | ||
| 6962 | ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 6963 | } | ||
| 6964 | |||
| 6965 | RD = ((lo_val & 0xFFFF) | hi_val << 16); | ||
| 6966 | } | ||
| 6967 | |||
| 6968 | cpu->Reg[15] += GET_INST_SIZE(cpu); | ||
| 6969 | INC_PC(sizeof(generic_arm_inst)); | ||
| 6970 | FETCH_INST; | ||
| 6971 | GOTO_NEXT_INST; | ||
| 6972 | } | ||
| 6973 | |||
| 6885 | USAD8_INST: | 6974 | USAD8_INST: |
| 6886 | USADA8_INST: | 6975 | USADA8_INST: |
| 6887 | USAT_INST: | 6976 | USAT_INST: |
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/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 34eb5aaf7..5b6e5f8cd 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -790,6 +790,11 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword); | |||
| 790 | extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); | 790 | extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); |
| 791 | extern void ARMul_SelectProcessor(ARMul_State*, unsigned); | 791 | extern void ARMul_SelectProcessor(ARMul_State*, unsigned); |
| 792 | 792 | ||
| 793 | extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); | ||
| 794 | extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); | ||
| 795 | extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); | ||
| 796 | extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); | ||
| 797 | |||
| 793 | #define DIFF_LOG 0 | 798 | #define DIFF_LOG 0 |
| 794 | #define SAVE_LOG 0 | 799 | #define SAVE_LOG 0 |
| 795 | 800 | ||