    module GHC.CmmToAsm.X86.Cond (
            Cond(..),
            condToUnsigned,
            maybeFlipCond,
            maybeInvertCond
    )

    where

    import GHC.Prelude

    data Cond
            = ALWAYS        -- What's really used? ToDo
            | EQQ           -- je/jz -> zf=1
            | GE            -- jge   -> sf=of
            | GEU           -- ae    -> cf=0
            | GTT           -- jg    -> zf=0 && sf=of
            | GU            -- ja    -> cf=0 && zf=0
            | LE            -- jle   -> zf=1 || sf/=of
            | LEU           -- jbe   -> cf=1 || zf=1
            | LTT           -- jl    -> sf/=of
            | LU            -- jb    -> cf=1
            | NE            -- jne   -> zf=0
            | NEG           -- js    -> sf=1
            | POS           -- jns   -> sf=0
            | CARRY         -- jc    -> cf=1
            | OFLO          -- jo    -> of=1
            | PARITY        -- jp    -> pf=1
            | NOTPARITY     -- jnp   -> pf=0
            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

    condToUnsigned :: Cond -> Cond
    condToUnsigned :: Cond -> Cond
    condToUnsigned Cond
    GTT = Cond
    GU
    condToUnsigned Cond
    LTT = Cond
    LU
    condToUnsigned Cond
    GE  = Cond
    GEU
    condToUnsigned Cond
    LE  = Cond
    LEU
    condToUnsigned Cond
    x   = Cond
    x

    -- | @maybeFlipCond c@ returns @Just c'@ if it is possible to flip the
    -- arguments to the conditional @c@, and the new condition should be @c'@.
    maybeFlipCond :: Cond -> Maybe Cond
    maybeFlipCond :: Cond -> Maybe Cond
    maybeFlipCond Cond
    cond  = case Cond
    cond of
            Cond
    EQQ   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    EQQ
            Cond
    NE    -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    NE
            Cond
    LU    -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GU
            Cond
    GU    -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LU
            Cond
    LEU   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GEU
            Cond
    GEU   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LEU
            Cond
    LTT   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GTT
            Cond
    GTT   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LTT
            Cond
    LE    -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GE
            Cond
    GE    -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LE
            Cond
    _other -> Maybe Cond
    forall a. Maybe a
    Nothing

    -- | If we apply @maybeInvertCond@ to the condition of a jump we turn
    -- jumps taken into jumps not taken and vice versa.
    --
    -- Careful! If the used comparison and the conditional jump
    -- don't match the above behaviour will NOT hold.
    -- When used for FP comparisons this does not consider unordered
    -- numbers.
    -- Also inverting twice might return a synonym for the original condition.
    maybeInvertCond :: Cond -> Maybe Cond
    maybeInvertCond :: Cond -> Maybe Cond
    maybeInvertCond Cond
    cond  = case Cond
    cond of
            Cond
    ALWAYS  -> Maybe Cond
    forall a. Maybe a
    Nothing
            Cond
    EQQ     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    NE
            Cond
    NE      -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    EQQ

            Cond
    NEG     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    POS
            Cond
    POS     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    NEG

            Cond
    GEU     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LU
            Cond
    LU      -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GEU

            Cond
    GE      -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LTT
            Cond
    LTT     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GE

            Cond
    GTT     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LE
            Cond
    LE      -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GTT

            Cond
    GU      -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    LEU
            Cond
    LEU     -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GU

            --GEU "==" NOTCARRY, they are synonyms
            --at the assembly level
            Cond
    CARRY   -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    GEU

            Cond
    OFLO    -> Maybe Cond
    forall a. Maybe a
    Nothing

            Cond
    PARITY  -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    NOTPARITY
            Cond
    NOTPARITY -> Cond -> Maybe Cond
    forall a. a -> Maybe a
    Just Cond
    PARITY