# 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);
|
||||
}
|
||||
|
||||
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()) = {};
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user