aboutsummaryrefslogtreecommitdiff
path: root/src/core/arm/dyncom
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/dyncom')
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp49
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h14
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp74
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp536
4 files changed, 551 insertions, 122 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 6d4fb1b48..a838fd25a 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -47,68 +47,38 @@ ARM_DynCom::ARM_DynCom() : ticks(0) {
ARM_DynCom::~ARM_DynCom() {
}
-/**
- * Set the Program Counter to an address
- * @param addr Address to set PC to
- */
void ARM_DynCom::SetPC(u32 pc) {
state->pc = state->Reg[15] = pc;
}
-/*
- * Get the current Program Counter
- * @return Returns current PC
- */
u32 ARM_DynCom::GetPC() const {
return state->Reg[15];
}
-/**
- * Get an ARM register
- * @param index Register index (0-15)
- * @return Returns the value in the register
- */
u32 ARM_DynCom::GetReg(int index) const {
return state->Reg[index];
}
-/**
- * Set an ARM register
- * @param index Register index (0-15)
- * @param value Value to set register to
- */
void ARM_DynCom::SetReg(int index, u32 value) {
state->Reg[index] = value;
}
-/**
- * Get the current CPSR register
- * @return Returns the value of the CPSR register
- */
u32 ARM_DynCom::GetCPSR() const {
return state->Cpsr;
}
-/**
- * Set the current CPSR register
- * @param cpsr Value to set CPSR to
- */
void ARM_DynCom::SetCPSR(u32 cpsr) {
state->Cpsr = cpsr;
}
-/**
- * Returns the number of clock ticks since the last reset
- * @return Returns number of clock ticks
- */
u64 ARM_DynCom::GetTicks() const {
return ticks;
}
-/**
- * Executes the given number of instructions
- * @param num_instructions Number of instructions to executes
- */
+void ARM_DynCom::AddTicks(u64 ticks) {
+ this->ticks += ticks;
+}
+
void ARM_DynCom::ExecuteInstructions(int num_instructions) {
state->NumInstrsToExecute = num_instructions;
@@ -118,11 +88,6 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
ticks += InterpreterMainLoop(state.get());
}
-/**
- * Saves the current CPU context
- * @param ctx Thread context to save
- * @todo Do we need to save Reg[15] and NextInstr?
- */
void ARM_DynCom::SaveContext(ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -139,11 +104,6 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {
ctx.mode = state->NextInstr;
}
-/**
- * Loads a CPU context
- * @param ctx Thread context to load
- * @param Do we need to load Reg[15] and NextInstr?
- */
void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
@@ -160,7 +120,6 @@ void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
state->NextInstr = ctx.mode;
}
-/// Prepare core for thread reschedule (if needed to correctly handle state)
void ARM_DynCom::PrepareReschedule() {
state->NumInstrsToExecute = 0;
}
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 6fa2a0ba7..7284dcd07 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -27,14 +27,14 @@ public:
* Get the current Program Counter
* @return Returns current PC
*/
- u32 GetPC() const;
+ u32 GetPC() const override;
/**
* Get an ARM register
* @param index Register index (0-15)
* @return Returns the value in the register
*/
- u32 GetReg(int index) const;
+ u32 GetReg(int index) const override;
/**
* Set an ARM register
@@ -47,7 +47,7 @@ public:
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
- u32 GetCPSR() const;
+ u32 GetCPSR() const override;
/**
* Set the current CPSR register
@@ -59,7 +59,13 @@ public:
* Returns the number of clock ticks since the last reset
* @return Returns number of clock ticks
*/
- u64 GetTicks() const;
+ u64 GetTicks() const override;
+
+ /**
+ * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
+ * @param ticks Number of ticks to advance the CPU core
+ */
+ void AddTicks(u64 ticks) override;
/**
* Saves the current CPU context
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 5d174a08f..551bb77a6 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -28,9 +28,40 @@
#include "core/arm/dyncom/arm_dyncom_dec.h"
const ISEITEM arm_instruction[] = {
- #define VFP_DECODE
- #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
- #undef VFP_DECODE
+ {"vmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0},
+ {"vmls", 7, ARMVFP2, 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0},
+ {"vnmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0},
+ {"vnmla", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
+ {"vnmls", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
+ {"vnmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
+ {"vmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
+ {"vadd", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
+ {"vsub", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
+ {"vdiv", 5, ARMVFP2, 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
+ {"vmov(i)", 4, ARMVFP3, 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0},
+ {"vmov(r)", 5, ARMVFP3, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
+ {"vabs", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
+ {"vneg", 5, ARMVFP2, 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
+ {"vsqrt", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
+ {"vcmp", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
+ {"vcmp2", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40},
+ {"vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
+ {"vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11,5, 6, 6, 1},
+ {"vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
+ {"vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10},
+ {"vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10},
+ {"vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0,4,0x10},
+ {"vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xA10},
+ {"vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0,4,0x10},
+ {"vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1},
+ {"vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1},
+ {"vstr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 0, 9, 11,5},
+ {"vpush", 3, ARMVFP2, 23, 27, 0x1A, 16, 21, 0x2D, 9, 11,5},
+ {"vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11,5},
+ {"vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3D, 9, 11,5},
+ {"vldr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 1, 9, 11,5},
+ {"vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11,5},
+
{"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005},
{"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a},
{"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007},
@@ -187,9 +218,40 @@ const ISEITEM arm_instruction[] = {
};
const ISEITEM arm_exclusion_code[] = {
- #define VFP_DECODE_EXCLUSION
- #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
- #undef VFP_DECODE_EXCLUSION
+ {"vmla", 0, ARMVFP2, 0},
+ {"vmls", 0, ARMVFP2, 0},
+ {"vnmla", 0, ARMVFP2, 0},
+ {"vnmla", 0, ARMVFP2, 0},
+ {"vnmls", 0, ARMVFP2, 0},
+ {"vnmul", 0, ARMVFP2, 0},
+ {"vmul", 0, ARMVFP2, 0},
+ {"vadd", 0, ARMVFP2, 0},
+ {"vsub", 0, ARMVFP2, 0},
+ {"vdiv", 0, ARMVFP2, 0},
+ {"vmov(i)", 0, ARMVFP3, 0},
+ {"vmov(r)", 0, ARMVFP3, 0},
+ {"vabs", 0, ARMVFP2, 0},
+ {"vneg", 0, ARMVFP2, 0},
+ {"vsqrt", 0, ARMVFP2, 0},
+ {"vcmp", 0, ARMVFP2, 0},
+ {"vcmp2", 0, ARMVFP2, 0},
+ {"vcvt(bff)", 0, ARMVFP3, 4, 4, 1},
+ {"vcvt(bds)", 0, ARMVFP2, 0},
+ {"vcvt(bfi)", 0, ARMVFP2, 0},
+ {"vmovbrs", 0, ARMVFP2, 0},
+ {"vmsr", 0, ARMVFP2, 0},
+ {"vmovbrc", 0, ARMVFP2, 0},
+ {"vmrs", 0, ARMVFP2, 0},
+ {"vmovbcr", 0, ARMVFP2, 0},
+ {"vmovbrrss", 0, ARMVFP2, 0},
+ {"vmovbrrd", 0, ARMVFP2, 0},
+ {"vstr", 0, ARMVFP2, 0},
+ {"vpush", 0, ARMVFP2, 0},
+ {"vstm", 0, ARMVFP2, 0},
+ {"vpop", 0, ARMVFP2, 0},
+ {"vldr", 0, ARMVFP2, 0},
+ {"vldm", 0, ARMVFP2, 0},
+
{"srs" , 0 , 6 , 0},
{"rfe" , 0 , 6 , 0},
{"bkpt" , 0 , 3 , 0},
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 460001b1a..f58b4731a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1427,6 +1427,13 @@ typedef struct _blx_1_thumb {
unsigned int instr;
}blx_1_thumb;
+typedef struct _pkh_inst {
+ u32 Rm;
+ u32 Rn;
+ u32 Rd;
+ u8 imm;
+} pkh_inst;
+
typedef arm_inst * ARM_INST_PTR;
#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
@@ -2376,8 +2383,30 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
}
return inst_base;
}
-ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHBT"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHTB"); }
+
+ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
+ pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->imm = BITS(inst, 7, 11);
+
+ return inst_base;
+}
+
+ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
+}
+
ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
{
arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
@@ -2390,8 +2419,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
return inst_base;
}
ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
+ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
{
arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
@@ -2409,21 +2437,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
return inst_base;
}
+ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
{
- return INTERPRETER_TRANSLATE(qadd16)(inst, index);
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
}
ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB8"); }
+ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
{
- return INTERPRETER_TRANSLATE(qadd16)(inst, index);
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
}
ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
{
- return INTERPRETER_TRANSLATE(qadd16)(inst, index);
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
}
ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
{
@@ -3086,15 +3121,47 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
inst_base->load_r15 = 1;
return inst_base;
}
-ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD8"); }
+ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADDSUBX"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD16"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADDSUBX"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); }
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
{
arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
@@ -3217,23 +3284,93 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
return inst_base;
}
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD16"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADDSUBX"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB16"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUBADDX"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAD8"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USADA8"); }
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ inst_cream->op1 = BITS(inst, 20, 24);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Ra = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(usada8)(inst, index);
+}
ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); }
ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUBADDX"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTAB16"); }
-ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTB16"); }
+ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
+ uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ return inst_base;
+}
+ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
+}
/* Floating point VFPv3 structures and instructions */
@@ -3250,9 +3387,40 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UN
typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
const transop_fp_t arm_instruction_trans[] = {
- #define VFP_INTERPRETER_TABLE
- #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
- #undef VFP_INTERPRETER_TABLE
+ INTERPRETER_TRANSLATE(vmla),
+ INTERPRETER_TRANSLATE(vmls),
+ INTERPRETER_TRANSLATE(vnmla),
+ INTERPRETER_TRANSLATE(vnmla),
+ INTERPRETER_TRANSLATE(vnmls),
+ INTERPRETER_TRANSLATE(vnmul),
+ INTERPRETER_TRANSLATE(vmul),
+ INTERPRETER_TRANSLATE(vadd),
+ INTERPRETER_TRANSLATE(vsub),
+ INTERPRETER_TRANSLATE(vdiv),
+ INTERPRETER_TRANSLATE(vmovi),
+ INTERPRETER_TRANSLATE(vmovr),
+ INTERPRETER_TRANSLATE(vabs),
+ INTERPRETER_TRANSLATE(vneg),
+ INTERPRETER_TRANSLATE(vsqrt),
+ INTERPRETER_TRANSLATE(vcmp),
+ INTERPRETER_TRANSLATE(vcmp2),
+ INTERPRETER_TRANSLATE(vcvtbds),
+ INTERPRETER_TRANSLATE(vcvtbff),
+ INTERPRETER_TRANSLATE(vcvtbfi),
+ INTERPRETER_TRANSLATE(vmovbrs),
+ INTERPRETER_TRANSLATE(vmsr),
+ INTERPRETER_TRANSLATE(vmovbrc),
+ INTERPRETER_TRANSLATE(vmrs),
+ INTERPRETER_TRANSLATE(vmovbcr),
+ INTERPRETER_TRANSLATE(vmovbrrss),
+ INTERPRETER_TRANSLATE(vmovbrrd),
+ INTERPRETER_TRANSLATE(vstr),
+ INTERPRETER_TRANSLATE(vpush),
+ INTERPRETER_TRANSLATE(vstm),
+ INTERPRETER_TRANSLATE(vpop),
+ INTERPRETER_TRANSLATE(vldr),
+ INTERPRETER_TRANSLATE(vldm),
+
INTERPRETER_TRANSLATE(srs),
INTERPRETER_TRANSLATE(rfe),
INTERPRETER_TRANSLATE(bkpt),
@@ -3976,7 +4144,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
case 124: goto PKHTB_INST; \
case 125: goto PKHBT_INST; \
case 126: goto SMUL_INST; \
- case 127: goto SMLAL_INST; \
+ case 127: goto SMLALXY_INST; \
case 128: goto SMLA_INST; \
case 129: goto MCRR_INST; \
case 130: goto MRRC_INST; \
@@ -4093,10 +4261,12 @@ unsigned InterpreterMainLoop(ARMul_State* state)
// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
// to a clunky switch statement.
#if defined __GNUC__ || defined __clang__
- void *InstLabel[] = {
- #define VFP_INTERPRETER_LABEL
- #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
- #undef VFP_INTERPRETER_LABEL
+ void *InstLabel[] = {
+ &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST,
+ &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST,
+ &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST,
+ &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST,
+
&&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST,
&&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST,
&&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST,
@@ -4106,7 +4276,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
&&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST,
&&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST,
&&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST,
- &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLAL_INST,&&SMLA_INST,
+ &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST,
&&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST,
&&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
&&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
@@ -4130,7 +4300,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
DISPATCH:
{
if (!cpu->NirqSig) {
- if (!(cpu->Cpsr & 0x80)) {
+ if (!(cpu->Cpsr & 0x80)) {
goto END;
}
}
@@ -5575,8 +5745,34 @@ unsigned InterpreterMainLoop(ARMul_State* state)
FETCH_INST;
GOTO_NEXT_INST;
}
+
PKHBT_INST:
+ {
+ INC_ICOUNTER;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
+ RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
+ }
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(pkh_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
PKHTB_INST:
+ {
+ INC_ICOUNTER;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
+ int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
+ RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
+ }
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(pkh_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
PLD_INST:
{
INC_ICOUNTER;
@@ -5587,55 +5783,60 @@ unsigned InterpreterMainLoop(ARMul_State* state)
GOTO_NEXT_INST;
}
QADD_INST:
- QADD8_INST:
+ QADD8_INST:
QADD16_INST:
QADDSUBX_INST:
+ QSUB8_INST:
QSUB16_INST:
QSUBADDX_INST:
{
INC_ICOUNTER;
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
- const s16 rm_lo = (RM & 0xFFFF);
- const s16 rm_hi = ((RM >> 16) & 0xFFFF);
- const s16 rn_lo = (RN & 0xFFFF);
- const s16 rn_hi = ((RN >> 16) & 0xFFFF);
+ const u16 rm_lo = (RM & 0xFFFF);
+ const u16 rm_hi = ((RM >> 16) & 0xFFFF);
+ const u16 rn_lo = (RN & 0xFFFF);
+ const u16 rn_hi = ((RN >> 16) & 0xFFFF);
const u8 op2 = inst_cream->op2;
- s32 lo_result = 0;
- s32 hi_result = 0;
+ u16 lo_result = 0;
+ u16 hi_result = 0;
// QADD16
if (op2 == 0x00) {
- lo_result = (rn_lo + rm_lo);
- hi_result = (rn_hi + rm_hi);
+ lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
+ hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
}
// QASX
else if (op2 == 0x01) {
- lo_result = (rn_lo - rm_hi);
- hi_result = (rn_hi + rm_lo);
+ lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
+ hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
}
// QSAX
else if (op2 == 0x02) {
- lo_result = (rn_lo + rm_hi);
- hi_result = (rn_hi - rm_lo);
+ lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
+ hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
}
// QSUB16
else if (op2 == 0x03) {
- lo_result = (rn_lo - rm_lo);
- hi_result = (rn_hi - rm_hi);
+ lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
+ hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
+ }
+ // QADD8
+ else if (op2 == 0x04) {
+ lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
+ ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
+ hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
+ ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
+ }
+ // QSUB8
+ else if (op2 == 0x07) {
+ lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
+ ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
+ hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
+ ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
}
-
- if (lo_result > 0x7FFF)
- lo_result = 0x7FFF;
- else if (lo_result < -0x8000)
- lo_result = -0x8000;
-
- if (hi_result > 0x7FFF)
- hi_result = 0x7FFF;
- else if (hi_result < -0x8000)
- hi_result = -0x8000;
RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
}
@@ -5649,7 +5850,6 @@ unsigned InterpreterMainLoop(ARMul_State* state)
QDADD_INST:
QDSUB_INST:
QSUB_INST:
- QSUB8_INST:
REV_INST:
{
INC_ICOUNTER;
@@ -6622,15 +6822,95 @@ unsigned InterpreterMainLoop(ARMul_State* state)
FETCH_INST;
GOTO_NEXT_INST;
}
- UADD16_INST:
UADD8_INST:
+ UADD16_INST:
UADDSUBX_INST:
- UHADD16_INST:
+
UHADD8_INST:
+ UHADD16_INST:
UHADDSUBX_INST:
- UHSUB16_INST:
- UHSUB8_INST:
UHSUBADDX_INST:
+ UHSUB8_INST:
+ UHSUB16_INST:
+ {
+ INC_ICOUNTER;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ const u32 rm_val = RM;
+ const u32 rn_val = RN;
+ const u8 op2 = inst_cream->op2;
+
+
+ if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
+ {
+ u32 lo_val = 0;
+ u32 hi_val = 0;
+
+ // UHADD16
+ if (op2 == 0x00) {
+ lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
+ hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
+ }
+ // UHASX
+ else if (op2 == 0x01) {
+ lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
+ hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
+ }
+ // UHSAX
+ else if (op2 == 0x02) {
+ lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
+ hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
+ }
+ // UHSUB16
+ else if (op2 == 0x03) {
+ lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
+ hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
+ }
+
+ lo_val >>= 1;
+ hi_val >>= 1;
+
+ RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
+ }
+ else if (op2 == 0x04 || op2 == 0x07) {
+ u32 sum1;
+ u32 sum2;
+ u32 sum3;
+ u32 sum4;
+
+ // UHADD8
+ if (op2 == 0x04) {
+ sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
+ sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
+ sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
+ sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
+ }
+ // UHSUB8
+ else {
+ sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
+ sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
+ sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
+ sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
+ }
+
+ sum1 >>= 1;
+ sum2 >>= 1;
+ sum3 >>= 1;
+ sum4 >>= 1;
+
+ RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
+ }
+
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(generic_arm_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
+
UMAAL_INST:
{
INC_ICOUNTER;
@@ -6764,21 +7044,143 @@ unsigned InterpreterMainLoop(ARMul_State* state)
goto DISPATCH;
}
- UQADD16_INST:
UQADD8_INST:
+ UQADD16_INST:
UQADDSUBX_INST:
- UQSUB16_INST:
UQSUB8_INST:
+ UQSUB16_INST:
UQSUBADDX_INST:
+ {
+ INC_ICOUNTER;
+
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ const u8 op2 = inst_cream->op2;
+ const u32 rm_val = RM;
+ const u32 rn_val = RN;
+
+ u16 lo_val = 0;
+ u16 hi_val = 0;
+
+ // UQADD16
+ if (op2 == 0x00) {
+ lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
+ hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
+ }
+ // UQASX
+ else if (op2 == 0x01) {
+ lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
+ hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
+ }
+ // UQSAX
+ else if (op2 == 0x02) {
+ lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
+ hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
+ }
+ // UQSUB16
+ else if (op2 == 0x03) {
+ lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
+ hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
+ }
+ // UQADD8
+ else if (op2 == 0x04) {
+ lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
+ ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
+ hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
+ ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
+ }
+ // UQSUB8
+ else {
+ lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
+ ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
+ hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
+ ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
+ }
+
+ RD = ((lo_val & 0xFFFF) | hi_val << 16);
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(generic_arm_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
USAD8_INST:
USADA8_INST:
+ {
+ INC_ICOUNTER;
+
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
+
+ const u8 ra_idx = inst_cream->Ra;
+ const u32 rm_val = RM;
+ const u32 rn_val = RN;
+
+ const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
+ const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
+ const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
+ const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
+
+ u32 finalDif = (diff1 + diff2 + diff3 + diff4);
+
+ // Op is USADA8 if true.
+ if (ra_idx != 15)
+ finalDif += cpu->Reg[ra_idx];
+
+ RD = finalDif;
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(generic_arm_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
USAT_INST:
USAT16_INST:
USUB16_INST:
USUB8_INST:
USUBADDX_INST:
+
UXTAB16_INST:
UXTB16_INST:
+ {
+ INC_ICOUNTER;
+
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
+
+ const u8 rn_idx = inst_cream->Rn;
+ const u32 rm_val = RM;
+ const u32 rotation = inst_cream->rotate * 8;
+ const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
+
+ // UXTB16, otherwise UXTAB16
+ if (rn_idx == 15) {
+ RD = rotated_rm & 0x00FF00FF;
+ }
+ else {
+ const u32 rn_val = RN;
+
+ const u8 lo_rotated = (rotated_rm & 0xFF);
+ const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
+
+ const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
+ const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
+
+ RD = ((hi_result << 16) | (lo_result & 0xFFFF));
+ }
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC(sizeof(uxtab_inst));
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
#define VFP_INTERPRETER_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_INTERPRETER_IMPL