IR: add SubWithFlags op (arm64 subs)

with 8/16-bit handling to keep everything uniform.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig committed 2024-02-24 15:54:49 -04:00
1 parent f7e32373ce
commit 22ab7f2b3e
4 files changed
+32 -1

No files matched your search

@@ -200,6 +200,21 @@ DEF_OP(SubShift) {
sub(EmitSize, GetReg(Node), GetReg(Op->Src1.ID()), GetReg(Op->Src2.ID()), ConvertIRShiftType(Op->Shift), Op->ShiftAmount);
}
DEF_OP(SubWithFlags) {
auto Op = IROp->C<IR::IROp_SubWithFlags>();
const uint8_t OpSize = IROp->Size;
LOGMAN_THROW_AA_FMT(OpSize == 4 || OpSize == 8, "Unsupported {} size: {}", __func__, OpSize);
const auto EmitSize = OpSize == IR::i64Bit ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
uint64_t Const;
if (IsInlineConstant(Op->Src2, &Const)) {
subs(EmitSize, GetReg(Node), GetZeroableReg(Op->Src1), Const);
} else {
subs(EmitSize, GetReg(Node), GetZeroableReg(Op->Src1), GetReg(Op->Src2.ID()));
}
}
DEF_OP(SubNZCV) {
auto Op = IROp->C<IR::IROp_SubNZCV>();
const uint8_t OpSize = IROp->Size;
+8
View File
@@ -1021,6 +1021,14 @@
"_Shift != ShiftType::ROR"
]
},
"GPR = SubWithFlags OpSize:#Size, GPR:$Src1, GPR:$Src2": {
"Desc": [ "Integer Sub. Truncates and sets NZCV per SubNZCV"],
"DestSize": "Size",
"HasSideEffects": true,
"EmitValidation": [
"Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit"
]
},
"SubNZCV OpSize:#Size, GPR:$Src1, GPR:$Src2": {
"Desc": ["Set NZCV for the difference of two GPRs. ",
"Carry flag uses arm64 definition, inverted x86.",
@@ -965,6 +965,7 @@ bool ConstProp::ConstantInlining(IREmitter *IREmit, const IRListView& CurrentIR)
case OP_SUB:
case OP_ADDNZCV:
case OP_SUBNZCV:
case OP_SUBWITHFLAGS:
{
auto Op = IROp->C<IR::IROp_Add>();
@@ -979,7 +980,7 @@ bool ConstProp::ConstantInlining(IREmitter *IREmit, const IRListView& CurrentIR)
Changed = true;
}
} else if (IROp->Op == OP_SUBNZCV) {
} else if (IROp->Op == OP_SUBNZCV || IROp->Op == OP_SUBWITHFLAGS) {
// If the first source is zero, we can use a NEGS instruction.
uint64_t Constant1{};
if (IREmit->IsValueConstant(Op->Header.Args[0], &Constant1)) {
@@ -128,6 +128,13 @@ DeadFlagCalculationEliminination::Classify(IROp_Header *IROp)
.Replacement = OP_AND,
};
case OP_SUBWITHFLAGS:
return {
.Write = FLAG_NZCV,
.CanReplace = true,
.Replacement = OP_SUB,
};
case OP_ADDNZCV:
case OP_SUBNZCV:
case OP_TESTNZ: