{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Asm.Ar ( Arch (..) ) where

import qualified Asm.Aarch64    as AArch64
import qualified Asm.Aarch64.B  as AArch64
import qualified Asm.Aarch64.CF as AArch64
import           Asm.BB
import qualified Asm.X86        as X86
import qualified Asm.X86.B      as X86
import qualified Asm.X86.CF     as X86
import           CF
import           Class.E

class Arch arch reg freg f2reg where
    cf :: [BB arch reg freg f2reg () ()] -> [BB arch reg freg f2reg () ControlAnn]

    -- | result: src, dest
    mI :: arch reg freg f2reg a -> Maybe (reg, reg)
    mf :: arch reg freg f2reg a -> Maybe (freg, freg)

    bb :: [arch reg freg f2reg a] -> [BB arch reg freg f2reg a ()]
    expand :: BB arch reg freg f2reg () Liveness -> [arch reg freg f2reg Liveness]
    udd :: arch reg freg f2reg a -> UD

instance (E reg, E freg) => Arch X86.X86 reg freg f2reg where
    cf :: [BB X86 reg freg f2reg () ()]
-> [BB X86 reg freg f2reg () ControlAnn]
cf = [BB X86 reg freg f2reg () ()]
-> [BB X86 reg freg f2reg () ControlAnn]
forall reg freg f2reg.
(E reg, E freg) =>
[BB X86 reg freg f2reg () ()]
-> [BB X86 reg freg f2reg () ControlAnn]
X86.mkControlFlow

    mI :: forall a. X86 reg freg f2reg a -> Maybe (reg, reg)
mI (X86.MovRR a
_ reg
r0 reg
r1) = (reg, reg) -> Maybe (reg, reg)
forall a. a -> Maybe a
Just (reg
r1, reg
r0)
    mI X86 reg freg f2reg a
_                   = Maybe (reg, reg)
forall a. Maybe a
Nothing

    mf :: forall a. X86 reg freg f2reg a -> Maybe (freg, freg)
mf (X86.Movapd a
_ freg
r0 freg
r1) = (freg, freg) -> Maybe (freg, freg)
forall a. a -> Maybe a
Just (freg
r1, freg
r0)
    mf X86 reg freg f2reg a
_                    = Maybe (freg, freg)
forall a. Maybe a
Nothing

    bb :: forall a. [X86 reg freg f2reg a] -> [BB X86 reg freg f2reg a ()]
bb = [X86 reg freg f2reg a] -> [BB X86 reg freg f2reg a ()]
forall reg freg f2reg a.
[X86 reg freg f2reg a] -> [BB X86 reg freg f2reg a ()]
X86.bb
    expand :: BB X86 reg freg f2reg () Liveness -> [X86 reg freg f2reg Liveness]
expand = BB X86 reg freg f2reg () Liveness -> [X86 reg freg f2reg Liveness]
forall reg freg f2reg.
(E reg, E freg) =>
BB X86 reg freg f2reg () Liveness -> [X86 reg freg f2reg Liveness]
X86.expand
    udd :: forall a. X86 reg freg f2reg a -> UD
udd = X86 reg freg f2reg a -> UD
forall {reg} {freg} {f2reg} {ann}.
(E reg, E freg) =>
X86 reg freg f2reg ann -> UD
X86.udd

instance (E reg, E freg, E f2reg) => Arch AArch64.AArch64 reg freg f2reg where
    cf :: [BB AArch64 reg freg f2reg () ()]
-> [BB AArch64 reg freg f2reg () ControlAnn]
cf = [BB AArch64 reg freg f2reg () ()]
-> [BB AArch64 reg freg f2reg () ControlAnn]
forall reg freg f2reg.
(E reg, E freg, E f2reg) =>
[BB AArch64 reg freg f2reg () ()]
-> [BB AArch64 reg freg f2reg () ControlAnn]
AArch64.mkControlFlow

    mI :: forall a. AArch64 reg freg f2reg a -> Maybe (reg, reg)
mI (AArch64.MovRR a
_ reg
r0 reg
r1) = (reg, reg) -> Maybe (reg, reg)
forall a. a -> Maybe a
Just (reg
r0, reg
r1)
    mI AArch64 reg freg f2reg a
_                       = Maybe (reg, reg)
forall a. Maybe a
Nothing

    mf :: forall a. AArch64 reg freg f2reg a -> Maybe (freg, freg)
mf (AArch64.FMovXX a
_ freg
r0 freg
r1) = (freg, freg) -> Maybe (freg, freg)
forall a. a -> Maybe a
Just (freg
r0, freg
r1)
    mf AArch64 reg freg f2reg a
_                        = Maybe (freg, freg)
forall a. Maybe a
Nothing

    bb :: forall a.
[AArch64 reg freg f2reg a] -> [BB AArch64 reg freg f2reg a ()]
bb = [AArch64 reg freg f2reg a] -> [BB AArch64 reg freg f2reg a ()]
forall reg freg f2reg a.
[AArch64 reg freg f2reg a] -> [BB AArch64 reg freg f2reg a ()]
AArch64.bb
    expand :: BB AArch64 reg freg f2reg () Liveness
-> [AArch64 reg freg f2reg Liveness]
expand = BB AArch64 reg freg f2reg () Liveness
-> [AArch64 reg freg f2reg Liveness]
forall reg freg f2reg.
(E reg, E freg, E f2reg) =>
BB AArch64 reg freg f2reg () Liveness
-> [AArch64 reg freg f2reg Liveness]
AArch64.expand
    udd :: forall a. AArch64 reg freg f2reg a -> UD
udd = AArch64 reg freg f2reg a -> UD
forall {reg} {freg} {f2reg} {ann}.
(E reg, E freg, E f2reg) =>
AArch64 reg freg f2reg ann -> UD
AArch64.udd