diff options
Diffstat (limited to 'src/shader_recompiler/frontend/ir/ir_emitter.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 80 |
1 files changed, 53 insertions, 27 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 33819dd36..5d475207e 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -697,93 +697,107 @@ F16F32F64 IREmitter::FPTrunc(const F16F32F64& value, FpControl control) { | |||
| 697 | } | 697 | } |
| 698 | } | 698 | } |
| 699 | 699 | ||
| 700 | U1 IREmitter::FPEqual(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 700 | U1 IREmitter::FPEqual(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, bool ordered) { |
| 701 | if (lhs.Type() != rhs.Type()) { | 701 | if (lhs.Type() != rhs.Type()) { |
| 702 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 702 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 703 | } | 703 | } |
| 704 | switch (lhs.Type()) { | 704 | switch (lhs.Type()) { |
| 705 | case Type::F16: | 705 | case Type::F16: |
| 706 | return Inst<U1>(ordered ? Opcode::FPOrdEqual16 : Opcode::FPUnordEqual16, lhs, rhs); | 706 | return Inst<U1>(ordered ? Opcode::FPOrdEqual16 : Opcode::FPUnordEqual16, Flags{control}, |
| 707 | lhs, rhs); | ||
| 707 | case Type::F32: | 708 | case Type::F32: |
| 708 | return Inst<U1>(ordered ? Opcode::FPOrdEqual32 : Opcode::FPUnordEqual32, lhs, rhs); | 709 | return Inst<U1>(ordered ? Opcode::FPOrdEqual32 : Opcode::FPUnordEqual32, Flags{control}, |
| 710 | lhs, rhs); | ||
| 709 | case Type::F64: | 711 | case Type::F64: |
| 710 | return Inst<U1>(ordered ? Opcode::FPOrdEqual64 : Opcode::FPUnordEqual64, lhs, rhs); | 712 | return Inst<U1>(ordered ? Opcode::FPOrdEqual64 : Opcode::FPUnordEqual64, Flags{control}, |
| 713 | lhs, rhs); | ||
| 711 | default: | 714 | default: |
| 712 | ThrowInvalidType(lhs.Type()); | 715 | ThrowInvalidType(lhs.Type()); |
| 713 | } | 716 | } |
| 714 | } | 717 | } |
| 715 | 718 | ||
| 716 | U1 IREmitter::FPNotEqual(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 719 | U1 IREmitter::FPNotEqual(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, |
| 720 | bool ordered) { | ||
| 717 | if (lhs.Type() != rhs.Type()) { | 721 | if (lhs.Type() != rhs.Type()) { |
| 718 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 722 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 719 | } | 723 | } |
| 720 | switch (lhs.Type()) { | 724 | switch (lhs.Type()) { |
| 721 | case Type::F16: | 725 | case Type::F16: |
| 722 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual16 : Opcode::FPUnordNotEqual16, lhs, rhs); | 726 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual16 : Opcode::FPUnordNotEqual16, |
| 727 | Flags{control}, lhs, rhs); | ||
| 723 | case Type::F32: | 728 | case Type::F32: |
| 724 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual32 : Opcode::FPUnordNotEqual32, lhs, rhs); | 729 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual32 : Opcode::FPUnordNotEqual32, |
| 730 | Flags{control}, lhs, rhs); | ||
| 725 | case Type::F64: | 731 | case Type::F64: |
| 726 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual64 : Opcode::FPUnordNotEqual64, lhs, rhs); | 732 | return Inst<U1>(ordered ? Opcode::FPOrdNotEqual64 : Opcode::FPUnordNotEqual64, |
| 733 | Flags{control}, lhs, rhs); | ||
| 727 | default: | 734 | default: |
| 728 | ThrowInvalidType(lhs.Type()); | 735 | ThrowInvalidType(lhs.Type()); |
| 729 | } | 736 | } |
| 730 | } | 737 | } |
| 731 | 738 | ||
| 732 | U1 IREmitter::FPLessThan(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 739 | U1 IREmitter::FPLessThan(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, |
| 740 | bool ordered) { | ||
| 733 | if (lhs.Type() != rhs.Type()) { | 741 | if (lhs.Type() != rhs.Type()) { |
| 734 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 742 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 735 | } | 743 | } |
| 736 | switch (lhs.Type()) { | 744 | switch (lhs.Type()) { |
| 737 | case Type::F16: | 745 | case Type::F16: |
| 738 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan16 : Opcode::FPUnordLessThan16, lhs, rhs); | 746 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan16 : Opcode::FPUnordLessThan16, |
| 747 | Flags{control}, lhs, rhs); | ||
| 739 | case Type::F32: | 748 | case Type::F32: |
| 740 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan32 : Opcode::FPUnordLessThan32, lhs, rhs); | 749 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan32 : Opcode::FPUnordLessThan32, |
| 750 | Flags{control}, lhs, rhs); | ||
| 741 | case Type::F64: | 751 | case Type::F64: |
| 742 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan64 : Opcode::FPUnordLessThan64, lhs, rhs); | 752 | return Inst<U1>(ordered ? Opcode::FPOrdLessThan64 : Opcode::FPUnordLessThan64, |
| 753 | Flags{control}, lhs, rhs); | ||
| 743 | default: | 754 | default: |
| 744 | ThrowInvalidType(lhs.Type()); | 755 | ThrowInvalidType(lhs.Type()); |
| 745 | } | 756 | } |
| 746 | } | 757 | } |
| 747 | 758 | ||
| 748 | U1 IREmitter::FPGreaterThan(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 759 | U1 IREmitter::FPGreaterThan(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, |
| 760 | bool ordered) { | ||
| 749 | if (lhs.Type() != rhs.Type()) { | 761 | if (lhs.Type() != rhs.Type()) { |
| 750 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 762 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 751 | } | 763 | } |
| 752 | switch (lhs.Type()) { | 764 | switch (lhs.Type()) { |
| 753 | case Type::F16: | 765 | case Type::F16: |
| 754 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan16 : Opcode::FPUnordGreaterThan16, lhs, | 766 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan16 : Opcode::FPUnordGreaterThan16, |
| 755 | rhs); | 767 | Flags{control}, lhs, rhs); |
| 756 | case Type::F32: | 768 | case Type::F32: |
| 757 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan32 : Opcode::FPUnordGreaterThan32, lhs, | 769 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan32 : Opcode::FPUnordGreaterThan32, |
| 758 | rhs); | 770 | Flags{control}, lhs, rhs); |
| 759 | case Type::F64: | 771 | case Type::F64: |
| 760 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan64 : Opcode::FPUnordGreaterThan64, lhs, | 772 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThan64 : Opcode::FPUnordGreaterThan64, |
| 761 | rhs); | 773 | Flags{control}, lhs, rhs); |
| 762 | default: | 774 | default: |
| 763 | ThrowInvalidType(lhs.Type()); | 775 | ThrowInvalidType(lhs.Type()); |
| 764 | } | 776 | } |
| 765 | } | 777 | } |
| 766 | 778 | ||
| 767 | U1 IREmitter::FPLessThanEqual(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 779 | U1 IREmitter::FPLessThanEqual(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, |
| 780 | bool ordered) { | ||
| 768 | if (lhs.Type() != rhs.Type()) { | 781 | if (lhs.Type() != rhs.Type()) { |
| 769 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 782 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 770 | } | 783 | } |
| 771 | switch (lhs.Type()) { | 784 | switch (lhs.Type()) { |
| 772 | case Type::F16: | 785 | case Type::F16: |
| 773 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual16 : Opcode::FPUnordLessThanEqual16, | 786 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual16 : Opcode::FPUnordLessThanEqual16, |
| 774 | lhs, rhs); | 787 | Flags{control}, lhs, rhs); |
| 775 | case Type::F32: | 788 | case Type::F32: |
| 776 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual32 : Opcode::FPUnordLessThanEqual32, | 789 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual32 : Opcode::FPUnordLessThanEqual32, |
| 777 | lhs, rhs); | 790 | Flags{control}, lhs, rhs); |
| 778 | case Type::F64: | 791 | case Type::F64: |
| 779 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual64 : Opcode::FPUnordLessThanEqual64, | 792 | return Inst<U1>(ordered ? Opcode::FPOrdLessThanEqual64 : Opcode::FPUnordLessThanEqual64, |
| 780 | lhs, rhs); | 793 | Flags{control}, lhs, rhs); |
| 781 | default: | 794 | default: |
| 782 | ThrowInvalidType(lhs.Type()); | 795 | ThrowInvalidType(lhs.Type()); |
| 783 | } | 796 | } |
| 784 | } | 797 | } |
| 785 | 798 | ||
| 786 | U1 IREmitter::FPGreaterThanEqual(const F16F32F64& lhs, const F16F32F64& rhs, bool ordered) { | 799 | U1 IREmitter::FPGreaterThanEqual(const F16F32F64& lhs, const F16F32F64& rhs, FpControl control, |
| 800 | bool ordered) { | ||
| 787 | if (lhs.Type() != rhs.Type()) { | 801 | if (lhs.Type() != rhs.Type()) { |
| 788 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); | 802 | throw InvalidArgument("Mismatching types {} and {}", lhs.Type(), rhs.Type()); |
| 789 | } | 803 | } |
| @@ -791,20 +805,32 @@ U1 IREmitter::FPGreaterThanEqual(const F16F32F64& lhs, const F16F32F64& rhs, boo | |||
| 791 | case Type::F16: | 805 | case Type::F16: |
| 792 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual16 | 806 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual16 |
| 793 | : Opcode::FPUnordGreaterThanEqual16, | 807 | : Opcode::FPUnordGreaterThanEqual16, |
| 794 | lhs, rhs); | 808 | Flags{control}, lhs, rhs); |
| 795 | case Type::F32: | 809 | case Type::F32: |
| 796 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual32 | 810 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual32 |
| 797 | : Opcode::FPUnordGreaterThanEqual32, | 811 | : Opcode::FPUnordGreaterThanEqual32, |
| 798 | lhs, rhs); | 812 | Flags{control}, lhs, rhs); |
| 799 | case Type::F64: | 813 | case Type::F64: |
| 800 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual64 | 814 | return Inst<U1>(ordered ? Opcode::FPOrdGreaterThanEqual64 |
| 801 | : Opcode::FPUnordGreaterThanEqual64, | 815 | : Opcode::FPUnordGreaterThanEqual64, |
| 802 | lhs, rhs); | 816 | Flags{control}, lhs, rhs); |
| 803 | default: | 817 | default: |
| 804 | ThrowInvalidType(lhs.Type()); | 818 | ThrowInvalidType(lhs.Type()); |
| 805 | } | 819 | } |
| 806 | } | 820 | } |
| 807 | 821 | ||
| 822 | U1 IREmitter::FPIsNan(const F32& value) { | ||
| 823 | return Inst<U1>(Opcode::FPIsNan32, value); | ||
| 824 | } | ||
| 825 | |||
| 826 | U1 IREmitter::FPOrdered(const F32& lhs, const F32& rhs) { | ||
| 827 | return LogicalAnd(LogicalNot(FPIsNan(lhs)), LogicalNot(FPIsNan(rhs))); | ||
| 828 | } | ||
| 829 | |||
| 830 | U1 IREmitter::FPUnordered(const F32& lhs, const F32& rhs) { | ||
| 831 | return LogicalOr(FPIsNan(lhs), FPIsNan(rhs)); | ||
| 832 | } | ||
| 833 | |||
| 808 | U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) { | 834 | U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) { |
| 809 | if (a.Type() != b.Type()) { | 835 | if (a.Type() != b.Type()) { |
| 810 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 836 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |