backend/arm64/reg_alloc: More flag handling
This commit is contained in:
parent
21601764de
commit
78bc0812b9
2 changed files with 29 additions and 1 deletions
|
@ -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()) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue