arm64/reg_alloc: Remove PrepareForCallReg and PrepareForCallVec

This commit is contained in:
Merry 2022-11-29 15:11:00 +00:00 committed by Liam
parent 73eecfbaef
commit 4f1f7c8e97
6 changed files with 24 additions and 47 deletions

View file

@ -24,19 +24,6 @@ static void EmitCoprocessorException() {
} }
static void CallCoprocCallback(oaknut::CodeGenerator& code, EmitContext& ctx, A32::Coprocessor::Callback callback, IR::Inst* inst = nullptr, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}) { static void CallCoprocCallback(oaknut::CodeGenerator& code, EmitContext& ctx, A32::Coprocessor::Callback callback, IR::Inst* inst = nullptr, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}) {
if (inst) {
const auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, arg0, arg1);
if (callback.user_arg) {
code.MOV(X0, reinterpret_cast<u64>(*callback.user_arg));
}
code.MOV(Xscratch0, reinterpret_cast<u64>(callback.function));
code.BLR(Xscratch0);
code.MOV(Xresult, X0);
return;
}
ctx.reg_alloc.PrepareForCall({}, arg0, arg1); ctx.reg_alloc.PrepareForCall({}, arg0, arg1);
if (callback.user_arg) { if (callback.user_arg) {
@ -45,6 +32,10 @@ static void CallCoprocCallback(oaknut::CodeGenerator& code, EmitContext& ctx, A3
code.MOV(Xscratch0, reinterpret_cast<u64>(callback.function)); code.MOV(Xscratch0, reinterpret_cast<u64>(callback.function));
code.BLR(Xscratch0); code.BLR(Xscratch0);
if (inst) {
ctx.reg_alloc.DefineAsRegister(inst, X0);
}
} }
template<> template<>

View file

@ -25,19 +25,19 @@ static bool IsOrdered(IR::AccType acctype) {
static void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, fn);
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
code.MOV(Wscratch0, 1); code.MOV(Wscratch0, 1);
@ -46,7 +46,7 @@ static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ct
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
@ -65,7 +65,7 @@ static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::I
static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1], args[2]); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]);
const bool ordered = IsOrdered(args[3].GetImmediateAccType()); const bool ordered = IsOrdered(args[3].GetImmediateAccType());
oaknut::Label end; oaknut::Label end;
@ -81,7 +81,7 @@ static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& c
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.l(end); code.l(end);
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
template<> template<>

View file

@ -423,7 +423,7 @@ void EmitIR<IR::Opcode::A64GetCNTFRQ>(oaknut::CodeGenerator& code, EmitContext&
template<> template<>
void EmitIR<IR::Opcode::A64GetCNTPCT>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64GetCNTPCT>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst); ctx.reg_alloc.PrepareForCall();
if (!ctx.conf.wall_clock_cntpct && ctx.conf.enable_cycle_counting) { if (!ctx.conf.wall_clock_cntpct && ctx.conf.enable_cycle_counting) {
code.LDR(X1, SP, offsetof(StackLayout, cycles_to_run)); code.LDR(X1, SP, offsetof(StackLayout, cycles_to_run));
code.SUB(X1, X1, Xticks); code.SUB(X1, X1, Xticks);
@ -433,7 +433,7 @@ void EmitIR<IR::Opcode::A64GetCNTPCT>(oaknut::CodeGenerator& code, EmitContext&
code.MOV(Xticks, X0); code.MOV(Xticks, X0);
} }
EmitRelocation(code, ctx, LinkTarget::GetCNTPCT); EmitRelocation(code, ctx, LinkTarget::GetCNTPCT);
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
template<> template<>

View file

@ -25,31 +25,32 @@ static bool IsOrdered(IR::AccType acctype) {
static void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, fn);
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
static void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Qresult = ctx.reg_alloc.PrepareForCallVec(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, fn);
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Qresult.B16(), Q0.B16()); code.MOV(Q8.B16(), Q0.B16());
ctx.reg_alloc.DefineAsRegister(inst, Q8);
} }
static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
code.MOV(Wscratch0, 1); code.MOV(Wscratch0, 1);
@ -58,12 +59,12 @@ static void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ct
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
static void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Qresult = ctx.reg_alloc.PrepareForCallVec(inst, {}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
code.MOV(Wscratch0, 1); code.MOV(Wscratch0, 1);
@ -72,7 +73,8 @@ static void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext&
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.MOV(Qresult.B16(), Q0.B16()); code.MOV(Q8.B16(), Q0.B16());
ctx.reg_alloc.DefineAsRegister(inst, Q8);
} }
static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
@ -91,7 +93,7 @@ static void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::I
static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Xresult = ctx.reg_alloc.PrepareForCallReg(inst, {}, args[1], args[2]); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]);
const bool ordered = IsOrdered(args[3].GetImmediateAccType()); const bool ordered = IsOrdered(args[3].GetImmediateAccType());
oaknut::Label end; oaknut::Label end;
@ -107,7 +109,7 @@ static void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& c
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
code.l(end); code.l(end);
code.MOV(Xresult, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
template<> template<>

View file

@ -182,20 +182,6 @@ void RegAlloc::PrepareForCall(std::optional<Argument::copyable_reference> arg0,
} }
} }
oaknut::XReg RegAlloc::PrepareForCallReg(IR::Inst* result, std::optional<Argument::copyable_reference> arg0, std::optional<Argument::copyable_reference> arg1, std::optional<Argument::copyable_reference> arg2, std::optional<Argument::copyable_reference> arg3) {
PrepareForCall(arg0, arg1, arg2, arg3);
ASSERT(result && result->GetType() != IR::Type::U128);
DefineAsRegister(result, X0);
return X0;
}
oaknut::QReg RegAlloc::PrepareForCallVec(IR::Inst* result, std::optional<Argument::copyable_reference> arg0, std::optional<Argument::copyable_reference> arg1, std::optional<Argument::copyable_reference> arg2, std::optional<Argument::copyable_reference> arg3) {
PrepareForCall(arg0, arg1, arg2, arg3);
ASSERT(result && result->GetType() == IR::Type::U128);
DefineAsRegister(result, Q8);
return Q8;
}
void RegAlloc::DefineAsExisting(IR::Inst* inst, Argument& arg) { void RegAlloc::DefineAsExisting(IR::Inst* inst, Argument& arg) {
ASSERT(!ValueLocation(inst)); ASSERT(!ValueLocation(inst));

View file

@ -272,8 +272,6 @@ public:
} }
void PrepareForCall(std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}, std::optional<Argument::copyable_reference> arg2 = {}, std::optional<Argument::copyable_reference> arg3 = {}); void PrepareForCall(std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}, std::optional<Argument::copyable_reference> arg2 = {}, std::optional<Argument::copyable_reference> arg3 = {});
oaknut::XReg PrepareForCallReg(IR::Inst* result, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}, std::optional<Argument::copyable_reference> arg2 = {}, std::optional<Argument::copyable_reference> arg3 = {});
oaknut::QReg PrepareForCallVec(IR::Inst* result, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}, std::optional<Argument::copyable_reference> arg2 = {}, std::optional<Argument::copyable_reference> arg3 = {});
void DefineAsExisting(IR::Inst* inst, Argument& arg); void DefineAsExisting(IR::Inst* inst, Argument& arg);
void DefineAsRegister(IR::Inst* inst, oaknut::Reg reg); void DefineAsRegister(IR::Inst* inst, oaknut::Reg reg);