summaryrefslogtreecommitdiffstats
path: root/src/core/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.h8
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp11
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h7
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp465
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp6
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h4
-rw-r--r--src/core/arm/interpreter/armsupp.cpp16
-rw-r--r--src/core/arm/skyeye_common/armdefs.h1
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp64
9 files changed, 290 insertions, 292 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index d3bd4a9a3..e612f7439 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -7,7 +7,9 @@
#include "common/common.h"
#include "common/common_types.h"
-#include "core/hle/svc.h"
+namespace Core {
+ struct ThreadContext;
+}
/// Generic ARM11 CPU interface
class ARM_Interface : NonCopyable {
@@ -87,13 +89,13 @@ public:
* Saves the current CPU context
* @param ctx Thread context to save
*/
- virtual void SaveContext(ThreadContext& ctx) = 0;
+ virtual void SaveContext(Core::ThreadContext& ctx) = 0;
/**
* Loads a CPU context
* @param ctx Thread context to load
*/
- virtual void LoadContext(const ThreadContext& ctx) = 0;
+ virtual void LoadContext(const Core::ThreadContext& ctx) = 0;
/// Prepare core for thread reschedule (if needed to correctly handle state)
virtual void PrepareReschedule() = 0;
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index c779e3fd4..9c4cc90f2 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -9,13 +9,14 @@
#include "core/arm/dyncom/arm_dyncom.h"
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
+#include "core/core.h"
#include "core/core_timing.h"
const static cpu_config_t s_arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
};
-ARM_DynCom::ARM_DynCom() : ticks(0) {
+ARM_DynCom::ARM_DynCom() {
state = std::unique_ptr<ARMul_State>(new ARMul_State);
ARMul_EmulateInit();
@@ -74,11 +75,11 @@ void ARM_DynCom::SetCPSR(u32 cpsr) {
}
u64 ARM_DynCom::GetTicks() const {
- return ticks;
+ // TODO(Subv): Remove ARM_DynCom::GetTicks() and use CoreTiming::GetTicks() directly once ARMemu is gone
+ return CoreTiming::GetTicks();
}
void ARM_DynCom::AddTicks(u64 ticks) {
- this->ticks += ticks;
down_count -= ticks;
if (down_count < 0)
CoreTiming::Advance();
@@ -94,7 +95,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
AddTicks(ticks_executed);
}
-void ARM_DynCom::SaveContext(ThreadContext& ctx) {
+void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -110,7 +111,7 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {
ctx.mode = state->NextInstr;
}
-void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
+void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 7284dcd07..f16fb070c 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -71,13 +71,13 @@ public:
* Saves the current CPU context
* @param ctx Thread context to save
*/
- void SaveContext(ThreadContext& ctx) override;
+ void SaveContext(Core::ThreadContext& ctx) override;
/**
* Loads a CPU context
* @param ctx Thread context to load
*/
- void LoadContext(const ThreadContext& ctx) override;
+ void LoadContext(const Core::ThreadContext& ctx) override;
/// Prepare core for thread reschedule (if needed to correctly handle state)
void PrepareReschedule() override;
@@ -89,8 +89,5 @@ public:
void ExecuteInstructions(int num_instructions) override;
private:
-
std::unique_ptr<ARMul_State> state;
- u64 ticks;
-
};
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 7c710ccde..d0347566c 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -176,13 +176,11 @@ unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned i
unsigned int shifter_operand;
int shift_imm = BITS(sht_oper, 7, 11);
if (shift_imm == 0) {
- if (BIT(rm, 31)) {
+ if (BIT(rm, 31) == 0)
shifter_operand = 0;
- cpu->shifter_carry_out = BIT(rm, 31);
- } else {
+ else
shifter_operand = 0xFFFFFFFF;
- cpu->shifter_carry_out = BIT(rm, 31);
- }
+ cpu->shifter_carry_out = BIT(rm, 31);
} else {
shifter_operand = static_cast<int>(rm) >> shift_imm;
cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
@@ -1728,25 +1726,21 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
}
ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
inst_cream->inst = inst;
- if (I_BIT == 0) {
+ if (BITS(inst, 25, 27) == 2) {
inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
+ } else if (BITS(inst, 25, 27) == 3) {
+ inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
} else {
DEBUG_MSG;
}
- #if 0
- inst_cream->get_addr = get_calc_addr_op(inst);
- if(inst == 0x54f13001) {
- DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr);
- }
- #endif
if (BITS(inst, 12, 15) == 15) {
inst_base->br = INDIRECT_BRANCH;
@@ -1846,17 +1840,24 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
}
ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
inst_cream->inst = inst;
- if (I_BIT == 0) {
+ if (BITS(inst, 25, 27) == 2) {
inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
+ } else if (BITS(inst, 25, 27) == 3) {
+ inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
} else {
+ // Reaching this would indicate the thumb version
+ // of this instruction, however the 3DS CPU doesn't
+ // support this variant (the 3DS CPU is only ARMv6K,
+ // while this variant is added in ARMv6T2).
+ // So it's sufficient for citra to not implement this.
DEBUG_MSG;
}
@@ -2714,17 +2715,19 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
}
ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
inst_cream->inst = inst;
-// inst_cream->get_addr = get_calc_addr_op(inst);
- if (I_BIT == 0) {
+
+ if (BITS(inst, 25, 27) == 2) {
inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
+ } else if (BITS(inst, 25, 27) == 3) {
+ inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
} else {
DEBUG_MSG;
}
@@ -2796,17 +2799,24 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
}
ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
inst_cream->inst = inst;
- if (I_BIT == 0) {
+ if (BITS(inst, 25, 27) == 2) {
inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
+ } else if (BITS(inst, 25, 27) == 3) {
+ inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
} else {
+ // Reaching this would indicate the thumb version
+ // of this instruction, however the 3DS CPU doesn't
+ // support this variant (the 3DS CPU is only ARMv6K,
+ // while this variant is added in ARMv6T2).
+ // So it's sufficient for citra to not implement this.
DEBUG_MSG;
}
@@ -3905,21 +3915,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
#endif
- #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
- #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
-
- #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop)))
- #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) )
- #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag)))
- #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop))
- #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop))
- #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
-
- #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \
- ((lop >= 0) && (rop) >= 0 && (dst < 0))))
- #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \
- ((lop >= 0) && (rop) >= 0 && (dst < 0))))
- #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31))
+ #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
+ #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
+ #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
#define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \
(cpu->NFlag << 31) | \
@@ -3967,16 +3965,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
&&INIT_INST_LENGTH,&&END
};
#endif
- arm_inst * inst_base;
- unsigned int lop, rop, dst;
+ arm_inst* inst_base;
unsigned int addr;
unsigned int phys_addr;
- unsigned int last_pc = 0;
unsigned int num_instrs = 0;
- static unsigned int last_physical_base = 0, last_logical_base = 0;
int ptr;
- bool single_step = (cpu->NumInstrsToExecute == 1);
LOAD_NZCVT;
DISPATCH:
@@ -4003,12 +3997,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
ADC_INST:
{
- adc_inst *inst_cream = (adc_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- unsigned int sht_op = SHIFTER_OPERAND;
- rop = SHIFTER_OPERAND + cpu->CFlag;
- RD = dst = lop + rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ adc_inst* const inst_cream = (adc_inst*)inst_base->component;
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4016,10 +4011,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag);
- UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(adc_inst));
@@ -4033,14 +4028,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
ADD_INST:
{
- add_inst *inst_cream = (add_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- if (inst_cream->Rn == 15) {
- lop += 2 * GET_INST_SIZE(cpu);
- }
- rop = SHIFTER_OPERAND;
- RD = dst = lop + rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ add_inst* const inst_cream = (add_inst*)inst_base->component;
+
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * GET_INST_SIZE(cpu);
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4048,10 +4046,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG(dst, lop, rop);
- UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(add_inst));
@@ -4067,9 +4065,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
{
and_inst *inst_cream = (and_inst *)inst_base->component;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- rop = SHIFTER_OPERAND;
- RD = dst = lop & rop;
+ u32 lop = RN;
+ u32 rop = SHIFTER_OPERAND;
+ RD = lop & rop;
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4077,8 +4075,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -4110,12 +4108,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
{
bic_inst *inst_cream = (bic_inst *)inst_base->component;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
+ u32 lop = RN;
if (inst_cream->Rn == 15) {
lop += 2 * GET_INST_SIZE(cpu);
}
- rop = SHIFTER_OPERAND;
- RD = dst = lop & (~rop);
+ u32 rop = SHIFTER_OPERAND;
+ RD = lop & (~rop);
if ((inst_cream->S) && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4123,8 +4121,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -4230,15 +4228,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
CMN_INST:
{
- cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- rop = SHIFTER_OPERAND;
- dst = lop + rop;
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG(dst, lop, rop);
- UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
+
+ bool carry;
+ bool overflow;
+ u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow);
+
+ UPDATE_NFLAG(result);
+ UPDATE_ZFLAG(result);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(cmn_inst));
@@ -4247,19 +4247,21 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
CMP_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
- lop = RN;
- if (inst_cream->Rn == 15) {
- lop += 2 * GET_INST_SIZE(cpu);
- }
- rop = SHIFTER_OPERAND;
- dst = lop - rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
- UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * GET_INST_SIZE(cpu);
+
+ bool carry;
+ bool overflow;
+ u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
+
+ UPDATE_NFLAG(result);
+ UPDATE_ZFLAG(result);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(cmp_inst));
@@ -4317,12 +4319,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
{
eor_inst *inst_cream = (eor_inst *)inst_base->component;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
+ u32 lop = RN;
if (inst_cream->Rn == 15) {
lop += 2 * GET_INST_SIZE(cpu);
}
- rop = SHIFTER_OPERAND;
- RD = dst = lop ^ rop;
+ u32 rop = SHIFTER_OPERAND;
+ RD = lop ^ rop;
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4330,8 +4332,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -4848,10 +4850,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOG_ERROR(Core_ARM11, "invalid operands for MLA");
CITRA_IGNORE_EXIT(-1);
}
- RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
+ RD = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(mla_inst));
@@ -4867,7 +4869,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
{
mov_inst *inst_cream = (mov_inst *)inst_base->component;
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- RD = dst = SHIFTER_OPERAND;
+ RD = SHIFTER_OPERAND;
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -4875,8 +4877,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -4964,39 +4966,41 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
MSR_INST:
{
- msr_inst *inst_cream = (msr_inst *)inst_base->component;
- const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
- unsigned int inst = inst_cream->inst;
- unsigned int operand;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ msr_inst *inst_cream = (msr_inst *)inst_base->component;
+ const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
+ unsigned int inst = inst_cream->inst;
+ unsigned int operand;
- if (BIT(inst, 25)) {
- int rot_imm = BITS(inst, 8, 11) * 2;
- operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
- } else {
- operand = cpu->Reg[BITS(inst, 0, 3)];
- }
- uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
- | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
- uint32_t mask;
- if (!inst_cream->R) {
- if (InAPrivilegedMode(cpu)) {
- if ((operand & StateMask) != 0) {
- /// UNPREDICTABLE
- DEBUG_MSG;
- } else
- mask = byte_mask & (UserMask | PrivMask);
+ if (BIT(inst, 25)) {
+ int rot_imm = BITS(inst, 8, 11) * 2;
+ operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
} else {
- mask = byte_mask & UserMask;
+ operand = cpu->Reg[BITS(inst, 0, 3)];
}
- SAVE_NZCVT;
+ uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
+ | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
+ uint32_t mask;
+ if (!inst_cream->R) {
+ if (InAPrivilegedMode(cpu)) {
+ if ((operand & StateMask) != 0) {
+ /// UNPREDICTABLE
+ DEBUG_MSG;
+ } else
+ mask = byte_mask & (UserMask | PrivMask);
+ } else {
+ mask = byte_mask & UserMask;
+ }
+ SAVE_NZCVT;
- cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
- switch_mode(cpu, cpu->Cpsr & 0x1f);
- LOAD_NZCVT;
- } else {
- if (CurrentModeHasSPSR) {
- mask = byte_mask & (UserMask | PrivMask | StateMask);
- cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
+ cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
+ switch_mode(cpu, cpu->Cpsr & 0x1f);
+ LOAD_NZCVT;
+ } else {
+ if (CurrentModeHasSPSR) {
+ mask = byte_mask & (UserMask | PrivMask | StateMask);
+ cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
+ }
}
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -5010,10 +5014,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
uint64_t rm = RM;
uint64_t rs = RS;
- RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff);
+ RD = static_cast<uint32_t>((rm * rs) & 0xffffffff);
if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(mul_inst));
@@ -5027,9 +5031,11 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
MVN_INST:
{
- mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- RD = dst = ~SHIFTER_OPERAND;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
+
+ RD = ~SHIFTER_OPERAND;
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -5037,8 +5043,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -5053,11 +5059,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
ORR_INST:
{
- orr_inst *inst_cream = (orr_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- rop = SHIFTER_OPERAND;
- RD = dst = lop | rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ orr_inst* const inst_cream = (orr_inst*)inst_base->component;
+
+ u32 lop = RN;
+ u32 rop = SHIFTER_OPERAND;
+ RD = lop | rop;
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -5065,8 +5073,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
UPDATE_CFLAG_WITH_SC;
}
if (inst_cream->Rd == 15) {
@@ -5286,14 +5294,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
RFE_INST:
RSB_INST:
{
- rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- rop = RN;
- lop = SHIFTER_OPERAND;
- if (inst_cream->Rn == 15) {
- rop += 2 * GET_INST_SIZE(cpu);;
- }
- RD = dst = lop - rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
+
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * GET_INST_SIZE(cpu);
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -5301,10 +5312,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
- UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(rsb_inst));
@@ -5318,11 +5329,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
RSC_INST:
{
- rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- rop = SHIFTER_OPERAND;
- RD = dst = rop - lop - !cpu->CFlag;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -5330,10 +5343,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag);
- UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(rsc_inst));
@@ -5456,11 +5469,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
SBC_INST:
{
- sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = SHIFTER_OPERAND + !cpu->CFlag;
- rop = RN;
- RD = dst = rop - lop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -5468,15 +5483,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
-
- if(rop >= !cpu->CFlag)
- UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND);
- else
- UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag);
-
- UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(sbc_inst));
@@ -6254,14 +6264,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
SUB_INST:
{
- sub_inst *inst_cream = (sub_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- lop = RN;
- if (inst_cream->Rn == 15) {
- lop += 8;
- }
- rop = SHIFTER_OPERAND;
- RD = dst = lop - rop;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ sub_inst* const inst_cream = (sub_inst*)inst_base->component;
+
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 8;
+
+ bool carry;
+ bool overflow;
+ RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
@@ -6269,10 +6282,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
LOAD_NZCVT;
}
} else if (inst_cream->S) {
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
- UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
- UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
+ UPDATE_NFLAG(RD);
+ UPDATE_ZFLAG(RD);
+ cpu->CFlag = carry;
+ cpu->VFlag = overflow;
}
if (inst_cream->Rd == 15) {
INC_PC(sizeof(sub_inst));
@@ -6400,18 +6413,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
TEQ_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- teq_inst *inst_cream = (teq_inst *)inst_base->component;
- lop = RN;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ teq_inst* const inst_cream = (teq_inst*)inst_base->component;
+
+ u32 lop = RN;
+ u32 rop = SHIFTER_OPERAND;
if (inst_cream->Rn == 15)
lop += GET_INST_SIZE(cpu) * 2;
- rop = SHIFTER_OPERAND;
- dst = lop ^ rop;
+ u32 result = lop ^ rop;
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(result);
+ UPDATE_ZFLAG(result);
UPDATE_CFLAG_WITH_SC;
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6421,18 +6435,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
}
TST_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
- tst_inst *inst_cream = (tst_inst *)inst_base->component;
- lop = RN;
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ tst_inst* const inst_cream = (tst_inst*)inst_base->component;
+
+ u32 lop = RN;
+ u32 rop = SHIFTER_OPERAND;
if (inst_cream->Rn == 15)
lop += GET_INST_SIZE(cpu) * 2;
- rop = SHIFTER_OPERAND;
- dst = lop & rop;
+ u32 result = lop & rop;
- UPDATE_NFLAG(dst);
- UPDATE_ZFLAG(dst);
+ UPDATE_NFLAG(result);
+ UPDATE_ZFLAG(result);
UPDATE_CFLAG_WITH_SC;
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6696,10 +6711,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
- const u32 rm = RM;
- const u32 rn = RN;
- const u32 rd_lo = RDLO;
- const u32 rd_hi = RDHI;
+ const u64 rm = RM;
+ const u64 rn = RN;
+ const u64 rd_lo = RDLO;
+ const u64 rd_hi = RDHI;
const u64 result = (rm * rn) + rd_lo + rd_hi;
RDLO = (result & 0xFFFFFFFF);
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index 80ebc359e..c76d371a2 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -4,6 +4,8 @@
#include "core/arm/interpreter/arm_interpreter.h"
+#include "core/core.h"
+
const static cpu_config_t arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
};
@@ -75,7 +77,7 @@ void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
ARMul_Emulate32(state);
}
-void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
+void ARM_Interpreter::SaveContext(Core::ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -91,7 +93,7 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
ctx.mode = state->NextInstr;
}
-void ARM_Interpreter::LoadContext(const ThreadContext& ctx) {
+void ARM_Interpreter::LoadContext(const Core::ThreadContext& ctx) {
memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index 019dad5df..e5ecc69c2 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -70,13 +70,13 @@ public:
* Saves the current CPU context
* @param ctx Thread context to save
*/
- void SaveContext(ThreadContext& ctx) override;
+ void SaveContext(Core::ThreadContext& ctx) override;
/**
* Loads a CPU context
* @param ctx Thread context to load
*/
- void LoadContext(const ThreadContext& ctx) override;
+ void LoadContext(const Core::ThreadContext& ctx) override;
/// Prepare core for thread reschedule (if needed to correctly handle state)
void PrepareReschedule() override;
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 68ac2a0ce..e2626eefb 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -418,6 +418,22 @@ ARMul_NegZero (ARMul_State * state, ARMword result)
}
}
+// Add with carry, indicates if a carry-out or signed overflow occurred.
+u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
+{
+ u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
+ s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
+ u64 result = (unsigned_sum & 0xFFFFFFFF);
+
+ if (carry_out_occurred)
+ *carry_out_occurred = (result != unsigned_sum);
+
+ if (overflow_occurred)
+ *overflow_occurred = ((s64)(s32)result != signed_sum);
+
+ return (u32)result;
+}
+
// Compute whether an addition of A and B, giving RESULT, overflowed.
bool AddOverflow(ARMword a, ARMword b, ARMword result)
{
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 1b2cef451..560b51a9f 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -795,6 +795,7 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
+extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);
extern bool ARMul_AddOverflowQ(ARMword, ARMword);
extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 08d0d719f..77b528607 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -959,70 +959,34 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
static u32
vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func)
{
-
- {
- struct vfp_single vsd, vsp, vsn, vsm;
- u32 exceptions;
- s32 v;
-
-
-
- v = vfp_get_float(state, sn);
- pr_debug("VFP: s%u = %08x\n", sn, v);
- vfp_single_unpack(&vsn, v);
- if (vsn.exponent == 0 && vsn.significand)
- vfp_single_normalise_denormal(&vsn);
-
- vfp_single_unpack(&vsm, m);
- if (vsm.exponent == 0 && vsm.significand)
- vfp_single_normalise_denormal(&vsm);
-
- exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
-
- if (negate & NEG_MULTIPLY)
- vsp.sign = vfp_sign_negate(vsp.sign);
-
- v = vfp_get_float(state, sd);
- pr_debug("VFP: s%u = %08x\n", sd, v);
- vfp_single_unpack(&vsn, v);
- if (negate & NEG_SUBTRACT)
- vsn.sign = vfp_sign_negate(vsn.sign);
-
- exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
-
- return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
- }
-
- struct vfp_double vsd, vsp, vsn, vsm;
+ vfp_single vsd, vsp, vsn, vsm;
u32 exceptions;
s32 v;
- s64 vd;
- s64 md;
v = vfp_get_float(state, sn);
- vd = vfp_single_to_doubleintern(state, v, fpscr);
- vfp_double_unpack(&vsn, vd);
+ pr_debug("VFP: s%u = %08x\n", sn, v);
+ vfp_single_unpack(&vsn, v);
+ if (vsn.exponent == 0 && vsn.significand)
+ vfp_single_normalise_denormal(&vsn);
+
+ vfp_single_unpack(&vsm, m);
+ if (vsm.exponent == 0 && vsm.significand)
+ vfp_single_normalise_denormal(&vsm);
- md = vfp_single_to_doubleintern(state, m, fpscr);
- vfp_double_unpack(&vsm, md);
+ exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
- exceptions = vfp_double_multiply(&vsp, &vsn, &vsm, fpscr);
if (negate & NEG_MULTIPLY)
vsp.sign = vfp_sign_negate(vsp.sign);
v = vfp_get_float(state, sd);
- vd = vfp_single_to_doubleintern(state, v, fpscr);
- vfp_double_unpack(&vsn, vd);
-
+ pr_debug("VFP: s%u = %08x\n", sd, v);
+ vfp_single_unpack(&vsn, v);
if (negate & NEG_SUBTRACT)
vsn.sign = vfp_sign_negate(vsn.sign);
- exceptions |= vfp_double_add(&vsd, &vsn, &vsp, fpscr);
-
- s64 debug = vfp_double_pack(&vsd);
-
- return vfp_double_fcvtsinterncutting(state, sd, &vsd, fpscr);
+ exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
+ return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func);
}
/*