mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-03-03 01:42:57 +00:00
A32: Condense flag handling
Remove individual flag handlers, and handle them in chuks where able, to produce more optimal code.
This commit is contained in:
@@ -541,6 +541,37 @@ void A32EmitX64::EmitA32SetCpsrNZCVQ(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
}
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetCpsrNZ(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
ctx.reg_alloc.Use(args[0], HostLoc::RAX);
|
||||
|
||||
code.mov(al, code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1]);
|
||||
code.and_(al, 1);
|
||||
code.or_(al, ah);
|
||||
code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
ctx.reg_alloc.Use(args[0], HostLoc::RAX);
|
||||
|
||||
if (args[1].IsImmediate()) {
|
||||
const bool c = args[1].GetImmediateU1();
|
||||
|
||||
code.mov(al, ah);
|
||||
code.or_(al, c);
|
||||
code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al);
|
||||
} else {
|
||||
const Xbyak::Reg8 c = ctx.reg_alloc.UseGpr(args[1]).cvt8();
|
||||
|
||||
code.mov(al, ah);
|
||||
code.or_(al, c);
|
||||
code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitGetFlag(BlockOfCode& code, A32EmitContext& ctx, IR::Inst* inst, size_t flag_bit) {
|
||||
const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32();
|
||||
code.mov(result, dword[r15 + offsetof(A32JitState, cpsr_nzcv)]);
|
||||
@@ -551,48 +582,10 @@ static void EmitGetFlag(BlockOfCode& code, A32EmitContext& ctx, IR::Inst* inst,
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
static void EmitSetFlag(BlockOfCode& code, A32EmitContext& ctx, IR::Inst* inst, size_t flag_bit) {
|
||||
const u32 flag_mask = 1u << flag_bit;
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
if (args[0].IsImmediate()) {
|
||||
if (args[0].GetImmediateU1()) {
|
||||
code.or_(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], flag_mask);
|
||||
} else {
|
||||
code.and_(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], ~flag_mask);
|
||||
}
|
||||
} else {
|
||||
const Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
|
||||
if (flag_bit != 0) {
|
||||
code.shl(to_store, static_cast<int>(flag_bit));
|
||||
code.and_(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], ~flag_mask);
|
||||
code.or_(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], to_store);
|
||||
} else {
|
||||
code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv)], to_store.cvt8());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetNFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
EmitSetFlag(code, ctx, inst, NZCV::x64_n_flag_bit);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetZFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
EmitSetFlag(code, ctx, inst, NZCV::x64_z_flag_bit);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32GetCFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
EmitGetFlag(code, ctx, inst, NZCV::x64_c_flag_bit);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetCFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
EmitSetFlag(code, ctx, inst, NZCV::x64_c_flag_bit);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetVFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
EmitSetFlag(code, ctx, inst, NZCV::x64_v_flag_bit);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32OrQFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
if (args[0].IsImmediate()) {
|
||||
|
||||
@@ -134,6 +134,31 @@ void EmitX64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) {
|
||||
ASSERT_MSG(false, "should never happen");
|
||||
}
|
||||
|
||||
void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
const int bitsize = [&] {
|
||||
switch (args[0].GetType()) {
|
||||
case IR::Type::U8:
|
||||
return 8;
|
||||
case IR::Type::U16:
|
||||
return 16;
|
||||
case IR::Type::U32:
|
||||
return 32;
|
||||
case IR::Type::U64:
|
||||
return 64;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}();
|
||||
|
||||
const Xbyak::Reg64 nz = ctx.reg_alloc.ScratchGpr(HostLoc::RAX);
|
||||
const Xbyak::Reg value = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||
code.cmp(value, 0);
|
||||
code.lahf();
|
||||
ctx.reg_alloc.DefineValue(inst, nz);
|
||||
}
|
||||
|
||||
void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
|
||||
@@ -166,22 +166,6 @@ IR::U1 IREmitter::GetCFlag() {
|
||||
return Inst<IR::U1>(Opcode::A32GetCFlag);
|
||||
}
|
||||
|
||||
void IREmitter::SetNFlag(const IR::U1& value) {
|
||||
Inst(Opcode::A32SetNFlag, value);
|
||||
}
|
||||
|
||||
void IREmitter::SetZFlag(const IR::U1& value) {
|
||||
Inst(Opcode::A32SetZFlag, value);
|
||||
}
|
||||
|
||||
void IREmitter::SetCFlag(const IR::U1& value) {
|
||||
Inst(Opcode::A32SetCFlag, value);
|
||||
}
|
||||
|
||||
void IREmitter::SetVFlag(const IR::U1& value) {
|
||||
Inst(Opcode::A32SetVFlag, value);
|
||||
}
|
||||
|
||||
void IREmitter::OrQFlag(const IR::U1& value) {
|
||||
Inst(Opcode::A32OrQFlag, value);
|
||||
}
|
||||
@@ -198,6 +182,18 @@ void IREmitter::SetGEFlagsCompressed(const IR::U32& value) {
|
||||
Inst(Opcode::A32SetGEFlagsCompressed, value);
|
||||
}
|
||||
|
||||
IR::NZCV IREmitter::NZFrom(const IR::Value& value) {
|
||||
return Inst<IR::NZCV>(Opcode::GetNZFromOp, value);
|
||||
}
|
||||
|
||||
void IREmitter::SetCpsrNZ(const IR::NZCV& nz) {
|
||||
Inst(Opcode::A32SetCpsrNZ, nz);
|
||||
}
|
||||
|
||||
void IREmitter::SetCpsrNZC(const IR::NZCV& nz, const IR::U1& c) {
|
||||
Inst(Opcode::A32SetCpsrNZC, nz, c);
|
||||
}
|
||||
|
||||
void IREmitter::DataSynchronizationBarrier() {
|
||||
Inst(Opcode::A32DataSynchronizationBarrier);
|
||||
}
|
||||
|
||||
@@ -62,15 +62,15 @@ public:
|
||||
void SetCheckBit(const IR::U1& value);
|
||||
IR::U1 GetOverflowFrom(const IR::Value& value);
|
||||
IR::U1 GetCFlag();
|
||||
void SetNFlag(const IR::U1& value);
|
||||
void SetZFlag(const IR::U1& value);
|
||||
void SetCFlag(const IR::U1& value);
|
||||
void SetVFlag(const IR::U1& value);
|
||||
void OrQFlag(const IR::U1& value);
|
||||
IR::U32 GetGEFlags();
|
||||
void SetGEFlags(const IR::U32& value);
|
||||
void SetGEFlagsCompressed(const IR::U32& value);
|
||||
|
||||
IR::NZCV NZFrom(const IR::Value& value);
|
||||
void SetCpsrNZ(const IR::NZCV& nz);
|
||||
void SetCpsrNZC(const IR::NZCV& nz, const IR::U1& c);
|
||||
|
||||
void DataSynchronizationBarrier();
|
||||
void DataMemoryBarrier();
|
||||
void InstructionSynchronizationBarrier();
|
||||
|
||||
@@ -181,9 +181,7 @@ bool TranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate,
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -210,9 +208,7 @@ bool TranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5
|
||||
}
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -235,9 +231,7 @@ bool TranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -264,9 +258,7 @@ bool TranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate,
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -294,9 +286,7 @@ bool TranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -319,9 +309,7 @@ bool TranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -438,9 +426,7 @@ bool TranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate,
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -468,9 +454,7 @@ bool TranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -493,9 +477,7 @@ bool TranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -522,9 +504,7 @@ bool TranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8>
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -552,9 +532,7 @@ bool TranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, Shift
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -575,9 +553,7 @@ bool TranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType s
|
||||
const auto result = shifted.result;
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -604,9 +580,7 @@ bool TranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8>
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -634,9 +608,7 @@ bool TranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, Shift
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -659,9 +631,7 @@ bool TranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType s
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -688,9 +658,7 @@ bool TranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate,
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -718,9 +686,7 @@ bool TranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -743,9 +709,7 @@ bool TranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1066,9 +1030,7 @@ bool TranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||
const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||
const auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1082,9 +1044,7 @@ bool TranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shi
|
||||
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||
const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1103,9 +1063,7 @@ bool TranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Re
|
||||
const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||
const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1118,9 +1076,7 @@ bool TranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
|
||||
const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||
const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1134,9 +1090,7 @@ bool TranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shi
|
||||
const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||
const auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1155,9 +1109,7 @@ bool TranslatorVisitor::arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Re
|
||||
const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||
const auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ bool TranslatorVisitor::arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) {
|
||||
const auto result = ir.Add(ir.Mul(ir.GetRegister(n), ir.GetRegister(m)), ir.GetRegister(a));
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -59,8 +58,7 @@ bool TranslatorVisitor::arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
|
||||
const auto result = ir.Mul(ir.GetRegister(n), ir.GetRegister(m));
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -91,8 +89,7 @@ bool TranslatorVisitor::arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Re
|
||||
ir.SetRegister(dLo, lo);
|
||||
ir.SetRegister(dHi, hi);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(hi));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -121,8 +118,7 @@ bool TranslatorVisitor::arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Re
|
||||
ir.SetRegister(dLo, lo);
|
||||
ir.SetRegister(dHi, hi);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(hi));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -177,8 +173,7 @@ bool TranslatorVisitor::arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Re
|
||||
ir.SetRegister(dLo, lo);
|
||||
ir.SetRegister(dHi, hi);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(hi));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -207,8 +202,7 @@ bool TranslatorVisitor::arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Re
|
||||
ir.SetRegister(dLo, lo);
|
||||
ir.SetRegister(dHi, hi);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(hi));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -22,9 +22,7 @@ bool TranslatorVisitor::thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -37,9 +35,7 @@ bool TranslatorVisitor::thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -52,9 +48,7 @@ bool TranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -117,8 +111,7 @@ bool TranslatorVisitor::thumb16_MOV_imm(Reg d, Imm<8> imm8) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -171,8 +164,7 @@ bool TranslatorVisitor::thumb16_AND_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -186,8 +178,7 @@ bool TranslatorVisitor::thumb16_EOR_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -202,9 +193,7 @@ bool TranslatorVisitor::thumb16_LSL_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result_carry.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result_carry.result));
|
||||
ir.SetZFlag(ir.IsZero(result_carry.result));
|
||||
ir.SetCFlag(result_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result_carry.result), result_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -219,9 +208,7 @@ bool TranslatorVisitor::thumb16_LSR_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -236,9 +223,7 @@ bool TranslatorVisitor::thumb16_ASR_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -283,9 +268,7 @@ bool TranslatorVisitor::thumb16_ROR_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result.result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||
ir.SetZFlag(ir.IsZero(result.result));
|
||||
ir.SetCFlag(result.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result.result), result.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -293,8 +276,7 @@ bool TranslatorVisitor::thumb16_ROR_reg(Reg m, Reg d_n) {
|
||||
// TST <Rn>, <Rm>
|
||||
bool TranslatorVisitor::thumb16_TST_reg(Reg m, Reg n) {
|
||||
const auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m));
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -332,8 +314,7 @@ bool TranslatorVisitor::thumb16_ORR_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -347,8 +328,7 @@ bool TranslatorVisitor::thumb16_MUL_reg(Reg n, Reg d_m) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -362,8 +342,7 @@ bool TranslatorVisitor::thumb16_BIC_reg(Reg m, Reg d_n) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -375,8 +354,7 @@ bool TranslatorVisitor::thumb16_MVN_reg(Reg m, Reg d) {
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (!ir.current_location.IT().IsInITBlock()) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCpsrNZ(ir.NZFrom(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ bool TranslatorVisitor::thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm
|
||||
const auto imm_carry = ThumbExpandImm_C(i, imm3, imm8, ir.GetCFlag());
|
||||
const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,9 +30,7 @@ bool TranslatorVisitor::thumb32_AND_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -49,9 +45,7 @@ bool TranslatorVisitor::thumb32_BIC_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -66,9 +60,7 @@ bool TranslatorVisitor::thumb32_MOV_imm(Imm<1> i, bool S, Imm<3> imm3, Reg d, Im
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -84,9 +76,7 @@ bool TranslatorVisitor::thumb32_ORR_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -101,9 +91,7 @@ bool TranslatorVisitor::thumb32_MVN_imm(Imm<1> i, bool S, Imm<3> imm3, Reg d, Im
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -119,9 +107,7 @@ bool TranslatorVisitor::thumb32_ORN_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -134,9 +120,7 @@ bool TranslatorVisitor::thumb32_TEQ_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm
|
||||
const auto imm_carry = ThumbExpandImm_C(i, imm3, imm8, ir.GetCFlag());
|
||||
const auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -151,9 +135,7 @@ bool TranslatorVisitor::thumb32_EOR_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(imm_carry.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), imm_carry.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ bool ShiftInstruction(TranslatorVisitor& v, Reg m, Reg d, Reg s, bool S, ShiftFu
|
||||
const auto result_carry = (v.ir.*shift_fn)(v.ir.GetRegister(m), shift_s, apsr_c);
|
||||
|
||||
if (S) {
|
||||
v.ir.SetNFlag(v.ir.MostSignificantBit(result_carry.result));
|
||||
v.ir.SetZFlag(v.ir.IsZero(result_carry.result));
|
||||
v.ir.SetCFlag(result_carry.carry);
|
||||
v.ir.SetCpsrNZC(v.ir.NZFrom(result_carry.result), result_carry.carry);
|
||||
}
|
||||
|
||||
v.ir.SetRegister(d, result_carry.result);
|
||||
|
||||
@@ -15,9 +15,7 @@ bool TranslatorVisitor::thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftTy
|
||||
const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag());
|
||||
const auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,9 +30,7 @@ bool TranslatorVisitor::thumb32_AND_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2
|
||||
const auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -48,9 +44,7 @@ bool TranslatorVisitor::thumb32_BIC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2
|
||||
const auto result = ir.AndNot(ir.GetRegister(n), shifted.result);
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -64,9 +58,7 @@ bool TranslatorVisitor::thumb32_MOV_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2,
|
||||
const auto result = shifted.result;
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -82,9 +74,7 @@ bool TranslatorVisitor::thumb32_ORR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2
|
||||
const auto result = ir.Or(ir.GetRegister(n), shifted.result);
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -98,9 +88,7 @@ bool TranslatorVisitor::thumb32_MVN_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2,
|
||||
const auto result = ir.Not(shifted.result);
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -116,9 +104,7 @@ bool TranslatorVisitor::thumb32_ORN_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2
|
||||
const auto result = ir.Or(ir.GetRegister(n), ir.Not(shifted.result));
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -131,9 +117,7 @@ bool TranslatorVisitor::thumb32_TEQ_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftTy
|
||||
const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag());
|
||||
const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -148,9 +132,7 @@ bool TranslatorVisitor::thumb32_EOR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2
|
||||
const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||
ir.SetRegister(d, result);
|
||||
if (S) {
|
||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||
ir.SetZFlag(ir.IsZero(result));
|
||||
ir.SetCFlag(shifted.carry);
|
||||
ir.SetCpsrNZC(ir.NZFrom(result), shifted.carry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -176,10 +176,8 @@ bool Inst::WritesToCPSR() const {
|
||||
case Opcode::A32SetCpsrNZCVRaw:
|
||||
case Opcode::A32SetCpsrNZCV:
|
||||
case Opcode::A32SetCpsrNZCVQ:
|
||||
case Opcode::A32SetNFlag:
|
||||
case Opcode::A32SetZFlag:
|
||||
case Opcode::A32SetCFlag:
|
||||
case Opcode::A32SetVFlag:
|
||||
case Opcode::A32SetCpsrNZ:
|
||||
case Opcode::A32SetCpsrNZC:
|
||||
case Opcode::A32OrQFlag:
|
||||
case Opcode::A32SetGEFlags:
|
||||
case Opcode::A32SetGEFlagsCompressed:
|
||||
@@ -546,6 +544,7 @@ bool Inst::IsAPseudoOperation() const {
|
||||
case Opcode::GetOverflowFromOp:
|
||||
case Opcode::GetGEFromOp:
|
||||
case Opcode::GetNZCVFromOp:
|
||||
case Opcode::GetNZFromOp:
|
||||
case Opcode::GetUpperFromOp:
|
||||
case Opcode::GetLowerFromOp:
|
||||
case Opcode::MostSignificantBit:
|
||||
@@ -669,7 +668,7 @@ void Inst::Use(const Value& value) {
|
||||
Inst* insert_point = value.GetInst();
|
||||
while (insert_point->next_pseudoop) {
|
||||
insert_point = insert_point->next_pseudoop;
|
||||
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
|
||||
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == value.GetInst());
|
||||
}
|
||||
insert_point->next_pseudoop = this;
|
||||
}
|
||||
@@ -682,7 +681,7 @@ void Inst::UndoUse(const Value& value) {
|
||||
Inst* insert_point = value.GetInst();
|
||||
while (insert_point->next_pseudoop != this) {
|
||||
insert_point = insert_point->next_pseudoop;
|
||||
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
|
||||
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == value.GetInst());
|
||||
}
|
||||
insert_point->next_pseudoop = next_pseudoop;
|
||||
next_pseudoop = nullptr;
|
||||
|
||||
@@ -22,11 +22,9 @@ A32OPC(SetCpsr, Void, U32
|
||||
A32OPC(SetCpsrNZCV, Void, NZCV )
|
||||
A32OPC(SetCpsrNZCVRaw, Void, U32 )
|
||||
A32OPC(SetCpsrNZCVQ, Void, U32 )
|
||||
A32OPC(SetNFlag, Void, U1 )
|
||||
A32OPC(SetZFlag, Void, U1 )
|
||||
A32OPC(SetCpsrNZ, Void, NZCV )
|
||||
A32OPC(SetCpsrNZC, Void, NZCV, U1 )
|
||||
A32OPC(GetCFlag, U1, )
|
||||
A32OPC(SetCFlag, Void, U1 )
|
||||
A32OPC(SetVFlag, Void, U1 )
|
||||
A32OPC(OrQFlag, Void, U1 )
|
||||
A32OPC(GetGEFlags, U32, )
|
||||
A32OPC(SetGEFlags, Void, U32 )
|
||||
@@ -90,6 +88,7 @@ OPCODE(GetCarryFromOp, U1, Opaq
|
||||
OPCODE(GetOverflowFromOp, U1, Opaque )
|
||||
OPCODE(GetGEFromOp, U32, Opaque )
|
||||
OPCODE(GetNZCVFromOp, NZCV, Opaque )
|
||||
OPCODE(GetNZFromOp, NZCV, Opaque )
|
||||
OPCODE(GetUpperFromOp, U128, Opaque )
|
||||
OPCODE(GetLowerFromOp, U128, Opaque )
|
||||
|
||||
|
||||
@@ -13,13 +13,6 @@ namespace Dynarmic::Optimization {
|
||||
void A32ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) {
|
||||
for (auto& inst : block) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::Opcode::A32SetCFlag: {
|
||||
const IR::Value arg = inst.GetArg(0);
|
||||
if (!arg.IsImmediate() && arg.GetInst()->GetOpcode() == IR::Opcode::A32GetCFlag) {
|
||||
inst.Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32ReadMemory8: {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
break;
|
||||
|
||||
@@ -29,24 +29,34 @@ void A32GetSetElimination(IR::Block& block) {
|
||||
std::array<RegisterInfo, 32> ext_reg_vector_double_info;
|
||||
std::array<RegisterInfo, 16> ext_reg_vector_quad_info;
|
||||
struct CpsrInfo {
|
||||
RegisterInfo n;
|
||||
RegisterInfo z;
|
||||
RegisterInfo nz;
|
||||
RegisterInfo c;
|
||||
RegisterInfo v;
|
||||
RegisterInfo nzc;
|
||||
RegisterInfo nzcv;
|
||||
RegisterInfo ge;
|
||||
} cpsr_info;
|
||||
|
||||
const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst) {
|
||||
const auto do_delete_last_set = [&block](RegisterInfo& info) {
|
||||
if (info.set_instruction_present) {
|
||||
info.set_instruction_present = false;
|
||||
info.last_set_instruction->Invalidate();
|
||||
block.Instructions().erase(info.last_set_instruction);
|
||||
}
|
||||
info = {};
|
||||
};
|
||||
|
||||
const auto do_set = [&do_delete_last_set](RegisterInfo& info, IR::Value value, Iterator set_inst) {
|
||||
do_delete_last_set(info);
|
||||
info.register_value = value;
|
||||
info.set_instruction_present = true;
|
||||
info.last_set_instruction = set_inst;
|
||||
};
|
||||
|
||||
const auto do_set_without_inst = [&do_delete_last_set](RegisterInfo& info, IR::Value value) {
|
||||
do_delete_last_set(info);
|
||||
info.register_value = value;
|
||||
};
|
||||
|
||||
const auto do_get = [](RegisterInfo& info, Iterator get_inst) {
|
||||
if (info.register_value.IsEmpty()) {
|
||||
info.register_value = IR::Value(&*get_inst);
|
||||
@@ -167,24 +177,40 @@ void A32GetSetElimination(IR::Block& block) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetNFlag: {
|
||||
do_set(cpsr_info.n, inst->GetArg(0), inst);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetZFlag: {
|
||||
do_set(cpsr_info.z, inst->GetArg(0), inst);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetCFlag: {
|
||||
do_set(cpsr_info.c, inst->GetArg(0), inst);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32GetCFlag: {
|
||||
do_get(cpsr_info.c, inst);
|
||||
// ensure source is not deleted
|
||||
cpsr_info.nzc = {};
|
||||
cpsr_info.nzcv = {};
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetVFlag: {
|
||||
do_set(cpsr_info.v, inst->GetArg(0), inst);
|
||||
case IR::Opcode::A32SetCpsrNZCV:
|
||||
case IR::Opcode::A32SetCpsrNZCVRaw: {
|
||||
do_delete_last_set(cpsr_info.nz);
|
||||
do_delete_last_set(cpsr_info.c);
|
||||
do_delete_last_set(cpsr_info.nzc);
|
||||
do_set(cpsr_info.nzcv, inst->GetArg(0), inst);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetCpsrNZCVQ: {
|
||||
do_delete_last_set(cpsr_info.nz);
|
||||
do_delete_last_set(cpsr_info.c);
|
||||
do_delete_last_set(cpsr_info.nzc);
|
||||
do_delete_last_set(cpsr_info.nzcv);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetCpsrNZ: {
|
||||
// cpsr_info.c remains valid
|
||||
cpsr_info.nzc = {}; // TODO: Consider reduction of previous to a SetCFlag operation
|
||||
cpsr_info.nzcv = {};
|
||||
do_set(cpsr_info.nz, inst->GetArg(0), inst);
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetCpsrNZC: {
|
||||
cpsr_info.nzcv = {};
|
||||
do_set(cpsr_info.nzc, {}, inst);
|
||||
do_set_without_inst(cpsr_info.nz, inst->GetArg(0));
|
||||
do_set_without_inst(cpsr_info.c, inst->GetArg(1));
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::A32SetGEFlags: {
|
||||
|
||||
Reference in New Issue
Block a user