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:
Merry
2022-07-17 15:34:11 +01:00
parent 2e1ab36240
commit cf08130f2c
15 changed files with 284 additions and 271 deletions

View File

@@ -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()) {

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 )

View File

@@ -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;

View File

@@ -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: {