# 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:
SachinVin 2022-09-10 16:33:18 +05:30
parent 40db85e783
commit 0dde1d1ff3
4 changed files with 116 additions and 5 deletions

View File

@ -504,7 +504,49 @@ void A32EmitA64::EmitA32SetCpsrNZCVQ(A32EmitContext& ctx, IR::Inst* inst) {
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) {
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);
code.ForceReturnFromRunCode();
//Todo: find a better/generic place to FlushIcache when switching between
// far code and near code
// Todo: find a better/generic place to FlushIcache when switching between
// far code and near code
code.FlushIcache();
code.SwitchToNearCode();
}
@ -1551,7 +1593,9 @@ void A32EmitA64::Unpatch(const IR::LocationDescriptor& location) {
EmitA64::Unpatch(location);
if (config.HasOptimization(OptimizationFlag::FastDispatch)) {
code.DisableWriting();
SCOPE_EXIT { code.EnableWriting(); };
SCOPE_EXIT {
code.EnableWriting();
};
(*fast_dispatch_table_lookup)(location.Value()) = {};
}

View File

@ -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});
Optimization::PolyfillPass(ir_block, polyfill_options);
if (config.HasOptimization(OptimizationFlag::GetSetElimination)) {
Optimization::A32GetSetElimination(ir_block);
Optimization::A32GetSetElimination(ir_block, {.convert_nz_to_nzc = true});
Optimization::DeadCodeElimination(ir_block);
}
if (config.HasOptimization(OptimizationFlag::ConstProp)) {

View File

@ -116,16 +116,80 @@ void EmitA64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) {
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) {
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 value = ctx.reg_alloc.UseGpr(args[0]);
sign_extend(value);
code.CMP(value, ZR);
code.MRS(nzcv, FIELD_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) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);

View File

@ -20,6 +20,8 @@ A32OPC(SetExtendedRegister64, Void, A32E
A32OPC(GetCpsr, U32, )
A32OPC(SetCpsr, Void, U32 )
A32OPC(SetCpsrNZCV, Void, NZCV )
A32OPC(SetCpsrNZ, Void, NZCV )
A32OPC(SetCpsrNZC, Void, NZCV, U1 )
A32OPC(SetCpsrNZCVRaw, Void, U32 )
A32OPC(SetCpsrNZCVQ, Void, U32 )
A32OPC(GetCFlag, U1, )
@ -86,9 +88,10 @@ 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 )
OPCODE(GetCFlagFromNZCV, U1, NZCV )
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
// Calculations