summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp96
-rw-r--r--src/core/arm/interpreter/armsupp.cpp35
-rw-r--r--src/core/arm/skyeye_common/armdefs.h2
3 files changed, 131 insertions, 2 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 0ee103c56..a66560af2 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1100,6 +1100,14 @@ typedef struct _smla_inst {
1100 unsigned int Rn; 1100 unsigned int Rn;
1101} smla_inst; 1101} smla_inst;
1102 1102
1103typedef struct ssat_inst {
1104 unsigned int Rn;
1105 unsigned int Rd;
1106 unsigned int imm5;
1107 unsigned int sat_imm;
1108 unsigned int shift_type;
1109} ssat_inst;
1110
1103typedef struct umaal_inst { 1111typedef struct umaal_inst {
1104 unsigned int Rn; 1112 unsigned int Rn;
1105 unsigned int Rm; 1113 unsigned int Rm;
@@ -2525,7 +2533,24 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
2525} 2533}
2526ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUSD"); } 2534ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUSD"); }
2527ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SRS"); } 2535ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SRS"); }
2528ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT"); } 2536ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)
2537{
2538 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
2539 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
2540
2541 inst_base->cond = BITS(inst, 28, 31);
2542 inst_base->idx = index;
2543 inst_base->br = NON_BRANCH;
2544 inst_base->load_r15 = 0;
2545
2546 inst_cream->Rn = BITS(inst, 0, 3);
2547 inst_cream->Rd = BITS(inst, 12, 15);
2548 inst_cream->imm5 = BITS(inst, 7, 11);
2549 inst_cream->sat_imm = BITS(inst, 16, 20);
2550 inst_cream->shift_type = BIT(inst, 6);
2551
2552 return inst_base;
2553}
2529ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT16"); } 2554ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT16"); }
2530ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUB8"); } 2555ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUB8"); }
2531ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) 2556ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index)
@@ -3128,7 +3153,10 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
3128{ 3153{
3129 return INTERPRETER_TRANSLATE(usada8)(inst, index); 3154 return INTERPRETER_TRANSLATE(usada8)(inst, index);
3130} 3155}
3131ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); } 3156ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index)
3157{
3158 return INTERPRETER_TRANSLATE(ssat)(inst, index);
3159}
3132ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); } 3160ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); }
3133ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); } 3161ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); }
3134ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); } 3162ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); }
@@ -5514,6 +5542,38 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5514 SMUSD_INST: 5542 SMUSD_INST:
5515 SRS_INST: 5543 SRS_INST:
5516 SSAT_INST: 5544 SSAT_INST:
5545 {
5546 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5547 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
5548
5549 u8 shift_type = inst_cream->shift_type;
5550 u8 shift_amount = inst_cream->imm5;
5551 u32 rn_val = RN;
5552
5553 // 32-bit ASR is encoded as an amount of 0.
5554 if (shift_type == 1 && shift_amount == 0)
5555 shift_amount = 31;
5556
5557 if (shift_type == 0)
5558 rn_val <<= shift_amount;
5559 else if (shift_type == 1)
5560 rn_val = ((s32)rn_val >> shift_amount);
5561
5562 bool saturated = false;
5563 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
5564
5565 if (saturated)
5566 cpu->Cpsr |= (1 << 27);
5567
5568 RD = rn_val;
5569 }
5570
5571 cpu->Reg[15] += GET_INST_SIZE(cpu);
5572 INC_PC(sizeof(ssat_inst));
5573 FETCH_INST;
5574 GOTO_NEXT_INST;
5575 }
5576
5517 SSAT16_INST: 5577 SSAT16_INST:
5518 SSUB8_INST: 5578 SSUB8_INST:
5519 STC_INST: 5579 STC_INST:
@@ -6262,6 +6322,38 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6262 } 6322 }
6263 6323
6264 USAT_INST: 6324 USAT_INST:
6325 {
6326 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6327 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
6328
6329 u8 shift_type = inst_cream->shift_type;
6330 u8 shift_amount = inst_cream->imm5;
6331 u32 rn_val = RN;
6332
6333 // 32-bit ASR is encoded as an amount of 0.
6334 if (shift_type == 1 && shift_amount == 0)
6335 shift_amount = 31;
6336
6337 if (shift_type == 0)
6338 rn_val <<= shift_amount;
6339 else if (shift_type == 1)
6340 rn_val = ((s32)rn_val >> shift_amount);
6341
6342 bool saturated = false;
6343 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
6344
6345 if (saturated)
6346 cpu->Cpsr |= (1 << 27);
6347
6348 RD = rn_val;
6349 }
6350
6351 cpu->Reg[15] += GET_INST_SIZE(cpu);
6352 INC_PC(sizeof(ssat_inst));
6353 FETCH_INST;
6354 GOTO_NEXT_INST;
6355 }
6356
6265 USAT16_INST: 6357 USAT16_INST:
6266 USUB16_INST: 6358 USUB16_INST:
6267 USUB8_INST: 6359 USUB8_INST:
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 8b3661c8f..426b67831 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -578,6 +578,41 @@ u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
578 return left - right; 578 return left - right;
579} 579}
580 580
581// Signed saturation.
582u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
583{
584 const u32 max = (1 << shift) - 1;
585 const s32 top = (value >> shift);
586
587 if (top > 0) {
588 *saturation_occurred = true;
589 return max;
590 }
591 else if (top < -1) {
592 *saturation_occurred = true;
593 return ~max;
594 }
595
596 *saturation_occurred = false;
597 return (u32)value;
598}
599
600// Unsigned saturation
601u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
602{
603 const u32 max = (1 << shift) - 1;
604
605 if (value < 0) {
606 *saturation_occurred = true;
607 return 0;
608 } else if ((u32)value > max) {
609 *saturation_occurred = true;
610 return max;
611 }
612
613 *saturation_occurred = false;
614 return (u32)value;
615}
581 616
582/* This function does the work of generating the addresses used in an 617/* This function does the work of generating the addresses used in an
583 LDC instruction. The code here is always post-indexed, it's up to the 618 LDC instruction. The code here is always post-indexed, it's up to the
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 0f2bcbdb1..8611d7392 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -800,6 +800,8 @@ extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
800extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); 800extern u8 ARMul_UnsignedSaturatedSub8(u8, u8);
801extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); 801extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
802extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); 802extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
803extern u32 ARMul_SignedSatQ(s32, u8, bool*);
804extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
803 805
804#define DIFF_LOG 0 806#define DIFF_LOG 0
805#define SAVE_LOG 0 807#define SAVE_LOG 0