diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 68 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 60 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 5 |
3 files changed, 100 insertions, 33 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index f0d349de7..b9c2aa6c2 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -5948,56 +5948,58 @@ L_stm_s_takeabort: | |||
| 5948 | printf("Unhandled v6 insn: %08x", instr); | 5948 | printf("Unhandled v6 insn: %08x", instr); |
| 5949 | } | 5949 | } |
| 5950 | break; | 5950 | break; |
| 5951 | case 0x62: // QADD16, QASX, QSAX, and QSUB16 | 5951 | case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8 |
| 5952 | if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 || | ||
| 5953 | (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70) | ||
| 5954 | { | 5952 | { |
| 5953 | const u8 op2 = BITS(5, 7); | ||
| 5954 | |||
| 5955 | const u8 rd_idx = BITS(12, 15); | 5955 | const u8 rd_idx = BITS(12, 15); |
| 5956 | const u8 rn_idx = BITS(16, 19); | 5956 | const u8 rn_idx = BITS(16, 19); |
| 5957 | const u8 rm_idx = BITS(0, 3); | 5957 | const u8 rm_idx = BITS(0, 3); |
| 5958 | const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); | 5958 | const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); |
| 5959 | const s16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); | 5959 | const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); |
| 5960 | const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); | 5960 | const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); |
| 5961 | const s16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); | 5961 | const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); |
| 5962 | 5962 | ||
| 5963 | s32 lo_result; | 5963 | u16 lo_result = 0; |
| 5964 | s32 hi_result; | 5964 | u16 hi_result = 0; |
| 5965 | 5965 | ||
| 5966 | // QADD16 | 5966 | // QADD16 |
| 5967 | if ((instr & 0xFF0) == 0xf10) { | 5967 | if (op2 == 0x00) { |
| 5968 | lo_result = (rn_lo + rm_lo); | 5968 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); |
| 5969 | hi_result = (rn_hi + rm_hi); | 5969 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); |
| 5970 | } | 5970 | } |
| 5971 | // QASX | 5971 | // QASX |
| 5972 | else if ((instr & 0xFF0) == 0xf30) { | 5972 | else if (op2 == 0x01) { |
| 5973 | lo_result = (rn_lo - rm_hi); | 5973 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); |
| 5974 | hi_result = (rn_hi + rm_lo); | 5974 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); |
| 5975 | } | 5975 | } |
| 5976 | // QSAX | 5976 | // QSAX |
| 5977 | else if ((instr & 0xFF0) == 0xf50) { | 5977 | else if (op2 == 0x02) { |
| 5978 | lo_result = (rn_lo + rm_hi); | 5978 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); |
| 5979 | hi_result = (rn_hi - rm_lo); | 5979 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); |
| 5980 | } | 5980 | } |
| 5981 | // QSUB16 | 5981 | // QSUB16 |
| 5982 | else { | 5982 | else if (op2 == 0x03) { |
| 5983 | lo_result = (rn_lo - rm_lo); | 5983 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); |
| 5984 | hi_result = (rn_hi - rm_hi); | 5984 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi); |
| 5985 | } | ||
| 5986 | // QADD8 | ||
| 5987 | else if (op2 == 0x04) { | ||
| 5988 | lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) | | ||
| 5989 | ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8; | ||
| 5990 | hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) | | ||
| 5991 | ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8; | ||
| 5992 | } | ||
| 5993 | // QSUB8 | ||
| 5994 | else if (op2 == 0x07) { | ||
| 5995 | lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | | ||
| 5996 | ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; | ||
| 5997 | hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | | ||
| 5998 | ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; | ||
| 5985 | } | 5999 | } |
| 5986 | |||
| 5987 | if (lo_result > 0x7FFF) | ||
| 5988 | lo_result = 0x7FFF; | ||
| 5989 | else if (lo_result < -0x8000) | ||
| 5990 | lo_result = -0x8000; | ||
| 5991 | |||
| 5992 | if (hi_result > 0x7FFF) | ||
| 5993 | hi_result = 0x7FFF; | ||
| 5994 | else if (hi_result < -0x8000) | ||
| 5995 | hi_result = -0x8000; | ||
| 5996 | 6000 | ||
| 5997 | state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | 6001 | state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 5998 | return 1; | 6002 | return 1; |
| 5999 | } else { | ||
| 6000 | printf("Unhandled v6 insn: %08x", BITS(20, 27)); | ||
| 6001 | } | 6003 | } |
| 6002 | break; | 6004 | break; |
| 6003 | case 0x63: | 6005 | case 0x63: |
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 8f158e2c8..8b3661c8f 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp | |||
| @@ -478,6 +478,66 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | |||
| 478 | ASSIGNV (SubOverflow (a, b, result)); | 478 | ASSIGNV (SubOverflow (a, b, result)); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | /* 8-bit signed saturated addition */ | ||
| 482 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | ||
| 483 | { | ||
| 484 | u8 result = left + right; | ||
| 485 | |||
| 486 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { | ||
| 487 | if (left & 0x80) | ||
| 488 | result = 0x80; | ||
| 489 | else | ||
| 490 | result = 0x7F; | ||
| 491 | } | ||
| 492 | |||
| 493 | return result; | ||
| 494 | } | ||
| 495 | |||
| 496 | /* 8-bit signed saturated subtraction */ | ||
| 497 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | ||
| 498 | { | ||
| 499 | u8 result = left - right; | ||
| 500 | |||
| 501 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { | ||
| 502 | if (left & 0x80) | ||
| 503 | result = 0x80; | ||
| 504 | else | ||
| 505 | result = 0x7F; | ||
| 506 | } | ||
| 507 | |||
| 508 | return result; | ||
| 509 | } | ||
| 510 | |||
| 511 | /* 16-bit signed saturated addition */ | ||
| 512 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | ||
| 513 | { | ||
| 514 | u16 result = left + right; | ||
| 515 | |||
| 516 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { | ||
| 517 | if (left & 0x8000) | ||
| 518 | result = 0x8000; | ||
| 519 | else | ||
| 520 | result = 0x7FFF; | ||
| 521 | } | ||
| 522 | |||
| 523 | return result; | ||
| 524 | } | ||
| 525 | |||
| 526 | /* 16-bit signed saturated subtraction */ | ||
| 527 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | ||
| 528 | { | ||
| 529 | u16 result = left - right; | ||
| 530 | |||
| 531 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { | ||
| 532 | if (left & 0x8000) | ||
| 533 | result = 0x8000; | ||
| 534 | else | ||
| 535 | result = 0x7FFF; | ||
| 536 | } | ||
| 537 | |||
| 538 | return result; | ||
| 539 | } | ||
| 540 | |||
| 481 | /* 8-bit unsigned saturated addition */ | 541 | /* 8-bit unsigned saturated addition */ |
| 482 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | 542 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) |
| 483 | { | 543 | { |
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index c7509fcb2..0f2bcbdb1 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_SignedSaturatedAdd8(u8, u8); | ||
| 794 | extern u8 ARMul_SignedSaturatedSub8(u8, u8); | ||
| 795 | extern u16 ARMul_SignedSaturatedAdd16(u16, u16); | ||
| 796 | extern u16 ARMul_SignedSaturatedSub16(u16, u16); | ||
| 797 | |||
| 793 | extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); | 798 | extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); |
| 794 | extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); | 799 | extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); |
| 795 | extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); | 800 | extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); |