    module GHC.CmmToAsm.AArch64.Cond  where

    import GHC.Prelude hiding (EQ)

    -- https://developer.arm.com/documentation/den0024/a/the-a64-instruction-set/data-processing-instructions/conditional-instructions

    -- TODO: This appears to go a bit overboard? Maybe we should stick with what LLVM
    -- settled on for fcmp?
    -- false: always yields false, regardless of operands.
    -- oeq: yields true if both operands are not a QNAN and op1 is equal to op2.
    -- ogt: yields true if both operands are not a QNAN and op1 is greater than op2.
    -- oge: yields true if both operands are not a QNAN and op1 is greater than or equal to op2.
    -- olt: yields true if both operands are not a QNAN and op1 is less than op2.
    -- ole: yields true if both operands are not a QNAN and op1 is less than or equal to op2.
    -- one: yields true if both operands are not a QNAN and op1 is not equal to op2.
    -- ord: yields true if both operands are not a QNAN.
    -- ueq: yields true if either operand is a QNAN or op1 is equal to op2.
    -- ugt: yields true if either operand is a QNAN or op1 is greater than op2.
    -- uge: yields true if either operand is a QNAN or op1 is greater than or equal to op2.
    -- ult: yields true if either operand is a QNAN or op1 is less than op2.
    -- ule: yields true if either operand is a QNAN or op1 is less than or equal to op2.
    -- une: yields true if either operand is a QNAN or op1 is not equal to op2.
    -- uno: yields true if either operand is a QNAN.
    -- true: always yields true, regardless of operands.
    --
    -- LLVMs icmp knows about:
    -- eq: yields true if the operands are equal, false otherwise. No sign interpretation is necessary or performed.
    -- ne: yields true if the operands are unequal, false otherwise. No sign interpretation is necessary or performed.
    -- ugt: interprets the operands as unsigned values and yields true if op1 is greater than op2.
    -- uge: interprets the operands as unsigned values and yields true if op1 is greater than or equal to op2.
    -- ult: interprets the operands as unsigned values and yields true if op1 is less than op2.
    -- ule: interprets the operands as unsigned values and yields true if op1 is less than or equal to op2.
    -- sgt: interprets the operands as signed values and yields true if op1 is greater than op2.
    -- sge: interprets the operands as signed values and yields true if op1 is greater than or equal to op2.
    -- slt: interprets the operands as signed values and yields true if op1 is less than op2.
    -- sle: interprets the operands as signed values and yields true if op1 is less than or equal to op2.

    data Cond
        = ALWAYS -- b.al
        | EQ     -- b.eq
        | NE     -- b.ne
        -- signed
        | SLT    -- b.lt
        | SLE    -- b.le
        | SGE    -- b.ge
        | SGT    -- b.gt
        -- unsigned
        | ULT    -- b.lo
        | ULE    -- b.ls
        | UGE    -- b.hs
        | UGT    -- b.hi
        -- ordered
        | OLT    -- b.mi
        | OLE    -- b.ls
        | OGE    -- b.ge
        | OGT    -- b.gt
        -- unordered
        | UOLT   -- b.lt
        | UOLE   -- b.le
        | UOGE   -- b.pl
        | UOGT   -- b.hi
        -- others
        -- NEVER -- b.nv
                 -- I removed never. According to the ARM spec:
                 -- >   The Condition code NV exists only to provide a valid disassembly of
                 -- >   the 0b1111 encoding, otherwise its behavior is identical to AL.
                 -- This can only lead to disaster. Better to not have it than someone
                 -- using it assuming it actually means never.

        | VS     -- oVerflow set
        | VC     -- oVerflow clear
        deriving Cond -> Cond -> Bool
    (Cond -> Cond -> Bool) -> (Cond -> Cond -> Bool) -> Eq Cond
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Cond -> Cond -> Bool
    == :: Cond -> Cond -> Bool
    $c/= :: Cond -> Cond -> Bool
    /= :: Cond -> Cond -> Bool
    Eq