# This is a combination of 4 commits.
^ This is the 1st commit message: backend/A64: impl EmitA32SetCpsrNZ(C) + GetCFlagFromNZCV Fix NZC Stuff impl GetCFlagFromNZCV fix EmitA32SetCpsrNZC simplify EmitGetCFlagFromNZCV EmitGetNZCVFromOp clang-format clang format ^ This is the commit message #2: fix EmitA32SetCpsrNZC # This is the commit message #3: simplify EmitGetCFlagFromNZCV # This is the commit message #4: EmitGetNZCVFromOp clang-format
This commit is contained in:
parent
40db85e783
commit
0dde1d1ff3
@ -504,7 +504,49 @@ void A32EmitA64::EmitA32SetCpsrNZCVQ(A32EmitContext& ctx, IR::Inst* inst) {
|
|||||||
code._MSR(FIELD_FPSR, host_fpsr);
|
code._MSR(FIELD_FPSR, host_fpsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void A32EmitA64::EmitA32SetCpsrNZ(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
|
const ARM64Reg nz = EncodeRegTo32(ctx.reg_alloc.UseGpr(args[0]));
|
||||||
|
const ARM64Reg nzcv = EncodeRegTo32(ctx.reg_alloc.ScratchGpr());
|
||||||
|
|
||||||
|
code.LDR(INDEX_UNSIGNED, nzcv, X28, offsetof(A32JitState, cpsr_nzcv));
|
||||||
|
code.ANDI2R(nzcv, nzcv, 0x3000'0000);
|
||||||
|
code.ORR(nzcv, nzcv, nz);
|
||||||
|
code.STR(INDEX_UNSIGNED, nzcv, X28, offsetof(A32JitState, cpsr_nzcv));
|
||||||
|
}
|
||||||
|
|
||||||
|
void A32EmitA64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
const ARM64Reg nzcv = EncodeRegTo32(ctx.reg_alloc.ScratchGpr());
|
||||||
|
code.LDR(INDEX_UNSIGNED, nzcv, X28, offsetof(A32JitState, cpsr_nzcv));
|
||||||
|
code.ANDI2R(nzcv, nzcv, 0x1000'0000);
|
||||||
|
if (args[0].IsImmediate()) {
|
||||||
|
if (args[1].IsImmediate()) {
|
||||||
|
const u32 c = (args[1].GetImmediateU32() << 29);
|
||||||
|
if (c) {
|
||||||
|
code.ORRI2R(nzcv, nzcv, c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const ARM64Reg c = EncodeRegTo32(ctx.reg_alloc.UseGpr(args[1]));
|
||||||
|
code.ORR(nzcv, nzcv, c, {nzcv, ST_LSL, 29});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const ARM64Reg nz = EncodeRegTo32(ctx.reg_alloc.UseScratchGpr(args[0]));
|
||||||
|
if (args[1].IsImmediate()) {
|
||||||
|
const u32 c = args[1].GetImmediateU32() << 29;
|
||||||
|
code.ORR(nzcv, nzcv, nz);
|
||||||
|
if (c) {
|
||||||
|
code.ORRI2R(nzcv, nzcv, c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const ARM64Reg c = EncodeRegTo32(ctx.reg_alloc.UseGpr(args[1]));
|
||||||
|
code.ORR(nzcv, nzcv, nz);
|
||||||
|
code.ORR(nzcv, nzcv, c, {nzcv, ST_LSL, 29});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code.STR(INDEX_UNSIGNED, nzcv, X28, offsetof(A32JitState, cpsr_nzcv));
|
||||||
|
}
|
||||||
|
|
||||||
void A32EmitA64::EmitA32SetCheckBit(A32EmitContext& ctx, IR::Inst* inst) {
|
void A32EmitA64::EmitA32SetCheckBit(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
@ -1409,8 +1451,8 @@ void A32EmitA64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDesc
|
|||||||
PushRSBHelper(X1, X2, terminal.next);
|
PushRSBHelper(X1, X2, terminal.next);
|
||||||
code.ForceReturnFromRunCode();
|
code.ForceReturnFromRunCode();
|
||||||
|
|
||||||
//Todo: find a better/generic place to FlushIcache when switching between
|
// Todo: find a better/generic place to FlushIcache when switching between
|
||||||
// far code and near code
|
// far code and near code
|
||||||
code.FlushIcache();
|
code.FlushIcache();
|
||||||
code.SwitchToNearCode();
|
code.SwitchToNearCode();
|
||||||
}
|
}
|
||||||
@ -1551,7 +1593,9 @@ void A32EmitA64::Unpatch(const IR::LocationDescriptor& location) {
|
|||||||
EmitA64::Unpatch(location);
|
EmitA64::Unpatch(location);
|
||||||
if (config.HasOptimization(OptimizationFlag::FastDispatch)) {
|
if (config.HasOptimization(OptimizationFlag::FastDispatch)) {
|
||||||
code.DisableWriting();
|
code.DisableWriting();
|
||||||
SCOPE_EXIT { code.EnableWriting(); };
|
SCOPE_EXIT {
|
||||||
|
code.EnableWriting();
|
||||||
|
};
|
||||||
|
|
||||||
(*fast_dispatch_table_lookup)(location.Value()) = {};
|
(*fast_dispatch_table_lookup)(location.Value()) = {};
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ private:
|
|||||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, config.callbacks, {config.arch_version, config.define_unpredictable_behaviour, config.hook_hint_instructions});
|
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, config.callbacks, {config.arch_version, config.define_unpredictable_behaviour, config.hook_hint_instructions});
|
||||||
Optimization::PolyfillPass(ir_block, polyfill_options);
|
Optimization::PolyfillPass(ir_block, polyfill_options);
|
||||||
if (config.HasOptimization(OptimizationFlag::GetSetElimination)) {
|
if (config.HasOptimization(OptimizationFlag::GetSetElimination)) {
|
||||||
Optimization::A32GetSetElimination(ir_block);
|
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
|
||||||
Optimization::DeadCodeElimination(ir_block);
|
Optimization::DeadCodeElimination(ir_block);
|
||||||
}
|
}
|
||||||
if (config.HasOptimization(OptimizationFlag::ConstProp)) {
|
if (config.HasOptimization(OptimizationFlag::ConstProp)) {
|
||||||
|
@ -116,16 +116,80 @@ void EmitA64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) {
|
|||||||
ASSERT_FALSE("should never happen");
|
ASSERT_FALSE("should never happen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitA64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
|
const auto sign_extend = [&](ARM64Reg value) {
|
||||||
|
switch (args[0].GetType()) {
|
||||||
|
case IR::Type::U8:
|
||||||
|
code.SXTB(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U16:
|
||||||
|
code.SXTH(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U32:
|
||||||
|
code.SXTW(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U64:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Arm64Gen::ARM64Reg nz = ctx.reg_alloc.ScratchGpr();
|
||||||
|
const Arm64Gen::ARM64Reg value = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
|
sign_extend(value);
|
||||||
|
code.CMP(value, ZR);
|
||||||
|
code.MRS(nz, FIELD_NZCV);
|
||||||
|
code.ANDI2R(nz, nz, 0xC0000000);
|
||||||
|
ctx.reg_alloc.DefineValue(inst, nz);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitA64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
|
void EmitA64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
|
const auto sign_extend = [&](ARM64Reg value) {
|
||||||
|
switch (args[0].GetType()) {
|
||||||
|
case IR::Type::U8:
|
||||||
|
code.SXTB(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U16:
|
||||||
|
code.SXTH(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U32:
|
||||||
|
code.SXTW(Arm64Gen::EncodeRegTo64(value), Arm64Gen::EncodeRegTo32(value));
|
||||||
|
break;
|
||||||
|
case IR::Type::U64:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Arm64Gen::ARM64Reg nzcv = ctx.reg_alloc.ScratchGpr();
|
Arm64Gen::ARM64Reg nzcv = ctx.reg_alloc.ScratchGpr();
|
||||||
Arm64Gen::ARM64Reg value = ctx.reg_alloc.UseGpr(args[0]);
|
Arm64Gen::ARM64Reg value = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
|
sign_extend(value);
|
||||||
code.CMP(value, ZR);
|
code.CMP(value, ZR);
|
||||||
code.MRS(nzcv, FIELD_NZCV);
|
code.MRS(nzcv, FIELD_NZCV);
|
||||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitA64::EmitGetCFlagFromNZCV(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
|
if (args[0].IsImmediate()) {
|
||||||
|
const ARM64Reg result = EncodeRegTo32(ctx.reg_alloc.ScratchGpr());
|
||||||
|
const u32 value = (args[0].GetImmediateU32() >> 29) & 1;
|
||||||
|
code.MOVI2R(result, value);
|
||||||
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
} else {
|
||||||
|
const ARM64Reg result = EncodeRegTo32(ctx.reg_alloc.UseScratchGpr(args[0]));
|
||||||
|
code.UBFX(result, result, 29, 1);
|
||||||
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmitA64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
void EmitA64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ A32OPC(SetExtendedRegister64, Void, A32E
|
|||||||
A32OPC(GetCpsr, U32, )
|
A32OPC(GetCpsr, U32, )
|
||||||
A32OPC(SetCpsr, Void, U32 )
|
A32OPC(SetCpsr, Void, U32 )
|
||||||
A32OPC(SetCpsrNZCV, Void, NZCV )
|
A32OPC(SetCpsrNZCV, Void, NZCV )
|
||||||
|
A32OPC(SetCpsrNZ, Void, NZCV )
|
||||||
|
A32OPC(SetCpsrNZC, Void, NZCV, U1 )
|
||||||
A32OPC(SetCpsrNZCVRaw, Void, U32 )
|
A32OPC(SetCpsrNZCVRaw, Void, U32 )
|
||||||
A32OPC(SetCpsrNZCVQ, Void, U32 )
|
A32OPC(SetCpsrNZCVQ, Void, U32 )
|
||||||
A32OPC(GetCFlag, U1, )
|
A32OPC(GetCFlag, U1, )
|
||||||
@ -86,9 +88,10 @@ OPCODE(GetCarryFromOp, U1, Opaq
|
|||||||
OPCODE(GetOverflowFromOp, U1, Opaque )
|
OPCODE(GetOverflowFromOp, U1, Opaque )
|
||||||
OPCODE(GetGEFromOp, U32, Opaque )
|
OPCODE(GetGEFromOp, U32, Opaque )
|
||||||
OPCODE(GetNZCVFromOp, NZCV, Opaque )
|
OPCODE(GetNZCVFromOp, NZCV, Opaque )
|
||||||
|
OPCODE(GetNZFromOp, NZCV, Opaque )
|
||||||
OPCODE(GetUpperFromOp, U128, Opaque )
|
OPCODE(GetUpperFromOp, U128, Opaque )
|
||||||
OPCODE(GetLowerFromOp, U128, Opaque )
|
OPCODE(GetLowerFromOp, U128, Opaque )
|
||||||
|
OPCODE(GetCFlagFromNZCV, U1, NZCV )
|
||||||
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
|
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
|
||||||
|
|
||||||
// Calculations
|
// Calculations
|
||||||
|
Loading…
x
Reference in New Issue
Block a user