arm64/abi: Deduplicate register code

This commit is contained in:
Merry 2022-07-24 11:56:25 +01:00 committed by merry
parent f3bf27c816
commit 77634509b5

View file

@ -55,26 +55,22 @@ static FrameInfo CalculateFrameInfo(RegisterList rl, size_t frame_size) {
};
}
#define DO_IT(TYPE, REG_TYPE, PAIR_OP, SINGLE_OP, OFFSET) \
for (size_t i = 0; i < frame_info.TYPE##s.size() - 1; i += 2) { \
code.PAIR_OP(oaknut::REG_TYPE{frame_info.TYPE##s[i]}, oaknut::REG_TYPE{frame_info.TYPE##s[i + 1]}, SP, (OFFSET) + i * TYPE##_size); \
} \
if (frame_info.TYPE##s.size() % 2 == 1) { \
const size_t i = frame_info.TYPE##s.size() - 1; \
code.SINGLE_OP(oaknut::REG_TYPE{frame_info.TYPE##s[i]}, SP, (OFFSET) + i * TYPE##_size); \
}
void ABI_PushRegisters(oaknut::CodeGenerator& code, RegisterList rl, size_t frame_size) {
const FrameInfo frame_info = CalculateFrameInfo(rl, frame_size);
code.SUB(SP, SP, frame_info.gprs_size + frame_info.fprs_size);
for (size_t i = 0; i < frame_info.gprs.size() - 1; i += 2) {
code.STP(oaknut::XReg{frame_info.gprs[i]}, oaknut::XReg{frame_info.gprs[i + 1]}, SP, i * gpr_size);
}
if (frame_info.gprs.size() % 2 == 1) {
const size_t i = frame_info.gprs.size() - 1;
code.STR(oaknut::XReg{frame_info.gprs[i]}, SP, i * gpr_size);
}
for (size_t i = 0; i < frame_info.fprs.size() - 1; i += 2) {
code.STP(oaknut::QReg{frame_info.fprs[i]}, oaknut::QReg{frame_info.fprs[i + 1]}, SP, frame_info.gprs_size + i * fpr_size);
}
if (frame_info.fprs.size() % 2 == 1) {
const size_t i = frame_info.fprs.size() - 1;
code.STR(oaknut::QReg{frame_info.fprs[i]}, SP, frame_info.gprs_size + i * fpr_size);
}
DO_IT(gpr, XReg, STP, STR, 0)
DO_IT(fpr, QReg, STP, STR, frame_info.gprs_size)
code.SUB(SP, SP, frame_info.frame_size);
}
@ -84,21 +80,8 @@ void ABI_PopRegisters(oaknut::CodeGenerator& code, RegisterList rl, size_t frame
code.ADD(SP, SP, frame_info.frame_size);
for (size_t i = 0; i < frame_info.gprs.size() - 1; i += 2) {
code.LDP(oaknut::XReg{frame_info.gprs[i]}, oaknut::XReg{frame_info.gprs[i + 1]}, SP, i * gpr_size);
}
if (frame_info.gprs.size() % 2 == 1) {
const size_t i = frame_info.gprs.size() - 1;
code.LDR(oaknut::XReg{frame_info.gprs[i]}, SP, i * gpr_size);
}
for (size_t i = 0; i < frame_info.fprs.size() - 1; i += 2) {
code.LDP(oaknut::QReg{frame_info.fprs[i]}, oaknut::QReg{frame_info.fprs[i + 1]}, SP, frame_info.gprs_size + i * fpr_size);
}
if (frame_info.fprs.size() % 2 == 1) {
const size_t i = frame_info.fprs.size() - 1;
code.LDR(oaknut::QReg{frame_info.fprs[i]}, SP, frame_info.gprs_size + i * fpr_size);
}
DO_IT(gpr, XReg, LDP, LDR, 0)
DO_IT(fpr, QReg, LDP, LDR, frame_info.gprs_size)
code.ADD(SP, SP, frame_info.gprs_size + frame_info.fprs_size);
}