module Asm.Aarch64.T ( irToAarch64 ) where

import           Asm.Aarch64
import           Asm.M
import           Control.Monad.State.Strict (runState)
import           Data.Bifunctor             (second)
import           Data.Bits                  (rotateR, (.&.))
import           Data.Tuple                 (swap)
import           Data.Word                  (Word16, Word64, Word8)
import           GHC.Float                  (castDoubleToWord64)
import qualified IR
import qualified Op

absReg :: IR.Temp -> AbsReg
absReg :: Temp -> AbsReg
absReg (IR.ITemp Int
i) = Int -> AbsReg
IReg Int
i; absReg (IR.ATemp Int
i) = Int -> AbsReg
IReg Int
i
absReg Temp
IR.C0 = AbsReg
CArg0; absReg Temp
IR.C1 = AbsReg
CArg1; absReg Temp
IR.C2 = AbsReg
CArg2
absReg Temp
IR.C3 = AbsReg
CArg3; absReg Temp
IR.C4 = AbsReg
CArg4; absReg Temp
IR.C5 = AbsReg
CArg5
absReg Temp
IR.CRet = AbsReg
CArg0

fabsReg :: IR.FTemp -> FAbsReg
fabsReg :: FTemp -> FAbsReg
fabsReg (IR.FTemp Int
i) = Int -> FAbsReg
FReg Int
i
fabsReg FTemp
IR.F0 = FAbsReg
FArg0; fabsReg FTemp
IR.F1 = FAbsReg
FArg1; fabsReg FTemp
IR.F2 = FAbsReg
FArg2
fabsReg FTemp
IR.F3 = FAbsReg
FArg3; fabsReg FTemp
IR.F4 = FAbsReg
FArg4; fabsReg FTemp
IR.F5 = FAbsReg
FArg5
fabsReg FTemp
IR.FRet = FAbsReg
FArg0; fabsReg FTemp
IR.FRet1 = FAbsReg
FArg1

mB :: BBin -> a -> reg -> reg -> reg -> AArch64 reg freg f2 a
mB BBin
Op.AndB = a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
AndRR
mB BBin
Op.OrB  = a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
OrRR
mB BBin
Op.XorB = a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
Eor

mIop :: IBin -> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
mIop IBin
Op.IPlus  = (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
AddRR
mIop IBin
Op.IMinus = (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
SubRR
mIop IBin
Op.ITimes = (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
MulRR
mIop IBin
Op.IDiv   = (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> reg -> reg -> reg -> AArch64 reg freg f2 a
Sdiv
mIop (Op.BI BBin
b) = (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just((a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
 -> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a))
-> (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
-> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a b. (a -> b) -> a -> b
$BBin -> a -> reg -> reg -> reg -> AArch64 reg freg f2 a
forall {a} {reg} {freg} {f2}.
BBin -> a -> reg -> reg -> reg -> AArch64 reg freg f2 a
mB BBin
b
mIop IBin
_         = Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
forall a. Maybe a
Nothing

mFop :: FBin -> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
mFop FBin
Op.FPlus  = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fadd
mFop FBin
Op.FMinus = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fsub
mFop FBin
Op.FTimes = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fmul
mFop FBin
Op.FDiv   = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fdiv
mFop FBin
Op.FMax   = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fmax
mFop FBin
Op.FMin   = (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
-> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. a -> Maybe a
Just a -> freg -> freg -> freg -> AArch64 reg freg f2 a
forall reg freg f2 a.
a -> freg -> freg -> freg -> AArch64 reg freg f2 a
Fmin
mFop FBin
_         = Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
forall a. Maybe a
Nothing

frel :: Op.FRel -> Cond
frel :: FRel -> Cond
frel FRel
Op.FGeq = Cond
Geq
frel FRel
Op.FLeq = Cond
Leq
frel FRel
Op.FGt  = Cond
Gt
frel FRel
Op.FLt  = Cond
Lt
frel FRel
Op.FEq  = Cond
Eq
frel FRel
Op.FNeq = Cond
Neq

iop :: Op.IRel -> Cond
iop :: IRel -> Cond
iop IRel
Op.IEq  = Cond
Eq
iop IRel
Op.INeq = Cond
Neq
iop IRel
Op.IGeq = Cond
Geq
iop IRel
Op.ILeq = Cond
Leq
iop IRel
Op.IGt  = Cond
Gt
iop IRel
Op.ILt  = Cond
Lt

nextR :: WM AbsReg
nextR :: WM AbsReg
nextR = Int -> AbsReg
IReg (Int -> AbsReg) -> StateT WSt Identity Int -> WM AbsReg
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT WSt Identity Int
nextI

nextV :: WM F2Abs
nextV :: WM F2Abs
nextV = Int -> F2Abs
F2Reg (Int -> F2Abs) -> StateT WSt Identity Int -> WM F2Abs
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT WSt Identity Int
nextI

nextF :: WM FAbsReg
nextF :: WM FAbsReg
nextF = Int -> FAbsReg
FReg (Int -> FAbsReg) -> StateT WSt Identity Int -> WM FAbsReg
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT WSt Identity Int
nextI

irToAarch64 :: IR.WSt -> [IR.Stmt] -> (Int, [AArch64 AbsReg FAbsReg F2Abs ()])
irToAarch64 :: WSt -> [Stmt] -> (Int, [AArch64 AbsReg FAbsReg F2Abs ()])
irToAarch64 WSt
st = ([AArch64 AbsReg FAbsReg F2Abs ()], Int)
-> (Int, [AArch64 AbsReg FAbsReg F2Abs ()])
forall a b. (a, b) -> (b, a)
swap (([AArch64 AbsReg FAbsReg F2Abs ()], Int)
 -> (Int, [AArch64 AbsReg FAbsReg F2Abs ()]))
-> ([Stmt] -> ([AArch64 AbsReg FAbsReg F2Abs ()], Int))
-> [Stmt]
-> (Int, [AArch64 AbsReg FAbsReg F2Abs ()])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (WSt -> Int)
-> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt)
-> ([AArch64 AbsReg FAbsReg F2Abs ()], Int)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second WSt -> Int
IR.wtemps (([AArch64 AbsReg FAbsReg F2Abs ()], WSt)
 -> ([AArch64 AbsReg FAbsReg F2Abs ()], Int))
-> ([Stmt] -> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt))
-> [Stmt]
-> ([AArch64 AbsReg FAbsReg F2Abs ()], Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
 -> WSt -> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt))
-> WSt
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
-> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt)
forall a b c. (a -> b -> c) -> b -> a -> c
flip State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
-> WSt -> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt)
forall s a. State s a -> s -> (a, s)
runState WSt
st (State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
 -> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt))
-> ([Stmt] -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()])
-> [Stmt]
-> ([AArch64 AbsReg FAbsReg F2Abs ()], WSt)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stmt -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()])
-> [Stmt] -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall (f :: * -> *) (t :: * -> *) m a.
(Applicative f, Traversable t, Monoid m) =>
(a -> f m) -> t a -> f m
foldMapA Stmt -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
ir

-- only needs to be "quadword aligned" when it is the base register for load/store instructions
aR :: AbsReg -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
aR :: AbsReg -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
aR AbsReg
t = do
    l <- WM Label
nextL
    -- FIXME: bool-tuples are size 9 &c.
    -- (this would crash on stack-allocated arrays of bools...)
    pure [TstI () t (BM 1 3), Bc () Eq l, AddRC () t t 8, Label () l]

plF :: IR.FExp -> WM ([AArch64 AbsReg FAbsReg F2Abs ()] -> [AArch64 AbsReg FAbsReg F2Abs ()], FAbsReg)
plF :: FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF (IR.FReg FTemp
t) = ([AArch64 AbsReg FAbsReg F2Abs ()]
 -> [AArch64 AbsReg FAbsReg F2Abs ()],
 FAbsReg)
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([AArch64 AbsReg FAbsReg F2Abs ()]
-> [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> a
id, FTemp -> FAbsReg
fabsReg FTemp
t)
plF FExp
e           = do {i <- StateT WSt Identity Int
nextI; pl <- feval e (IR.FTemp i); pure ((pl++), FReg i)}

plI :: IR.Exp -> WM ([AArch64 AbsReg FAbsReg F2Abs ()] -> [AArch64 AbsReg FAbsReg F2Abs ()], AbsReg)
plI :: Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI (IR.Reg Temp
t) = ([AArch64 AbsReg FAbsReg F2Abs ()]
 -> [AArch64 AbsReg FAbsReg F2Abs ()],
 AbsReg)
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([AArch64 AbsReg FAbsReg F2Abs ()]
-> [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> a
id, Temp -> AbsReg
absReg Temp
t)
plI Exp
e          = do {i <- StateT WSt Identity Int
nextI; pl <- eval e (IR.ITemp i); pure ((pl++), IReg i)}

ir :: IR.Stmt -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
ir :: Stmt -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
ir (IR.R Label
l)      = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> Label -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> Label -> AArch64 reg freg f2 a
RetL () Label
l]
ir (IR.L Label
l)      = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> Label -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> Label -> AArch64 reg freg f2 a
Label () Label
l]
ir (IR.J Label
l)      = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> Label -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> Label -> AArch64 reg freg f2 a
B () Label
l]
ir (IR.C Label
l)      = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> Label -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> Label -> AArch64 reg freg f2 a
C () Label
l]
ir (IR.MX FTemp
t FExp
e)   = FExp -> FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
feval FExp
e FTemp
t
ir (IR.MT Temp
t Exp
e)   = Exp -> Temp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
eval Exp
e Temp
t
ir (IR.Ma AL
_ Temp
t Exp
e) = do {r <- WM AbsReg
nextR; plE <- eval e IR.C0; pure $ plE ++ puL ++ [AddRC () FP ASP 16, MovRCf () r Malloc, Blr () r, MovRR () (absReg t) CArg0] ++ poL}
ir (IR.Free Temp
t) = do {r <- WM AbsReg
nextR; pure $ puL ++ [MovRR () CArg0 (absReg t), AddRC () FP ASP 16, MovRCf () r Free, Blr () r] ++ poL}
ir (IR.Sa Temp
t (IR.ConstI Int64
i)) | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 (Int64 -> Int64
forall {a}. Integral a => a -> a
sai Int64
i) = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AbsReg -> Word16 -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a.
a -> reg -> reg -> Word16 -> AArch64 reg freg f2 a
SubRC () AbsReg
ASP AbsReg
ASP Word16
u, () -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> reg -> AArch64 reg freg f2 a
MovRR () (Temp -> AbsReg
absReg Temp
t) AbsReg
ASP]
ir (IR.Sa Temp
t (IR.Reg Temp
r)) = let r' :: AbsReg
r'=Temp -> AbsReg
absReg Temp
r in do {plR <- AbsReg -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
aR AbsReg
r'; pure $ plR++[SubRR () ASP ASP (absReg r), MovRR () (absReg t) ASP]}
ir (IR.Sa Temp
t Exp
e) = do
    r <- StateT WSt Identity Int
nextI; plE <- eval e (IR.ITemp r)
    let r'=Int -> AbsReg
IReg Int
r
    plR <- aR r'
    pure $ plE ++ plR ++ [SubRR () ASP ASP r', MovRR () (absReg t) ASP]
ir (IR.Pop (IR.ConstI Int64
i)) | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 (Int64 -> Int64
forall {a}. Integral a => a -> a
sai Int64
i) = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AbsReg -> Word16 -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a.
a -> reg -> reg -> Word16 -> AArch64 reg freg f2 a
AddRC () AbsReg
ASP AbsReg
ASP Word16
u]
ir (IR.Pop (IR.Reg Temp
r)) = let r' :: AbsReg
r'=Temp -> AbsReg
absReg Temp
r in do {plR <- AbsReg -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
aR AbsReg
r'; pure $ plR ++ [AddRR () ASP ASP r']}
ir (IR.Pop Exp
e) = do
    r <- StateT WSt Identity Int
nextI; plE <- eval e (IR.ITemp r)
    let r'=Int -> AbsReg
IReg Int
r
    plR <- aR r'
    pure $ plE ++ plR ++ [AddRR () ASP ASP r']
ir (IR.Wr (IR.AP Temp
t Maybe Exp
Nothing Maybe AL
_) Exp
e) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Str () r (R $ absReg t)]
ir (IR.Wr (IR.AP Temp
t (Just (IR.ConstI Int64
i)) Maybe AL
_) Exp
e) | Just Word16
p <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mp Int64
i = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Str () r (RP (absReg t) p)]
ir (IR.Wr (IR.AP Temp
t (Just (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3))) Maybe AL
_) Exp
e) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e; (plEI,rI) <- plI eI
    pure $ plE $ plEI [Str () r (BI (absReg t) rI Three)]
ir (IR.Wr (IR.AP Temp
t (Just (IR.IB IBin
Op.IPlus (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3)) (IR.ConstI Int64
i))) Maybe AL
_) Exp
e) | (Int64
ix, Int64
0) <- Int64
i Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
8 = do
    rI <- StateT WSt Identity Int
nextI
    plEI <- eval (eI+IR.ConstI ix) (IR.ITemp rI)
    (plE,r) <- plI e
    pure $ plE $ plEI ++ [Str () r (BI (absReg t) (IReg rI) Three)]
ir (IR.Wr (IR.AP Temp
t (Just Exp
eI) Maybe AL
_) Exp
e) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e; (plEI,rI) <- plI eI
    pure $ plE $ plEI [Str () r (BI (absReg t) rI Zero)]
ir (IR.WrB (IR.AP Temp
t (Just (IR.ConstI Int64
i)) Maybe AL
_) (IR.ConstI Int64
n)) | Just Word16
iu <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
i, Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
n = do
    r <- WM AbsReg
nextR
    pure [MovRC () r u, StrB () r (RP (absReg t) iu)]
ir (IR.WrB (IR.AP Temp
t (Just Exp
eI) Maybe AL
_) (IR.ConstI Int64
n)) | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
n = do
    i <- WM AbsReg
nextR
    (plEI,rI) <- plI eI
    pure $ plEI [MovRC () i u, StrB () i (BI (absReg t) rI Zero)]
ir (IR.WrB (IR.AP Temp
t (Just (IR.ConstI Int64
ix)) Maybe AL
_) (IR.Is Temp
i)) | Just Word16
iu <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
ix = do
    [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Addr reg -> AArch64 reg freg f2 a
StrB () (Temp -> AbsReg
absReg Temp
i) (AbsReg -> Word16 -> Addr AbsReg
forall reg. reg -> Word16 -> Addr reg
RP (Temp -> AbsReg
absReg Temp
t) Word16
iu)]
ir (IR.WrB (IR.AP Temp
t (Just Exp
eI) Maybe AL
_) (IR.Is Temp
i)) = do
    (plEI,rI) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
eI
    pure $ plEI [StrB () (absReg i) (BI (absReg t) rI Zero)]
ir (IR.WrF (IR.AP Temp
tB (Just (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3))) Maybe AL
_) FExp
e) = do
    (plEI,iI) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
eI
    (plE,i) <- plF e
    pure $ plE $ plEI [StrD () i (BI (absReg tB) iI Three)]
ir (IR.WrF (IR.AP Temp
tB (Just (IR.IB IBin
Op.IPlus (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3)) (IR.ConstI Int64
ix8))) Maybe AL
_) FExp
e) | (Int64
ix, Int64
0) <- Int64
ix8 Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
8 = do
    iI <- StateT WSt Identity Int
nextI
    plEI <- eval (eI+IR.ConstI ix) (IR.ITemp iI)
    (plE,i) <- plF e
    pure $ plE $ plEI ++ [StrD () i (BI (absReg tB) (IReg iI) Three)]
ir (IR.WrF (IR.AP Temp
t (Just Exp
eI) Maybe AL
_) FExp
e) = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e; (plEI,iI) <- plI eI
    pure $ plE $ plEI [StrD () i (BI (absReg t) iI Zero)]
ir (IR.WrF (IR.AP Temp
t Maybe Exp
Nothing Maybe AL
_) FExp
e) = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [StrD () i (R (absReg t))]
ir (IR.MJ (IR.IRel IRel
Op.INeq Exp
e (IR.ConstI Int64
0)) Label
l) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Cbnz () r l]
ir (IR.MJ (IR.Is Temp
r) Label
l) =
    [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Label -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Label -> AArch64 reg freg f2 a
Cbnz () (Temp -> AbsReg
absReg Temp
r) Label
l]
ir (IR.MJ (IR.IU IUn
Op.IEven Exp
e) Label
l) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Tbz () r 0 l]
ir (IR.MJ (IR.IRel IRel
op Exp
e (IR.ConstI Int64
i)) Label
l) | Cond
c <- IRel -> Cond
iop IRel
op, Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
m12 Int64
i = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [CmpRC () r u, Bc () c l]
ir (IR.MJ (IR.IRel IRel
op Exp
e0 Exp
e1) Label
l) | Cond
c <- IRel -> Cond
iop IRel
op = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [CmpRR () r0 r1, Bc () c l]
ir (IR.MJ (IR.FRel FRel
op FExp
e (IR.ConstF Double
0)) Label
l) | Cond
c <- FRel -> Cond
frel FRel
op = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [FcmpZ () i, Bc () c l]
ir (IR.MJ (IR.FRel FRel
op FExp
e0 FExp
e1) Label
l) | Cond
c <- FRel -> Cond
frel FRel
op = do
    (plE0,r0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,r1) <- plF e1
    pure $ plE0 $ plE1 [Fcmp () r0 r1, Bc () c l]
ir (IR.MJ (IR.BU BUn
Op.BNeg Exp
p) Label
l) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
p
    pure $ plE [Cbz () r l]
ir (IR.MJ Exp
p Label
l) = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
p
    pure $ plE [Cbnz () r l]
ir (IR.Cmov (IR.IRel IRel
op Exp
e0 Exp
e1) Temp
t Exp
e) | Cond
c <- IRel -> Cond
iop IRel
op = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    (plE,r) <- plI e
    pure $ plE $ plE0 $ plE1 [CmpRR () r0 r1, Csel () (absReg t) r (absReg t) c]
ir (IR.Cset Temp
t (IR.IRel IRel
op Exp
e0 (IR.ConstI Int64
i))) | Cond
c <- IRel -> Cond
iop IRel
op, Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
m12 Int64
i = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0
    pure $ plE0 [CmpRC () r0 u, Cset () (absReg t) c]
ir (IR.Cset Temp
t (IR.IRel IRel
op Exp
e0 Exp
e1)) | Cond
c <- IRel -> Cond
iop IRel
op = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [CmpRR () r0 r1, Cset () (absReg t) c]
ir (IR.Cset Temp
t (IR.FRel FRel
op FExp
e0 FExp
e1)) | Cond
c <- FRel -> Cond
frel FRel
op = do
    (plE0,r0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,r1) <- plF e1
    pure $ plE0 $ plE1 [Fcmp () r0 r1, Cset () (absReg t) c]
ir (IR.Cset Temp
t (IR.IU IUn
Op.IOdd Exp
e0)) = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0
    pure $ plE0 [TstI () r0 (BM 1 0), Cset () (absReg t) Neq]
ir (IR.Cset Temp
t (IR.IU IUn
Op.IEven Exp
e0)) = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0
    pure $ plE0 [TstI () r0 (BM 1 0), Cset () (absReg t) Eq]
ir (IR.Fcmov (IR.IRel IRel
op Exp
e0 (IR.ConstI Int64
i64)) FTemp
t FExp
e) | Cond
c <- IRel -> Cond
iop IRel
op, Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
m12 Int64
i64 = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE,i) <- plF e
    pure $ plE $ plE0 [CmpRC () r0 u, Fcsel () (fabsReg t) i (fabsReg t) c]
ir (IR.Fcmov (IR.IRel IRel
op Exp
e0 Exp
e1) FTemp
t FExp
e) | Cond
c <- IRel -> Cond
iop IRel
op = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    (plE,i) <- plF e
    pure $ plE $ plE0 $ plE1 [CmpRR () r0 r1, Fcsel () (fabsReg t) i (fabsReg t) c]
ir (IR.Fcmov (IR.FRel FRel
op FExp
e0 FExp
e1) FTemp
t FExp
e) | Cond
c <- FRel -> Cond
frel FRel
op = do
    (plE0,r0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,r1) <- plF e1
    (plE,i) <- plF e
    pure $ plE $ plE0 $ plE1 [Fcmp () r0 r1, Fcsel () (fabsReg t) i (fabsReg t) c]
ir (IR.Fcmov (IR.IU IUn
Op.IOdd Exp
e0) FTemp
t FExp
e) = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE,i) <- plF e
    pure $ plE $ plE0 [TstI () r0 (BM 1 0), Fcsel () (fabsReg t) i (fabsReg t) Neq]
ir (IR.Fcmov (IR.IU IUn
Op.IEven Exp
e0) FTemp
t FExp
e) = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE,i) <- plF e
    pure $ plE $ plE0 [TstI () r0 (BM 1 0), Fcsel () (fabsReg t) i (fabsReg t) Eq]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
Nothing Maybe AL
_) (IR.AP Temp
tS Maybe Exp
Nothing Maybe AL
_) (IR.ConstI Int64
n)) | (Int64
n', Int64
0) <- Int64
n Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
2, Int64
n' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    t0 <- WM AbsReg
nextR; t1 <- nextR
    pure $ concat [ [Ldp () t0 t1 (RP (absReg tS) (i*16)), Stp () t0 t1 (RP (absReg tD) (i*16))] | i <- fromIntegral<$>[0..(n'-1)] ]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
Nothing Maybe AL
_) (IR.AP Temp
tS Maybe Exp
Nothing Maybe AL
_) (IR.ConstI Int64
n)) | Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    t <- WM AbsReg
nextR
    pure $ concat [ [Ldr () t (RP (absReg tS) (i*8)), Str () t (RP (absReg tD) (i*8))] | i <- fromIntegral<$>[0..(n-1)] ]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
Nothing Maybe AL
_) (IR.AP Temp
tS (Just Exp
eS) Maybe AL
_) (IR.ConstI Int64
n)) | (Int64
n', Int64
0) <- Int64
n Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
2, Int64
n' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS+eS) (IR.ITemp rS)
    pure $ plED ++ plES ++ concat [ [Ldp () t0 t1 (RP (IReg rS) (i*16)), Stp () t0 t1 (RP (IReg rD) (i*16))] | i <- fromIntegral<$>[0..(n'-1)] ]
ir (IR.Cpy (IR.AP Temp
tD (Just Exp
eD) Maybe AL
_) (IR.AP Temp
tS Maybe Exp
Nothing Maybe AL
_) (IR.ConstI Int64
n)) | (Int64
n', Int64
0) <- Int64
n Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
2, Int64
n' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD+eD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS) (IR.ITemp rS)
    pure $ plED ++ plES ++ concat [ [Ldp () t0 t1 (RP (IReg rS) (i*16)), Stp () t0 t1 (RP (IReg rD) (i*16))] | i <- fromIntegral<$>[0..(n'-1)] ]
ir (IR.Cpy (IR.AP Temp
tD (Just Exp
eD) Maybe AL
_) (IR.AP Temp
tS (Just Exp
eS) Maybe AL
_) (IR.ConstI Int64
n)) | (Int64
n', Int64
0) <- Int64
n Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
2, Int64
n' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD+eD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS+eS) (IR.ITemp rS)
    pure $ plED ++ plES ++ concat [ [Ldp () t0 t1 (RP (IReg rS) (i*16)), Stp () t0 t1 (RP (IReg rD) (i*16))] | i <- fromIntegral<$>[0..(n'-1)] ]
ir (IR.Cpy (IR.AP Temp
tD (Just Exp
eD) Maybe AL
_) (IR.AP Temp
tS (Just Exp
eS) Maybe AL
_) (IR.ConstI Int64
n)) | (Int64
n', Int64
1) <- Int64
n Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
2, Int64
n' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
4 = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD+eD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS+eS) (IR.ITemp rS)
    let li=Int64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral(Int64 -> Word16) -> Int64 -> Word16
forall a b. (a -> b) -> a -> b
$(Int64
nInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
-Int64
1)Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
*Int64
8
    pure $ plED ++ plES ++ concat [ [Ldp () t0 t1 (RP (IReg rS) (i*16)), Stp () t0 t1 (RP (IReg rD) (i*16))] | i <- fromIntegral<$>[0..(n'-1)] ] ++ [Ldr () t0 (RP (IReg rS) li), Str () t0 (RP (IReg rD) li)]
ir (IR.Cpy (IR.AP Temp
tD (Just (IR.ConstI Int64
oD)) Maybe AL
_) (IR.AP Temp
tS (Just (IR.ConstI Int64
oS)) Maybe AL
_) Exp
eN) | Just Word16
uS <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
oS, Just Word16
uD <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
oD = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    l <- nextL; eL <- nextL
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Tbz () rN 0 l, Ldr () t0 (RP rSA uS), Str () t0 (RP rDA uD), MovRC () i 1, Bc () Geq eL, AddRC () rSA rSA 8, AddRC () rDA rDA 8, Label () l, Ldp () t0 t1 (RP rSA uS), Stp () t0 t1 (RP rDA uD), AddRC () rSA rSA 16, AddRC () rDA rDA 16, AddRC () i i 2, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy (IR.AP Temp
tD (Just (IR.ConstI Int64
oD)) Maybe AL
_) (IR.AP Temp
tS Maybe Exp
eS Maybe AL
_) Exp
eN) | Just Word16
uD <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
oD = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR
    t0 <- nextR; t1 <- nextR
    plED <- eval (IR.Reg tD) (IR.ITemp rD)
    plES <- eval (maybe id (+) eS$IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    l <- nextL; eL <- nextL
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Tbz () rN 0 l, Ldr () t0 (R rSA), Str () t0 (RP rDA uD), MovRC () i 1, Bc () Geq eL, AddRC () rSA rSA 8, AddRC () rDA rDA 8, Label () l, Ldp () t0 t1 (R rSA), Stp () t0 t1 (RP rDA uD), AddRC () rSA rSA 16, AddRC () rDA rDA 16, AddRC () i i 2, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
eD Maybe AL
_) (IR.AP Temp
tS (Just (IR.ConstI Int64
oS)) Maybe AL
_) Exp
eN) | Just Word16
uS <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
oS = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR
    t0 <- nextR; t1 <- nextR
    plED <- eval (maybe id (+) eD$IR.Reg tD) (IR.ITemp rD)
    plES <- eval (IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    l <- nextL; eL <- nextL
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Tbz () rN 0 l, Ldr () t0 (RP rSA uS), Str () t0 (R rDA), MovRC () i 1, Bc () Geq eL, AddRC () rSA rSA 8, AddRC () rDA rDA 8, Label () l, Ldp () t0 t1 (RP rSA uS), Stp () t0 t1 (R rDA), AddRC () rSA rSA 16, AddRC () rDA rDA 16, AddRC () i i 2, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
eD Maybe AL
_) (IR.AP Temp
tS (Just (IR.IB IBin
Op.IPlus Exp
eS (IR.ConstI Int64
oS))) Maybe AL
_) Exp
eN) | Just Word16
uS <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
oS = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR
    t0 <- nextR; t1 <- nextR
    plED <- eval (maybe id (+) eD$IR.Reg tD) (IR.ITemp rD)
    plES <- eval (eS+IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    l <- nextL; eL <- nextL
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Tbz () rN 0 l, Ldr () t0 (RP rSA uS), Str () t0 (R rDA), MovRC () i 1, Bc () Geq eL, AddRC () rSA rSA 8, AddRC () rDA rDA 8, Label () l, Ldp () t0 t1 (RP rSA uS), Stp () t0 t1 (R rDA), AddRC () rSA rSA 16, AddRC () rDA rDA 16, AddRC () i i 2, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy (IR.AP Temp
tD Maybe Exp
eD Maybe AL
_) (IR.AP Temp
tS Maybe Exp
eS Maybe AL
_) Exp
eN) = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR
    t0 <- nextR; t1 <- nextR
    plED <- eval (maybe id (+) eD$IR.Reg tD) (IR.ITemp rD)
    plES <- eval (maybe id (+) eS$IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    l <- nextL; eL <- nextL
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Tbz () rN 0 l, Ldr () t0 (R rSA), Str () t0 (R rDA), MovRC () i 1, Bc () Geq eL, AddRC () rSA rSA 8, AddRC () rDA rDA 8, Label () l, Ldp () t0 t1 (R rSA), Stp () t0 t1 (R rDA), AddRC () rSA rSA 16, AddRC () rDA rDA 16, AddRC () i i 2, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy1 (IR.AP Temp
tD (Just (IR.ConstI Int64
di)) Maybe AL
_) (IR.AP Temp
tS (Just (IR.ConstI Int64
si)) Maybe AL
_) Exp
eN) | Just Word16
du <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
di, Just Word16
su <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
si = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR; t <- nextR
    (plEN, rN) <- plI eN
    l <- nextL; eL <- nextL
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    pure $ plEN [MovRR () rDA (absReg tD), MovRR () rSA (absReg tS), ZeroR () i, CmpRR () i rN, Bc () Geq eL, Label () l, LdrB () t (RP rSA du), StrB () t (RP rDA su), AddRC () rSA rSA 1, AddRC () rDA rDA 1, AddRC () i i 1, CmpRR () i rN, Bc () Lt l, Label () eL]
ir (IR.Cpy1 (IR.AP Temp
tD Maybe Exp
eD Maybe AL
_) (IR.AP Temp
tS Maybe Exp
eS Maybe AL
_) Exp
eN) = do
    rD <- StateT WSt Identity Int
nextI; rS <- nextI; i <- nextR; t <- nextR
    plED <- eval (maybe id (+) eD$IR.Reg tD) (IR.ITemp rD)
    plES <- eval (maybe id (+) eS$IR.Reg tS) (IR.ITemp rS)
    (plEN, rN) <- plI eN
    l <- nextL; eL <- nextL
    let rDA=Int -> AbsReg
IReg Int
rD; rSA=Int -> AbsReg
IReg Int
rS
    pure $ plED ++ plES ++ plEN [ZeroR () i, CmpRR () i rN, Bc () Geq eL, Label () l, LdrB () t (BI rSA i Zero), StrB () t (BI rDA i Zero), AddRC () i i 1, CmpRR () i rN, Bc () Lt l, Label () eL]
-- ir (IR.IRnd t) = pure [MrsR () (absReg t)]
ir (IR.IRnd Temp
t) = do
    r <- WM AbsReg
nextR
    pure $ puL ++ [AddRC () FP ASP 16, MovRCf () r JR, Blr () r, MovRR () (absReg t) CArg0] ++ poL
ir (IR.FRnd FTemp
t) = do
    r <- WM AbsReg
nextR
    pure $ puL ++ [AddRC () FP ASP 16, MovRCf () r DR, Blr () r, FMovXX () (fabsReg t) FArg0] ++ poL
ir Stmt
s             = [Char] -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. HasCallStack => [Char] -> a
error (Stmt -> [Char]
forall a. Show a => a -> [Char]
show Stmt
s)

puL, poL :: [AArch64 AbsReg freg f2reg ()]
puL :: forall freg f2reg. [AArch64 AbsReg freg f2reg ()]
puL = [() -> AbsReg -> AbsReg -> Word16 -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a.
a -> reg -> reg -> Word16 -> AArch64 reg freg f2 a
SubRC () AbsReg
ASP AbsReg
ASP Word16
16, ()
-> AbsReg -> AbsReg -> Addr AbsReg -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a.
a -> reg -> reg -> Addr reg -> AArch64 reg freg f2 a
Stp () AbsReg
FP AbsReg
LR (AbsReg -> Addr AbsReg
forall reg. reg -> Addr reg
R AbsReg
ASP)]
poL :: forall freg f2reg. [AArch64 AbsReg freg f2reg ()]
poL = [()
-> AbsReg -> AbsReg -> Addr AbsReg -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a.
a -> reg -> reg -> Addr reg -> AArch64 reg freg f2 a
Ldp () AbsReg
FP AbsReg
LR (AbsReg -> Addr AbsReg
forall reg. reg -> Addr reg
R AbsReg
ASP), () -> AbsReg -> AbsReg -> Word16 -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a.
a -> reg -> reg -> Word16 -> AArch64 reg freg f2 a
AddRC () AbsReg
ASP AbsReg
ASP Word16
16]

sai :: a -> a
sai a
i | a
i a -> a -> a
forall a. Integral a => a -> a -> a
`rem` a
16 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a
ia -> a -> a
forall a. Num a => a -> a -> a
+a
16 | Bool
otherwise = a
ia -> a -> a
forall a. Num a => a -> a -> a
+a
16a -> a -> a
forall a. Num a => a -> a -> a
+(a
16a -> a -> a
forall a. Num a => a -> a -> a
-a
r) where r :: a
r = a
i a -> a -> a
forall a. Integral a => a -> a -> a
`rem` a
16

mw64 :: Word64 -> AbsReg -> [AArch64 AbsReg freg f2reg ()]
mw64 :: forall freg f2reg.
Word64 -> AbsReg -> [AArch64 AbsReg freg f2reg ()]
mw64 Word64
w AbsReg
r =
    let w0 :: Word64
w0=Word64
w Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xffff; w1 :: Word64
w1=(Word64
w Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xffff0000) Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`rotateR` Int
16; w2 :: Word64
w2=(Word64
w Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xFFFF00000000) Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`rotateR` Int
32; w3 :: Word64
w3=(Word64
w Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0xFFFF000000000000) Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`rotateR` Int
48
    in () -> AbsReg -> Word16 -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a. a -> reg -> Word16 -> AArch64 reg freg f2 a
MovRC () AbsReg
r (Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w0)AArch64 AbsReg freg f2reg ()
-> [AArch64 AbsReg freg f2reg ()] -> [AArch64 AbsReg freg f2reg ()]
forall a. a -> [a] -> [a]
:[() -> AbsReg -> Word16 -> Int -> AArch64 AbsReg freg f2reg ()
forall reg freg f2 a.
a -> reg -> Word16 -> Int -> AArch64 reg freg f2 a
MovK () AbsReg
r (Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
wi) Int
s | (Word64
wi, Int
s) <- [(Word64
w1, Int
16), (Word64
w2, Int
32), (Word64
w3, Int
48)], Word64
wi Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word64
0 ]

ssin :: IR.FTemp -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
ssin :: FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
ssin FTemp
t = do
    d1 <- WM FAbsReg
nextF; d2 <- nextF; d3 <- nextF
    tsI <- nextI
    let tsIR=Int -> FTemp
IR.FTemp Int
tsI; tsC=Int -> FAbsReg
FReg Int
tsI
    pl3 <- feval (IR.ConstF$ -(1/6)) tsIR; pl5 <- feval (IR.ConstF$1/120) tsIR; pl7 <- feval (IR.ConstF$ -(1/5040)) tsIR
    pure $ [Fmul () d1 d0 d0, Fmul () d2 d1 d0, Fmul () d3 d2 d1, Fmul () d1 d1 d3] ++ pl3 ++ Fmadd () d0 d2 tsC d0 : pl5 ++ Fmadd () d0 d3 tsC d0 : pl7 ++ [Fmadd () d0 d1 tsC d0]
  where
    d0 :: FAbsReg
d0 = FTemp -> FAbsReg
fabsReg FTemp
t

cosϵ :: IR.FTemp -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
cosϵ :: FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
cosϵ FTemp
t = do
    d1 <- WM FAbsReg
nextF; d2 <- nextF; d3 <- nextF
    tsI <- nextI
    let tsIR=Int -> FTemp
IR.FTemp Int
tsI; tsC=Int -> FAbsReg
FReg Int
tsI
    pl0 <- feval 1 tsIR; pl2 <- feval (IR.ConstF$ -(1/2)) tsIR; pl4 <- feval (IR.ConstF$1/24) tsIR; pl6 <- feval (IR.ConstF$ -(1/720)) tsIR
    pure $ [Fmul () d1 d0 d0, Fmul () d2 d1 d1, Fmul () d3 d2 d1] ++ pl0 ++ FMovXX () d0 tsC : pl2 ++ Fmadd () d0 d1 tsC d0 : pl4 ++ Fmadd () d0 d2 tsC d0 : pl6 ++ [Fmadd () d0 d3 tsC d0]
  where
    d0 :: FAbsReg
d0 = FTemp -> FAbsReg
fabsReg FTemp
t

feval :: IR.FExp -> IR.FTemp -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
feval :: FExp -> FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
feval (IR.FReg FTemp
tS) FTemp
tD = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> FAbsReg -> FAbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> freg -> freg -> AArch64 reg freg f2 a
FMovXX () (FTemp -> FAbsReg
fabsReg FTemp
tD) (FTemp -> FAbsReg
fabsReg FTemp
tS)]
feval (IR.ConstF Double
d) FTemp
t = do
    i <- StateT WSt Identity Int
nextI
    let r=Int -> AbsReg
IReg Int
i
        w=Double -> Word64
castDoubleToWord64 Double
d
    pure $ mw64 w r ++ [FMovDR () (fabsReg t) r]
-- https://litchie.com/2020/04/sine
feval (IR.FU FUn
Op.FSin FExp
e) FTemp
t = do
    plE <- FExp -> FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
feval FExp
e FTemp
t
    let d0=FTemp -> FAbsReg
fabsReg FTemp
t
    s <- ssin t; c <- cosϵ t
    lc <- nextL; endL <- nextL
    i <- nextR; d2 <- nextF; i7 <- nextI
    π4i<-nextI; plπ4 <- feval (IR.ConstF$pi/4) (IR.FTemp π4i); pl7 <- eval (IR.ConstI 7) (IR.ITemp i7)
    let π4=Int -> FAbsReg
FReg Int
π4i
    dRot <- nextF; nres <- nextF
    pure $
        plE
        ++plπ4
        ++[Fdiv () d2 d0 π4, Frintm () d2 d2, Fmsub () d0 π4 d2 d0, Fcvtas () i d2]
        ++pl7
        ++[AndRR () i i (IReg i7), TstI () i (BM 1 0), Fsub () dRot π4 d0, Fcsel () d0 dRot d0 Neq]
        ++[ CmpRC () i 1, Bc () Eq lc, CmpRC () i 2, Bc () Eq lc
          , CmpRC () i 5, Bc () Eq lc, CmpRC () i 6, Bc () Eq lc
          ]
        ++s++B () endL
        :Label () lc:c
        ++[Label () endL]
        ++[Fneg () nres d0, TstI () i (BM 1 2), Fcsel () d0 nres d0 Neq]
feval (IR.FU FUn
Op.FCos FExp
e) FTemp
t = FExp -> FTemp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
feval (FUn -> FExp -> FExp
IR.FU FUn
Op.FSin (Double -> FExp
IR.ConstF(Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)FExp -> FExp -> FExp
forall a. Num a => a -> a -> a
-FExp
e)) FTemp
t
feval (IR.FB FBin
Op.FExp (IR.ConstF Double
2.718281828459045) FExp
e) FTemp
t = do
    r <- WM AbsReg
nextR
    plE <- feval e IR.F0
    pure $ plE ++ puL ++ [AddRC () FP ASP 16, MovRCf () r Exp, Blr () r, FMovXX () (fabsReg t) FArg0] ++ poL
feval (IR.FB FBin
Op.FExp FExp
e0 FExp
e1) FTemp
t = do
    r <- WM AbsReg
nextR
    plE0 <- feval e0 IR.F0; plE1 <- feval e1 IR.F1
    pure $ plE0 ++ plE1 ++ puL ++ [AddRC () FP ASP 16, MovRCf () r Pow, Blr () r, FMovXX () (fabsReg t) FArg0] ++ poL
feval (IR.FU FUn
Op.FLog FExp
e) FTemp
t = do
    r <- WM AbsReg
nextR
    plE <- feval e IR.F0
    pure $ plE ++ puL ++ [AddRC () FP ASP 16, MovRCf () r Log, Blr () r, FMovXX () (fabsReg t) FArg0] ++ poL
feval (IR.FB FBin
Op.FPlus FExp
e0 (IR.FB FBin
Op.FTimes FExp
e1 FExp
e2)) FTemp
t = do
    (plE0,i0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,i1) <- plF e1; (plE2,i2) <- plF e2
    pure $ plE0 $ plE1 $ plE2 [Fmadd () (fabsReg t) i1 i2 i0]
feval (IR.FB FBin
Op.FPlus (IR.FB FBin
Op.FTimes FExp
e0 FExp
e1) FExp
e2) FTemp
t = do
    (plE0,i0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,i1) <- plF e1; (plE2,i2) <- plF e2
    pure $ plE0 $ plE1 $ plE2 [Fmadd () (fabsReg t) i0 i1 i2]
feval (IR.FB FBin
Op.FMinus FExp
e0 (IR.FB FBin
Op.FTimes FExp
e1 FExp
e2)) FTemp
t = do
    (plE0,i0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,i1) <- plF e1; (plE2,i2) <- plF e2
    pure $ plE0 $ plE1 $ plE2 [Fmsub () (fabsReg t) i1 i2 i0]
feval (IR.FB FBin
Op.FMinus (IR.ConstF Double
0) FExp
e) FTemp
t = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fneg () (fabsReg t) i]
feval (IR.FB FBin
Op.FTimes (IR.ConstF (-1)) FExp
e) FTemp
t = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fneg () (fabsReg t) i]
feval (IR.FB FBin
Op.FTimes FExp
e (IR.ConstF (-1))) FTemp
t = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fneg () (fabsReg t) i]
feval (IR.FB FBin
fop FExp
e0 FExp
e1) FTemp
t | Just ()
-> FAbsReg -> FAbsReg -> FAbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
isn <- FBin
-> Maybe
     (()
      -> FAbsReg
      -> FAbsReg
      -> FAbsReg
      -> AArch64 AbsReg FAbsReg F2Abs ())
forall {a} {freg} {reg} {f2}.
FBin -> Maybe (a -> freg -> freg -> freg -> AArch64 reg freg f2 a)
mFop FBin
fop = do
    (plE0,r0) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e0; (plE1,r1) <- plF e1
    pure $ plE0 $ plE1 [isn () (fabsReg t) r0 r1]
feval (IR.FU FUn
Op.FAbs FExp
e) FTemp
t = do
    (plE,i) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fabs () (fabsReg t) i]
feval (IR.FAt (IR.AP Temp
tS (Just (IR.ConstI Int64
i)) Maybe AL
_)) FTemp
tD | Just Word16
i8 <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mp Int64
i = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> FAbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a.
a -> freg -> Addr reg -> AArch64 reg freg f2 a
LdrD () (FTemp -> FAbsReg
fabsReg FTemp
tD) (AbsReg -> Word16 -> Addr AbsReg
forall reg. reg -> Word16 -> Addr reg
RP (Temp -> AbsReg
absReg Temp
tS) Word16
i8)]
feval (IR.FAt (IR.AP Temp
tB (Just (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3))) Maybe AL
_)) FTemp
tD = do
    (plE,i) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
eI
    pure $ plE [LdrD () (fabsReg tD) (BI (absReg tB) i Three)]
feval (IR.FAt (IR.AP Temp
tB (Just (IR.IB IBin
Op.IPlus (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3)) (IR.ConstI Int64
ix8))) Maybe AL
_)) FTemp
tD | (Int64
ix, Int64
0) <- Int64
ix8 Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int64
8 = do
    i <- StateT WSt Identity Int
nextI; plE <- eval (eI+IR.ConstI ix) (IR.ITemp i)
    pure $ plE ++ [LdrD () (fabsReg tD) (BI (absReg tB) (IReg i) Three)]
feval (IR.FAt (IR.AP Temp
tB (Just Exp
e) Maybe AL
_)) FTemp
tD = do
    i <- StateT WSt Identity Int
nextI; plE <- eval e (IR.ITemp i)
    pure $ plE ++ [LdrD () (fabsReg tD) (BI (absReg tB) (IReg i) Zero)]
feval (IR.FAt (IR.AP Temp
tB Maybe Exp
Nothing Maybe AL
_)) FTemp
tD =
    [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> FAbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a.
a -> freg -> Addr reg -> AArch64 reg freg f2 a
LdrD () (FTemp -> FAbsReg
fabsReg FTemp
tD) (AbsReg -> Addr AbsReg
forall reg. reg -> Addr reg
R (Temp -> AbsReg
absReg Temp
tB))]
feval (IR.FConv Exp
e) FTemp
tD = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Scvtf () (fabsReg tD) r]
feval (IR.FU FUn
Op.FSqrt FExp
e) FTemp
t = do
    (plE,r) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fsqrt () (fabsReg t) r]
feval FExp
e FTemp
_             = [Char] -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. HasCallStack => [Char] -> a
error (FExp -> [Char]
forall a. Show a => a -> [Char]
show FExp
e)

eval :: IR.Exp -> IR.Temp -> WM [AArch64 AbsReg FAbsReg F2Abs ()]
eval :: Exp -> Temp -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
eval (IR.Reg Temp
tS) Temp
tD = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> reg -> AArch64 reg freg f2 a
MovRR () (Temp -> AbsReg
absReg Temp
tD) (Temp -> AbsReg
absReg Temp
tS)]
eval (IR.ConstI Int64
0) Temp
tD = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> AArch64 reg freg f2 a
ZeroR () (Temp -> AbsReg
absReg Temp
tD)]
eval (IR.ConstI Int64
i) Temp
tD | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
i = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Word16 -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Word16 -> AArch64 reg freg f2 a
MovRC () (Temp -> AbsReg
absReg Temp
tD) Word16
u]
eval (IR.ConstI Int64
i) Temp
tD | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 (-Int64
i) = let t :: AbsReg
t=Temp -> AbsReg
absReg Temp
tD in [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Word16 -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Word16 -> AArch64 reg freg f2 a
MovRC () AbsReg
t Word16
u, () -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> reg -> AArch64 reg freg f2 a
Neg () AbsReg
t AbsReg
t]
eval (IR.ConstI Int64
i) Temp
tD = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([AArch64 AbsReg FAbsReg F2Abs ()]
 -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()])
-> [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a b. (a -> b) -> a -> b
$ Word64 -> AbsReg -> [AArch64 AbsReg FAbsReg F2Abs ()]
forall freg f2reg.
Word64 -> AbsReg -> [AArch64 AbsReg freg f2reg ()]
mw64 (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i) (Temp -> AbsReg
absReg Temp
tD)
eval (IR.Is Temp
p) Temp
tD = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> reg -> AArch64 reg freg f2 a
MovRR () (Temp -> AbsReg
absReg Temp
tD) (Temp -> AbsReg
absReg Temp
p)]
eval (IR.IB IBin
Op.IPlus (IR.IB IBin
Op.IAsl Exp
e0 (IR.ConstI Int64
i)) Exp
e1) Temp
t | Just Word8
u <- Int64 -> Maybe Word8
forall a. Integral a => a -> Maybe Word8
ms Int64
i = do
    r0 <- StateT WSt Identity Int
nextI; r1 <- nextI
    plE0 <- eval e0 (IR.ITemp r0); plE1 <- eval e1 (IR.ITemp r1)
    pure $ plE0 ++ plE1 ++ [AddRRS () (absReg t) (IReg r1) (IReg r0) u]
eval (IR.IB IBin
Op.IPlus Exp
e (IR.ConstI Int64
i)) Temp
t | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
m12 Int64
i = do
    r <- StateT WSt Identity Int
nextI; plE <- eval e (IR.ITemp r)
    pure $ plE ++ [AddRC () (absReg t) (IReg r) u]
eval (IR.IB IBin
Op.IMinus Exp
e (IR.ConstI Int64
i)) Temp
t | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
m12 Int64
i = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [SubRC () (absReg t) r u]
eval (IR.IB IBin
Op.IAsl Exp
e (IR.ConstI Int64
i)) Temp
t = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Lsl () (absReg t) r (fromIntegral (i `mod` 64))]
eval (IR.IB IBin
Op.IMinus (IR.ConstI Int64
0) Exp
e) Temp
t = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Neg () (absReg t) r]
eval (IR.IB IBin
Op.ITimes (IR.ConstI (-1)) Exp
e) Temp
t = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Neg () (absReg t) r]
eval (IR.IB IBin
Op.ITimes Exp
e (IR.ConstI (-1))) Temp
t = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Neg () (absReg t) r]
eval (IR.IB IBin
Op.IRem Exp
e0 Exp
e1) Temp
t = do
    r2 <- WM AbsReg
nextR
    (plE0,r0) <- plI e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [Sdiv () r2 r0 r1, Msub () (absReg t) r2 r1 r0]
eval (IR.IB IBin
Op.IPlus (IR.IB IBin
Op.ITimes Exp
e0 Exp
e1) Exp
e2) Temp
t = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1; (plE2,r2) <- plI e2
    pure $ plE0 $ plE1 $ plE2 [Madd () (absReg t) r0 r1 r2]
eval (IR.IB IBin
Op.IMin Exp
e0 Exp
e1) Temp
t = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [CmpRR () r0 r1, Csel () (absReg t) r0 r1 Leq]
eval (IR.IB IBin
Op.IMax Exp
e0 Exp
e1) Temp
t = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [CmpRR () r0 r1, Csel () (absReg t) r0 r1 Geq]
eval (IR.IB IBin
op Exp
e0 Exp
e1) Temp
t | Just () -> AbsReg -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
isn <- IBin
-> Maybe
     (()
      -> AbsReg -> AbsReg -> AbsReg -> AArch64 AbsReg FAbsReg F2Abs ())
forall {a} {reg} {freg} {f2}.
IBin -> Maybe (a -> reg -> reg -> reg -> AArch64 reg freg f2 a)
mIop IBin
op = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [isn () (absReg t) r0 r1]
eval (IR.IRel IRel
rel Exp
e0 Exp
e1) Temp
t | Cond
c <- IRel -> Cond
iop IRel
rel = do
    (plE0,r0) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e0; (plE1,r1) <- plI e1
    pure $ plE0 $ plE1 [CmpRR () r0 r1, Cset () (absReg t) c]
eval (IR.IRFloor FExp
e) Temp
t = do
    (plE,r) <- FExp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      FAbsReg)
plF FExp
e
    pure $ plE [Fcvtms () (absReg t) r]
eval (IR.EAt (IR.AP Temp
tB (Just (IR.ConstI Int64
i)) Maybe AL
_)) Temp
tD | Just Word16
p <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mp Int64
i = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Addr reg -> AArch64 reg freg f2 a
Ldr () (Temp -> AbsReg
absReg Temp
tD) (AbsReg -> Word16 -> Addr AbsReg
forall reg. reg -> Word16 -> Addr reg
RP (Temp -> AbsReg
absReg Temp
tB) Word16
p)]
eval (IR.BAt (IR.AP Temp
tB (Just (IR.ConstI Int64
i)) Maybe AL
_)) Temp
tD | Just Word16
u <- Int64 -> Maybe Word16
forall a. Integral a => a -> Maybe Word16
mu16 Int64
i = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Addr reg -> AArch64 reg freg f2 a
LdrB () (Temp -> AbsReg
absReg Temp
tD) (AbsReg -> Word16 -> Addr AbsReg
forall reg. reg -> Word16 -> Addr reg
RP (Temp -> AbsReg
absReg Temp
tB) Word16
u)]
eval (IR.EAt (IR.AP Temp
rB (Just (IR.IB IBin
Op.IAsl Exp
eI (IR.ConstI Int64
3))) Maybe AL
_)) Temp
t = do
    (plE,i) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
eI
    pure $ plE [Ldr () (absReg t) (BI (absReg rB) i Three)]
eval (IR.EAt (IR.AP Temp
rB Maybe Exp
Nothing Maybe AL
_)) Temp
t = do
    [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Addr AbsReg -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Addr reg -> AArch64 reg freg f2 a
Ldr () (Temp -> AbsReg
absReg Temp
t) (AbsReg -> Addr AbsReg
forall reg. reg -> Addr reg
R (Temp -> AbsReg
absReg Temp
rB))]
eval (IR.EAt (IR.AP Temp
rB (Just Exp
e) Maybe AL
_)) Temp
t = do
    (plE,i) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Ldr () (absReg t) (BI (absReg rB) i Zero)]
eval (IR.BAt (IR.AP Temp
rB (Just Exp
e) Maybe AL
_)) Temp
t = do
    (plE,i) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [LdrB () (absReg t) (BI (absReg rB) i Zero)]
eval (IR.IB IBin
Op.IAsr Exp
e (IR.ConstI Int64
i)) Temp
t | Just Word8
s <- Int64 -> Maybe Word8
forall a. Integral a => a -> Maybe Word8
ms Int64
i = do
    (plE,r) <- Exp
-> WM
     ([AArch64 AbsReg FAbsReg F2Abs ()]
      -> [AArch64 AbsReg FAbsReg F2Abs ()],
      AbsReg)
plI Exp
e
    pure $ plE [Asr () (absReg t) r s]
eval (IR.LA Int
n) Temp
t = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> Int -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a. a -> reg -> Int -> AArch64 reg freg f2 a
LdrRL () (Temp -> AbsReg
absReg Temp
t) Int
n]
eval (IR.BU BUn
Op.BNeg (IR.Is Temp
r)) Temp
t = [AArch64 AbsReg FAbsReg F2Abs ()]
-> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. a -> StateT WSt Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [() -> AbsReg -> AbsReg -> BM -> AArch64 AbsReg FAbsReg F2Abs ()
forall reg freg f2 a.
a -> reg -> reg -> BM -> AArch64 reg freg f2 a
EorI () (Temp -> AbsReg
absReg Temp
t) (Temp -> AbsReg
absReg Temp
r) (Word8 -> Word8 -> BM
BM Word8
1 Word8
0)]
eval Exp
e Temp
_            = [Char] -> State WSt [AArch64 AbsReg FAbsReg F2Abs ()]
forall a. HasCallStack => [Char] -> a
error (Exp -> [Char]
forall a. Show a => a -> [Char]
show Exp
e)

ms :: Integral a => a -> Maybe Word8
ms :: forall a. Integral a => a -> Maybe Word8
ms a
i | a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>=a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
63 = Word8 -> Maybe Word8
forall a. a -> Maybe a
Just (a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i) | Bool
otherwise = Maybe Word8
forall a. Maybe a
Nothing

m12, mu16 :: Integral a => a -> Maybe Word16
m12 :: forall a. Integral a => a -> Maybe Word16
m12 a
i | a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
4096 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just (a -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i) | Bool
otherwise = Maybe Word16
forall a. Maybe a
Nothing

mu16 :: forall a. Integral a => a -> Maybe Word16
mu16 a
i | a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> Word16 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
maxBound :: Word16) Bool -> Bool -> Bool
|| a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< Word16 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
minBound :: Word16) = Maybe Word16
forall a. Maybe a
Nothing
       | Bool
otherwise = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just (a -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i)

mp :: Integral a => a -> Maybe Word16
mp :: forall a. Integral a => a -> Maybe Word16
mp a
i | a
i a -> a -> a
forall a. Integral a => a -> a -> a
`rem` a
8 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0 Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
32760 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just (a -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i) | Bool
otherwise = Maybe Word16
forall a. Maybe a
Nothing