emit_arm64_data_processing: Fix flag reading in AddSub
Also improve codegen for ZR case.
This commit is contained in:
parent
aaa0773695
commit
ff34f4c6ae
3 changed files with 24 additions and 11 deletions
|
@ -757,10 +757,20 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
|
|||
} else {
|
||||
MaybeAddSubImm<bitsize>(code, sub ? ~imm : imm, [&](const auto b) { code.ADD(Rresult, *Ra, b); });
|
||||
}
|
||||
} else {
|
||||
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
|
||||
|
||||
if (imm == 0) {
|
||||
if constexpr (bitsize == 32) {
|
||||
sub ? code.SBC(Rresult, Ra, WZR) : code.ADC(Rresult, Ra, WZR);
|
||||
} else {
|
||||
sub ? code.SBC(Rresult, Ra, XZR) : code.ADC(Rresult, Ra, XZR);
|
||||
}
|
||||
} else {
|
||||
code.MOV(Rscratch0<bitsize>(), imm);
|
||||
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]);
|
||||
|
||||
|
@ -783,6 +793,8 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
|
||||
|
||||
sub ? code.SBC(Rresult, Ra, Rb) : code.ADC(Rresult, Ra, Rb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
|||
// ASSERT size fits
|
||||
break;
|
||||
case HostLoc::Kind::Spill:
|
||||
code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size);
|
||||
code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size);
|
||||
break;
|
||||
case HostLoc::Kind::Flags:
|
||||
code.MRS(oaknut::XReg{new_location_index}, oaknut::SystemReg::NZCV);
|
||||
|
@ -296,7 +296,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
|||
ASSERT_FALSE("Logic error");
|
||||
break;
|
||||
case HostLoc::Kind::Spill:
|
||||
code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size);
|
||||
code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size);
|
||||
break;
|
||||
case HostLoc::Kind::Flags:
|
||||
ASSERT_FALSE("Moving from flags into fprs is not currently supported");
|
||||
|
@ -307,7 +307,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
|||
fprs[new_location_index].realized = true;
|
||||
return new_location_index;
|
||||
} else if constexpr (required_kind == HostLoc::Kind::Flags) {
|
||||
ASSERT_FALSE("Loading flags back into NZCV is not currently supported");
|
||||
ASSERT_FALSE("A simple read from flags is likely a logic error.");
|
||||
} else {
|
||||
static_assert(required_kind == HostLoc::Kind::Fpr || required_kind == HostLoc::Kind::Gpr || required_kind == HostLoc::Kind::Flags);
|
||||
}
|
||||
|
@ -399,9 +399,12 @@ void RegAlloc::ReadWriteFlags(Argument& read, IR::Inst* write) {
|
|||
} else {
|
||||
ASSERT_FALSE("Invalid current location for flags");
|
||||
}
|
||||
|
||||
if (write) {
|
||||
flags.SetupLocation(write);
|
||||
flags.locked--;
|
||||
flags.realized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RegAlloc::SpillFlags() {
|
||||
|
|
|
@ -153,8 +153,6 @@ public:
|
|||
auto ReadH(Argument& arg) { return RAReg<oaknut::HReg>{*this, false, arg.value}; }
|
||||
auto ReadB(Argument& arg) { return RAReg<oaknut::BReg>{*this, false, arg.value}; }
|
||||
|
||||
auto ReadFlags(Argument& arg) { return RAReg<FlagsTag>{*this, false, arg.value}; }
|
||||
|
||||
template<size_t size>
|
||||
auto ReadReg(Argument& arg) {
|
||||
if constexpr (size == 64) {
|
||||
|
@ -300,7 +298,7 @@ RAReg<T>::~RAReg() {
|
|||
HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst());
|
||||
info.locked--;
|
||||
if (reg) {
|
||||
info.realized = false;
|
||||
reg_alloc.ValueInfo(HostLoc{kind, reg->index()}).realized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue