backend/arm64/reg_alloc: More flag handling

This commit is contained in:
Merry 2022-07-23 14:55:50 +01:00 committed by merry
parent 21601764de
commit 78bc0812b9
2 changed files with 29 additions and 1 deletions

View file

@ -11,6 +11,8 @@
#include <mcl/assert.hpp> #include <mcl/assert.hpp>
#include <mcl/stdint.hpp> #include <mcl/stdint.hpp>
#include "dynarmic/backend/arm64/abi.h"
namespace Dynarmic::Backend::Arm64 { namespace Dynarmic::Backend::Arm64 {
using namespace oaknut::util; using namespace oaknut::util;
@ -232,7 +234,7 @@ int RegAlloc::RealizeWriteImpl(const IR::Inst* value) {
fprs[new_location_index].SetupLocation(value); fprs[new_location_index].SetupLocation(value);
return new_location_index; return new_location_index;
} else if constexpr (kind == HostLoc::Kind::Flags) { } else if constexpr (kind == HostLoc::Kind::Flags) {
ASSERT(flags.values.empty()); SpillFlags();
flags.SetupLocation(value); flags.SetupLocation(value);
return 0; return 0;
} else { } else {
@ -287,6 +289,31 @@ void RegAlloc::SpillFpr(int index) {
spills[new_location_index] = std::exchange(fprs[index], {}); spills[new_location_index] = std::exchange(fprs[index], {});
} }
void RegAlloc::ReadWriteFlags(Argument& read, IR::Inst* write) {
const auto current_location = ValueLocation(read.value.GetInst());
ASSERT(current_location);
if (current_location->kind == HostLoc::Kind::Flags) {
if (!flags.IsOneRemainingUse()) {
SpillFlags();
}
} else if (current_location->kind == HostLoc::Kind::Gpr) {
if (!flags.values.empty()) {
SpillFlags();
}
code.MSR(static_cast<oaknut::SystemReg>(0b11'011'0100'0010'000), oaknut::XReg{current_location->index});
} else if (current_location->kind == HostLoc::Kind::Spill) {
if (!flags.values.empty()) {
SpillFlags();
}
code.LDR(Wscratch0, SP, spill_offset + current_location->index * spill_slot_size);
code.MSR(static_cast<oaknut::SystemReg>(0b11'011'0100'0010'000), Xscratch0);
} else {
ASSERT_FALSE("Invalid current location for flags");
}
flags.SetupLocation(write);
}
void RegAlloc::SpillFlags() { void RegAlloc::SpillFlags() {
ASSERT(!flags.locked && !flags.realized); ASSERT(!flags.locked && !flags.realized);
if (flags.values.empty()) { if (flags.values.empty()) {

View file

@ -219,6 +219,7 @@ public:
void DefineAsExisting(IR::Inst* inst, Argument& arg); void DefineAsExisting(IR::Inst* inst, Argument& arg);
void ReadWriteFlags(Argument& read, IR::Inst* write);
void SpillFlags(); void SpillFlags();
void SpillAll(); void SpillAll();