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 {
|
} else {
|
||||||
MaybeAddSubImm<bitsize>(code, sub ? ~imm : imm, [&](const auto b) { code.ADD(Rresult, *Ra, b); });
|
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 {
|
} else {
|
||||||
code.MOV(Rscratch0<bitsize>(), imm);
|
code.MOV(Rscratch0<bitsize>(), imm);
|
||||||
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
|
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]);
|
auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]);
|
||||||
|
|
||||||
|
@ -783,6 +793,8 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
|
||||||
|
|
||||||
sub ? code.SBC(Rresult, Ra, Rb) : code.ADC(Rresult, Ra, Rb);
|
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
|
// ASSERT size fits
|
||||||
break;
|
break;
|
||||||
case HostLoc::Kind::Spill:
|
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;
|
break;
|
||||||
case HostLoc::Kind::Flags:
|
case HostLoc::Kind::Flags:
|
||||||
code.MRS(oaknut::XReg{new_location_index}, oaknut::SystemReg::NZCV);
|
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");
|
ASSERT_FALSE("Logic error");
|
||||||
break;
|
break;
|
||||||
case HostLoc::Kind::Spill:
|
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;
|
break;
|
||||||
case HostLoc::Kind::Flags:
|
case HostLoc::Kind::Flags:
|
||||||
ASSERT_FALSE("Moving from flags into fprs is not currently supported");
|
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;
|
fprs[new_location_index].realized = true;
|
||||||
return new_location_index;
|
return new_location_index;
|
||||||
} else if constexpr (required_kind == HostLoc::Kind::Flags) {
|
} 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 {
|
} else {
|
||||||
static_assert(required_kind == HostLoc::Kind::Fpr || required_kind == HostLoc::Kind::Gpr || required_kind == HostLoc::Kind::Flags);
|
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 {
|
} else {
|
||||||
ASSERT_FALSE("Invalid current location for flags");
|
ASSERT_FALSE("Invalid current location for flags");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (write) {
|
||||||
flags.SetupLocation(write);
|
flags.SetupLocation(write);
|
||||||
flags.locked--;
|
flags.locked--;
|
||||||
flags.realized = false;
|
flags.realized = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::SpillFlags() {
|
void RegAlloc::SpillFlags() {
|
||||||
|
|
|
@ -153,8 +153,6 @@ public:
|
||||||
auto ReadH(Argument& arg) { return RAReg<oaknut::HReg>{*this, false, arg.value}; }
|
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 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>
|
template<size_t size>
|
||||||
auto ReadReg(Argument& arg) {
|
auto ReadReg(Argument& arg) {
|
||||||
if constexpr (size == 64) {
|
if constexpr (size == 64) {
|
||||||
|
@ -300,7 +298,7 @@ RAReg<T>::~RAReg() {
|
||||||
HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst());
|
HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst());
|
||||||
info.locked--;
|
info.locked--;
|
||||||
if (reg) {
|
if (reg) {
|
||||||
info.realized = false;
|
reg_alloc.ValueInfo(HostLoc{kind, reg->index()}).realized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue