Merge pull request #472 from lioncash/overflow
dyncom: Fix some more V-flag setting ops. Plus some cleanup.
This commit is contained in:
commit
f3a7b66267
|
@ -3968,15 +3968,11 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
arm_inst* inst_base;
|
arm_inst* inst_base;
|
||||||
unsigned int lop, rop, dst;
|
|
||||||
unsigned int addr;
|
unsigned int addr;
|
||||||
unsigned int phys_addr;
|
unsigned int phys_addr;
|
||||||
unsigned int last_pc = 0;
|
|
||||||
unsigned int num_instrs = 0;
|
unsigned int num_instrs = 0;
|
||||||
|
|
||||||
static unsigned int last_physical_base = 0, last_logical_base = 0;
|
|
||||||
int ptr;
|
int ptr;
|
||||||
bool single_step = (cpu->NumInstrsToExecute == 1);
|
|
||||||
|
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
DISPATCH:
|
DISPATCH:
|
||||||
|
@ -4003,16 +3999,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
ADC_INST:
|
ADC_INST:
|
||||||
{
|
{
|
||||||
adc_inst *inst_cream = (adc_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
adc_inst* const inst_cream = (adc_inst*)inst_base->component;
|
||||||
u32 left = RN;
|
|
||||||
u32 right = SHIFTER_OPERAND;
|
|
||||||
|
|
||||||
u64 unsigned_sum = (left + right + cpu->CFlag);
|
bool carry;
|
||||||
s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)cpu->CFlag;
|
bool overflow;
|
||||||
u32 result = (unsigned_sum & 0xFFFFFFFF);
|
RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
|
||||||
|
|
||||||
RD = result;
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4020,10 +4013,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(result);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(result);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_CARRY_FROM_ADD(left, right, cpu->CFlag);
|
cpu->CFlag = carry;
|
||||||
cpu->VFlag = ((s64)(s32)result != signed_sum);
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(adc_inst));
|
INC_PC(sizeof(adc_inst));
|
||||||
|
@ -4037,14 +4030,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
ADD_INST:
|
ADD_INST:
|
||||||
{
|
{
|
||||||
add_inst *inst_cream = (add_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
add_inst* const inst_cream = (add_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
if (inst_cream->Rn == 15) {
|
u32 rn_val = RN;
|
||||||
lop += 2 * GET_INST_SIZE(cpu);
|
if (inst_cream->Rn == 15)
|
||||||
}
|
rn_val += 2 * GET_INST_SIZE(cpu);
|
||||||
rop = SHIFTER_OPERAND;
|
|
||||||
RD = dst = lop + rop;
|
bool carry;
|
||||||
|
bool overflow;
|
||||||
|
RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4052,10 +4048,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG(dst, lop, rop);
|
cpu->CFlag = carry;
|
||||||
UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(add_inst));
|
INC_PC(sizeof(add_inst));
|
||||||
|
@ -4071,9 +4067,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
{
|
{
|
||||||
and_inst *inst_cream = (and_inst *)inst_base->component;
|
and_inst *inst_cream = (and_inst *)inst_base->component;
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
||||||
lop = RN;
|
u32 lop = RN;
|
||||||
rop = SHIFTER_OPERAND;
|
u32 rop = SHIFTER_OPERAND;
|
||||||
RD = dst = lop & rop;
|
RD = lop & rop;
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4081,8 +4077,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -4114,12 +4110,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
{
|
{
|
||||||
bic_inst *inst_cream = (bic_inst *)inst_base->component;
|
bic_inst *inst_cream = (bic_inst *)inst_base->component;
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
||||||
lop = RN;
|
u32 lop = RN;
|
||||||
if (inst_cream->Rn == 15) {
|
if (inst_cream->Rn == 15) {
|
||||||
lop += 2 * GET_INST_SIZE(cpu);
|
lop += 2 * GET_INST_SIZE(cpu);
|
||||||
}
|
}
|
||||||
rop = SHIFTER_OPERAND;
|
u32 rop = SHIFTER_OPERAND;
|
||||||
RD = dst = lop & (~rop);
|
RD = lop & (~rop);
|
||||||
if ((inst_cream->S) && (inst_cream->Rd == 15)) {
|
if ((inst_cream->S) && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4127,8 +4123,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -4234,15 +4230,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
CMN_INST:
|
CMN_INST:
|
||||||
{
|
{
|
||||||
cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
rop = SHIFTER_OPERAND;
|
bool carry;
|
||||||
dst = lop + rop;
|
bool overflow;
|
||||||
UPDATE_NFLAG(dst);
|
u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow);
|
||||||
UPDATE_ZFLAG(dst);
|
|
||||||
UPDATE_CFLAG(dst, lop, rop);
|
UPDATE_NFLAG(result);
|
||||||
UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
|
UPDATE_ZFLAG(result);
|
||||||
|
cpu->CFlag = carry;
|
||||||
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(cmn_inst));
|
INC_PC(sizeof(cmn_inst));
|
||||||
|
@ -4251,19 +4249,21 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
CMP_INST:
|
CMP_INST:
|
||||||
{
|
{
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
|
cmp_inst* const 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;
|
|
||||||
|
|
||||||
UPDATE_NFLAG(dst);
|
u32 rn_val = RN;
|
||||||
UPDATE_ZFLAG(dst);
|
if (inst_cream->Rn == 15)
|
||||||
UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
|
rn_val += 2 * GET_INST_SIZE(cpu);
|
||||||
UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
|
|
||||||
|
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);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(cmp_inst));
|
INC_PC(sizeof(cmp_inst));
|
||||||
|
@ -4321,12 +4321,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
{
|
{
|
||||||
eor_inst *inst_cream = (eor_inst *)inst_base->component;
|
eor_inst *inst_cream = (eor_inst *)inst_base->component;
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
||||||
lop = RN;
|
u32 lop = RN;
|
||||||
if (inst_cream->Rn == 15) {
|
if (inst_cream->Rn == 15) {
|
||||||
lop += 2 * GET_INST_SIZE(cpu);
|
lop += 2 * GET_INST_SIZE(cpu);
|
||||||
}
|
}
|
||||||
rop = SHIFTER_OPERAND;
|
u32 rop = SHIFTER_OPERAND;
|
||||||
RD = dst = lop ^ rop;
|
RD = lop ^ rop;
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4334,8 +4334,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -4852,10 +4852,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOG_ERROR(Core_ARM11, "invalid operands for MLA");
|
LOG_ERROR(Core_ARM11, "invalid operands for MLA");
|
||||||
CITRA_IGNORE_EXIT(-1);
|
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) {
|
if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(mla_inst));
|
INC_PC(sizeof(mla_inst));
|
||||||
|
@ -4871,7 +4871,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
{
|
{
|
||||||
mov_inst *inst_cream = (mov_inst *)inst_base->component;
|
mov_inst *inst_cream = (mov_inst *)inst_base->component;
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
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 (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -4879,8 +4879,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -5016,10 +5016,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
||||||
uint64_t rm = RM;
|
uint64_t rm = RM;
|
||||||
uint64_t rs = RS;
|
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) {
|
if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(mul_inst));
|
INC_PC(sizeof(mul_inst));
|
||||||
|
@ -5033,9 +5033,11 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
MVN_INST:
|
MVN_INST:
|
||||||
{
|
{
|
||||||
mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
|
||||||
RD = dst = ~SHIFTER_OPERAND;
|
|
||||||
|
RD = ~SHIFTER_OPERAND;
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -5043,8 +5045,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -5059,11 +5061,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
ORR_INST:
|
ORR_INST:
|
||||||
{
|
{
|
||||||
orr_inst *inst_cream = (orr_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
orr_inst* const inst_cream = (orr_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
rop = SHIFTER_OPERAND;
|
u32 lop = RN;
|
||||||
RD = dst = lop | rop;
|
u32 rop = SHIFTER_OPERAND;
|
||||||
|
RD = lop | rop;
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -5071,8 +5075,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
|
@ -5292,14 +5296,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
RFE_INST:
|
RFE_INST:
|
||||||
RSB_INST:
|
RSB_INST:
|
||||||
{
|
{
|
||||||
rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
|
||||||
rop = RN;
|
|
||||||
lop = SHIFTER_OPERAND;
|
u32 rn_val = RN;
|
||||||
if (inst_cream->Rn == 15) {
|
if (inst_cream->Rn == 15)
|
||||||
rop += 2 * GET_INST_SIZE(cpu);;
|
rn_val += 2 * GET_INST_SIZE(cpu);
|
||||||
}
|
|
||||||
RD = dst = lop - rop;
|
bool carry;
|
||||||
|
bool overflow;
|
||||||
|
RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -5307,10 +5314,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
|
cpu->CFlag = carry;
|
||||||
UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(rsb_inst));
|
INC_PC(sizeof(rsb_inst));
|
||||||
|
@ -5324,11 +5331,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
RSC_INST:
|
RSC_INST:
|
||||||
{
|
{
|
||||||
rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
rop = SHIFTER_OPERAND;
|
bool carry;
|
||||||
RD = dst = rop - lop - !cpu->CFlag;
|
bool overflow;
|
||||||
|
RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -5336,10 +5345,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag);
|
cpu->CFlag = carry;
|
||||||
UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop);
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(rsc_inst));
|
INC_PC(sizeof(rsc_inst));
|
||||||
|
@ -5462,11 +5471,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
|
|
||||||
SBC_INST:
|
SBC_INST:
|
||||||
{
|
{
|
||||||
sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
|
||||||
lop = SHIFTER_OPERAND + !cpu->CFlag;
|
|
||||||
rop = RN;
|
bool carry;
|
||||||
RD = dst = rop - lop;
|
bool overflow;
|
||||||
|
RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -5474,15 +5485,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
|
cpu->CFlag = carry;
|
||||||
if(rop >= !cpu->CFlag)
|
cpu->VFlag = overflow;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(sbc_inst));
|
INC_PC(sizeof(sbc_inst));
|
||||||
|
@ -6260,14 +6266,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
SUB_INST:
|
SUB_INST:
|
||||||
{
|
{
|
||||||
sub_inst *inst_cream = (sub_inst *)inst_base->component;
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
sub_inst* const inst_cream = (sub_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
if (inst_cream->Rn == 15) {
|
u32 rn_val = RN;
|
||||||
lop += 8;
|
if (inst_cream->Rn == 15)
|
||||||
}
|
rn_val += 8;
|
||||||
rop = SHIFTER_OPERAND;
|
|
||||||
RD = dst = lop - rop;
|
bool carry;
|
||||||
|
bool overflow;
|
||||||
|
RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
|
||||||
|
|
||||||
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
if (inst_cream->S && (inst_cream->Rd == 15)) {
|
||||||
if (CurrentModeHasSPSR) {
|
if (CurrentModeHasSPSR) {
|
||||||
cpu->Cpsr = cpu->Spsr_copy;
|
cpu->Cpsr = cpu->Spsr_copy;
|
||||||
|
@ -6275,10 +6284,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
} else if (inst_cream->S) {
|
} else if (inst_cream->S) {
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(RD);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(RD);
|
||||||
UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
|
cpu->CFlag = carry;
|
||||||
UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
|
cpu->VFlag = overflow;
|
||||||
}
|
}
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(sub_inst));
|
INC_PC(sizeof(sub_inst));
|
||||||
|
@ -6406,18 +6415,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
|
|
||||||
TEQ_INST:
|
TEQ_INST:
|
||||||
{
|
{
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
teq_inst *inst_cream = (teq_inst *)inst_base->component;
|
teq_inst* const inst_cream = (teq_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
|
u32 lop = RN;
|
||||||
|
u32 rop = SHIFTER_OPERAND;
|
||||||
|
|
||||||
if (inst_cream->Rn == 15)
|
if (inst_cream->Rn == 15)
|
||||||
lop += GET_INST_SIZE(cpu) * 2;
|
lop += GET_INST_SIZE(cpu) * 2;
|
||||||
|
|
||||||
rop = SHIFTER_OPERAND;
|
u32 result = lop ^ rop;
|
||||||
dst = lop ^ rop;
|
|
||||||
|
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(result);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(result);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
|
@ -6427,18 +6437,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
TST_INST:
|
TST_INST:
|
||||||
{
|
{
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
tst_inst *inst_cream = (tst_inst *)inst_base->component;
|
tst_inst* const inst_cream = (tst_inst*)inst_base->component;
|
||||||
lop = RN;
|
|
||||||
|
u32 lop = RN;
|
||||||
|
u32 rop = SHIFTER_OPERAND;
|
||||||
|
|
||||||
if (inst_cream->Rn == 15)
|
if (inst_cream->Rn == 15)
|
||||||
lop += GET_INST_SIZE(cpu) * 2;
|
lop += GET_INST_SIZE(cpu) * 2;
|
||||||
|
|
||||||
rop = SHIFTER_OPERAND;
|
u32 result = lop & rop;
|
||||||
dst = lop & rop;
|
|
||||||
|
|
||||||
UPDATE_NFLAG(dst);
|
UPDATE_NFLAG(result);
|
||||||
UPDATE_ZFLAG(dst);
|
UPDATE_ZFLAG(result);
|
||||||
UPDATE_CFLAG_WITH_SC;
|
UPDATE_CFLAG_WITH_SC;
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
|
|
|
@ -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.
|
// Compute whether an addition of A and B, giving RESULT, overflowed.
|
||||||
bool AddOverflow(ARMword a, ARMword b, ARMword result)
|
bool AddOverflow(ARMword a, ARMword b, ARMword result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -795,6 +795,7 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
|
||||||
extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
|
extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
|
||||||
extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
|
extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
|
||||||
|
|
||||||
|
extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);
|
||||||
extern bool ARMul_AddOverflowQ(ARMword, ARMword);
|
extern bool ARMul_AddOverflowQ(ARMword, ARMword);
|
||||||
|
|
||||||
extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
|
extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
|
||||||
|
|
Reference in New Issue