[a64] Reorganize guest register allocation

Share a somewhat similar calling convention as ARM64
This commit is contained in:
Wunkolo 2024-05-06 22:37:37 -07:00
parent 0f9769baac
commit 49f9edbfab
3 changed files with 27 additions and 17 deletions

View File

@ -49,8 +49,17 @@ class A64ThunkEmitter : public A64Emitter {
// The following four functions provide save/load functionality for registers.
// They assume at least StackLayout::THUNK_STACK_SIZE bytes have been
// allocated on the stack.
// Caller saved:
// Dont assume these registers will survive a subroutine call
// x0, v0 is not saved/preserved since this is used to return values from
// subroutines x1-x15, x30 | d0-d7 and d16-v31
void EmitSaveVolatileRegs();
void EmitLoadVolatileRegs();
// Callee saved:
// Subroutines must preserve these registers if they intend to use them
// x19-x30 | d8-d15
void EmitSaveNonvolatileRegs();
void EmitLoadNonvolatileRegs();
};
@ -78,7 +87,7 @@ bool A64Backend::Initialize(Processor* processor) {
std::strcpy(fprs.name, "v");
fprs.types = MachineInfo::RegisterSet::FLOAT_TYPES |
MachineInfo::RegisterSet::VEC_TYPES;
fprs.count = A64Emitter::XMM_COUNT;
fprs.count = A64Emitter::FPR_COUNT;
code_cache_ = A64CodeCache::Create();
Backend::code_cache_ = code_cache_.get();

View File

@ -62,12 +62,13 @@ static const size_t kMaxCodeSize = 1_MiB;
static const size_t kStashOffset = 32;
// static const size_t kStashOffsetHigh = 32 + 32;
const uint32_t A64Emitter::gpr_reg_map_[A64Emitter::GPR_COUNT] = {
1, 10, 11, 12, 13, 14, 15,
// Register indices that the HIR is allowed to use for operands
const uint8_t A64Emitter::gpr_reg_map_[A64Emitter::GPR_COUNT] = {
19, 20, 21, 22, 23, 24, 25, 26,
};
const uint32_t A64Emitter::xmm_reg_map_[A64Emitter::XMM_COUNT] = {
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
const uint8_t A64Emitter::fpr_reg_map_[A64Emitter::FPR_COUNT] = {
8, 9, 10, 11, 12, 13, 14, 15,
};
A64Emitter::A64Emitter(A64Backend* backend)
@ -665,8 +666,8 @@ oaknut::XReg A64Emitter::GetNativeParam(uint32_t param) {
}
// Important: If you change these, you must update the thunks in a64_backend.cc!
oaknut::XReg A64Emitter::GetContextReg() { return X19; }
oaknut::XReg A64Emitter::GetMembaseReg() { return X20; }
oaknut::XReg A64Emitter::GetContextReg() { return X27; }
oaknut::XReg A64Emitter::GetMembaseReg() { return X28; }
void A64Emitter::ReloadContext() {
// mov(GetContextReg(), qword[rsp + StackLayout::GUEST_CTX_HOME]);

View File

@ -137,13 +137,13 @@ class A64Emitter : public oaknut::CodeBlock, public oaknut::CodeGenerator {
std::vector<SourceMapEntry>* out_source_map);
public:
// Reserved: XSP, X19, X20
// Scratch: X0/X1/X2
// Reserved: XSP, X27, X28
// Scratch: X1-X15, X30 | V0-v7 and V16-V31
// V0-2
// Available: X1, X10-r15
// Available: X19-X26
// V4-V15 (save to get V3)
static const int GPR_COUNT = 7;
static const int XMM_COUNT = 12;
static const size_t GPR_COUNT = 8;
static const size_t FPR_COUNT = 8;
static void SetupReg(const hir::Value* v, oaknut::WReg& r) {
const auto idx = gpr_reg_map_[v->reg.index];
@ -154,15 +154,15 @@ class A64Emitter : public oaknut::CodeBlock, public oaknut::CodeGenerator {
r = oaknut::XReg(idx);
}
static void SetupReg(const hir::Value* v, oaknut::SReg& r) {
const auto idx = xmm_reg_map_[v->reg.index];
const auto idx = fpr_reg_map_[v->reg.index];
r = oaknut::SReg(idx);
}
static void SetupReg(const hir::Value* v, oaknut::DReg& r) {
const auto idx = xmm_reg_map_[v->reg.index];
const auto idx = fpr_reg_map_[v->reg.index];
r = oaknut::DReg(idx);
}
static void SetupReg(const hir::Value* v, oaknut::QReg& r) {
const auto idx = xmm_reg_map_[v->reg.index];
const auto idx = fpr_reg_map_[v->reg.index];
r = oaknut::QReg(idx);
}
@ -247,8 +247,8 @@ class A64Emitter : public oaknut::CodeBlock, public oaknut::CodeGenerator {
size_t stack_size_ = 0;
static const uint32_t gpr_reg_map_[GPR_COUNT];
static const uint32_t xmm_reg_map_[XMM_COUNT];
static const uint8_t gpr_reg_map_[GPR_COUNT];
static const uint8_t fpr_reg_map_[FPR_COUNT];
};
} // namespace a64