diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 83ab114e..5b9c8b7a 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -443,6 +443,10 @@ void EmitX64::EmitGetOverflowFromOp(IR::Block&, IR::Inst*) { ASSERT_MSG(false, "should never happen"); } +void EmitX64::EmitGetGEFromOp(IR::Block&, IR::Inst*) { + ASSERT_MSG(false, "should never happen"); +} + void EmitX64::EmitPack2x32To1x64(IR::Block&, IR::Inst* inst) { OpArg lo; Xbyak::Reg64 result; diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 95ea1260..25cc83e1 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -232,9 +232,14 @@ Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) { // This is faster than doing a search through the block. switch (opcode) { case IR::Opcode::GetCarryFromOp: + DEBUG_ASSERT(!carry_inst || carry_inst->GetOpcode() == Opcode::GetCarryFromOp); return carry_inst; case IR::Opcode::GetOverflowFromOp: + DEBUG_ASSERT(!overflow_inst || overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp); return overflow_inst; + case IR::Opcode::GetGEFromOp: + DEBUG_ASSERT(!ge_inst || ge_inst->GetOpcode() == Opcode::GetGEFromOp); + return ge_inst; default: break; } @@ -302,6 +307,10 @@ void Inst::Use(Value& value) { ASSERT_MSG(!value.GetInst()->overflow_inst, "Only one of each type of pseudo-op allowed"); value.GetInst()->overflow_inst = this; break; + case Opcode::GetGEFromOp: + ASSERT_MSG(!value.GetInst()->ge_inst, "Only one of each type of pseudo-op allowed"); + value.GetInst()->ge_inst = this; + break; default: break; } @@ -312,11 +321,17 @@ void Inst::UndoUse(Value& value) { switch (op){ case Opcode::GetCarryFromOp: + DEBUG_ASSERT(value.GetInst()->carry_inst->GetOpcode() == Opcode::GetCarryFromOp); value.GetInst()->carry_inst = nullptr; break; case Opcode::GetOverflowFromOp: + DEBUG_ASSERT(value.GetInst()->overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp); value.GetInst()->overflow_inst = nullptr; break; + case Opcode::GetGEFromOp: + DEBUG_ASSERT(value.GetInst()->ge_inst->GetOpcode() == Opcode::GetGEFromOp); + value.GetInst()->ge_inst = nullptr; + break; default: break; } diff --git a/src/frontend/ir/microinstruction.h b/src/frontend/ir/microinstruction.h index c9634a20..1f569a6a 100644 --- a/src/frontend/ir/microinstruction.h +++ b/src/frontend/ir/microinstruction.h @@ -102,7 +102,12 @@ private: size_t use_count = 0; std::array args; - Inst* carry_inst = nullptr; + // Pointers to related pseudooperations: + // Since not all combinations are possible, we use a union to save space + union { + Inst* carry_inst = nullptr; + Inst* ge_inst; + }; Inst* overflow_inst = nullptr; }; diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 1d0eace1..4d742aa4 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -36,6 +36,7 @@ OPCODE(PushRSB, T::Void, T::U64 // Pseudo-operation, handled specially at final emit OPCODE(GetCarryFromOp, T::U1, T::U32 ) OPCODE(GetOverflowFromOp, T::U1, T::U32 ) +OPCODE(GetGEFromOp, T::U32, T::U32 ) // Calculations OPCODE(Pack2x32To1x64, T::U64, T::U32, T::U32 )