diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # kempe
 
+## 0.1.1.3
+
+  * Tweak some RTS flags for faster performance
+  * `lib/gaussian.kmp` has `mult` function
+  * A couple inefficiencies under the hood
+
 ## 0.1.1.2
 
   * Case statements with a single branch are plain and efficient.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Vanessa McHale (c) 2020
+Copyright Vanessa McHale (c) 2020-2021
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -6,9 +6,9 @@
 import qualified Data.ByteString.Lazy      as BSL
 import qualified Data.Text                 as T
 import           Kempe.Asm.Liveness
-import           Kempe.Asm.X86
 import           Kempe.Asm.X86.ControlFlow
 import           Kempe.Asm.X86.Linear
+import           Kempe.Asm.X86.Trans
 import           Kempe.Check.Pattern
 import           Kempe.File
 import           Kempe.IR
@@ -95,6 +95,7 @@
                         , bench "Generate assembly (examples/factorial.kmp)" $ nfIO (writeAsm "examples/factorial.kmp")
                         , bench "Generate assembly (examples/splitmix.kmp)" $ nfIO (writeAsm "examples/splitmix.kmp")
                         , bench "Generate assembly (lib/numbertheory.kmp)" $ nfIO (writeAsm "lib/numbertheory.kmp")
+                        , bench "Generate assembly (lib/gaussian.kmp)" $ nfIO (writeAsm "lib/gaussian.kmp")
                         -- , bench "Generate assembly (lib/rational.kmp)" $ nfIO (writeAsm "lib/rational.kmp")
                         , bench "Object file (examples/factorial.kmp)" $ nfIO (compile "examples/factorial.kmp" "/tmp/factorial.o" False)
                         , bench "Object file (lib/numbertheory.kmp)" $ nfIO (compile "lib/numbertheory.kmp" "/tmp/numbertheory.o" False)
diff --git a/docs/manual.pdf b/docs/manual.pdf
Binary files a/docs/manual.pdf and b/docs/manual.pdf differ
diff --git a/kempe.cabal b/kempe.cabal
--- a/kempe.cabal
+++ b/kempe.cabal
@@ -1,9 +1,9 @@
 cabal-version:   3.0
 name:            kempe
-version:         0.1.1.2
+version:         0.1.1.3
 license:         BSD-3-Clause
 license-file:    LICENSE
-copyright:       Copyright: (c) 2020 Vanessa McHale
+copyright:       Copyright: (c) 2020-2021 Vanessa McHale
 maintainer:      vamchale@gmail.com
 author:          Vanessa McHale
 synopsis:        Kempe compiler
@@ -30,10 +30,6 @@
     type:     git
     location: https://github.com/vmchale/kempe
 
-flag no-par
-    description: Disable concurrent build
-    manual:      True
-
 flag cross
     description: Enable to ease cross-compiling
     default:     False
@@ -54,7 +50,7 @@
         Kempe.Check.Pattern
         Kempe.IR
         Kempe.IR.Opt
-        Kempe.Asm.X86
+        Kempe.Asm.X86.Trans
         Kempe.Asm.X86.ControlFlow
         Kempe.Asm.Liveness
         Kempe.Asm.X86.Linear
@@ -86,26 +82,37 @@
     ghc-options:      -Wall
     build-depends:
         base >=4.9 && <5,
-        array -any,
-        bytestring -any,
+        array,
+        bytestring,
         containers >=0.6.0.0,
-        deepseq -any,
-        text -any,
-        mtl -any,
-        microlens -any,
-        transformers -any,
+        deepseq,
+        text,
+        mtl,
+        microlens,
+        transformers,
         extra >=1.7.4,
         prettyprinter >=1.7.0,
         composition-prelude >=2.0.2.0,
-        microlens-mtl -any,
+        microlens-mtl,
         process >=1.2.3.0,
-        temporary -any
+        temporary
 
-    if !flag(no-par)
-        ghc-options: -j +RTS -A32m -RTS
+    if impl(ghc >=8.0)
+        ghc-options:
+            -Wincomplete-uni-patterns -Wincomplete-record-updates
+            -Wredundant-constraints -Widentities
 
+    if impl(ghc >=8.4)
+        ghc-options: -Wmissing-export-lists
+
+    if impl(ghc >=8.2)
+        ghc-options: -Wcpp-undef
+
+    if impl(ghc >=8.10)
+        ghc-options: -Wunused-packages
+
     if !flag(cross)
-        build-tool-depends: alex:alex -any, happy:happy -any
+        build-tool-depends: alex:alex, happy:happy
 
     if impl(ghc >=8.0)
         ghc-options:
@@ -127,13 +134,13 @@
     other-modules:    Paths_kempe
     autogen-modules:  Paths_kempe
     default-language: Haskell2010
-    ghc-options:      -Wall
+    ghc-options:      -Wall -rtsopts -with-rtsopts=-A4m
     build-depends:
-        base -any,
-        optparse-applicative -any,
-        kempe-modules -any,
+        base,
+        optparse-applicative,
+        kempe-modules,
         prettyprinter >=1.7.0,
-        bytestring -any
+        bytestring
 
     if impl(ghc >=8.0)
         ghc-options:
@@ -162,19 +169,16 @@
     default-language: Haskell2010
     ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall
     build-depends:
-        base -any,
-        kempe-modules -any,
-        tasty -any,
-        tasty-hunit -any,
-        bytestring -any,
+        base,
+        kempe-modules,
+        tasty,
+        tasty-hunit,
+        bytestring,
         prettyprinter >=1.7.0,
-        deepseq -any,
-        tasty-golden -any,
-        text -any,
-        composition-prelude -any
-
-    if !flag(no-par)
-        ghc-options: -j +RTS -A32m -RTS
+        deepseq,
+        tasty-golden,
+        text,
+        composition-prelude
 
     if impl(ghc >=8.0)
         ghc-options:
@@ -198,14 +202,14 @@
     default-language: Haskell2010
     ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall
     build-depends:
-        base -any,
-        kempe-modules -any,
-        tasty -any,
-        bytestring -any,
-        process -any,
-        temporary -any,
-        filepath -any,
-        tasty-golden -any
+        base,
+        kempe-modules,
+        tasty,
+        bytestring,
+        process,
+        temporary,
+        filepath,
+        tasty-golden
 
     if impl(ghc >=8.0)
         ghc-options:
@@ -226,14 +230,14 @@
     main-is:          Bench.hs
     hs-source-dirs:   bench
     default-language: Haskell2010
-    ghc-options:      -Wall
+    ghc-options:      -Wall -rtsopts -with-rtsopts=-A4m
     build-depends:
-        base -any,
-        kempe-modules -any,
-        bytestring -any,
-        criterion -any,
-        prettyprinter -any,
-        text -any
+        base,
+        kempe-modules,
+        bytestring,
+        criterion,
+        prettyprinter,
+        text
 
     if impl(ghc >=8.0)
         ghc-options:
diff --git a/lib/gaussian.kmp b/lib/gaussian.kmp
--- a/lib/gaussian.kmp
+++ b/lib/gaussian.kmp
@@ -1,4 +1,5 @@
 ; Gaussian integers
+import"prelude/fn.kmp"
 
 type Gaussian { Gaussian Int Int }
 
@@ -16,8 +17,18 @@
 add : Gaussian Gaussian -- Gaussian
     =: [ dip(unGaussian) unGaussian grp + dip(+) Gaussian ]
 
+multRe : Gaussian Gaussian -- Int
+       =: [ dip(unGaussian) unGaussian dip(swap) * dip(*) - ]
+
+multIm : Gaussian Gaussian -- Int
+       =: [ dip(unGaussian) unGaussian dip(*) swap dip(*) + ]
+
+mult : Gaussian Gaussian -- Gaussian
+     =: [ dup2 multIm dip(multRe) Gaussian ]
+
 conjugate : Gaussian -- Gaussian
           =: [ unGaussian ~ Gaussian ]
 
 %foreign kabi add
 %foreign kabi conjugate
+%foreign kabi mult
diff --git a/src/Kempe/Asm/Liveness.hs b/src/Kempe/Asm/Liveness.hs
--- a/src/Kempe/Asm/Liveness.hs
+++ b/src/Kempe/Asm/Liveness.hs
@@ -16,8 +16,6 @@
 emptyLiveness :: Liveness
 emptyLiveness = Liveness IS.empty IS.empty
 
--- need: succ for a node
-
 initLiveness :: Copointed p => [p ControlAnn] -> LivenessMap
 initLiveness = IM.fromList . fmap (\asm -> let x = copoint asm in (node x, (x, emptyLiveness)))
 
diff --git a/src/Kempe/Asm/X86.hs b/src/Kempe/Asm/X86.hs
deleted file mode 100644
--- a/src/Kempe/Asm/X86.hs
+++ /dev/null
@@ -1,375 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
--- | Started out trying to implement maximal munch but ended with something
--- "flatter" that works with Kempe IR and my shitty register allocator.
-module Kempe.Asm.X86 ( irToX86
-                     ) where
-
-import           Control.Monad.State.Strict (State, evalState, gets, modify)
-import           Data.Foldable.Ext
-import           Data.List                  (scanl')
-import           Data.Word                  (Word8)
-import           Kempe.AST.Size
-import           Kempe.Asm.X86.Type
-import qualified Kempe.IR.Type              as IR
-
-toAbsReg :: IR.Temp -> AbsReg
-toAbsReg (IR.Temp8 i)   = AllocReg8 i
-toAbsReg (IR.Temp64 i)  = AllocReg64 i
-toAbsReg IR.DataPointer = DataPointer
-
-type WriteM = State IR.WriteSt
-
-irToX86 :: SizeEnv -> IR.WriteSt -> [IR.Stmt] -> [X86 AbsReg ()]
-irToX86 env w = runWriteM w . foldMapA (irEmit env)
-
-nextLabels :: IR.WriteSt -> IR.WriteSt
-nextLabels (IR.WriteSt ls ts) = IR.WriteSt (tail ls) ts
-
-nextInt :: IR.WriteSt -> IR.WriteSt
-nextInt (IR.WriteSt ls ts) = IR.WriteSt ls (tail ts)
-
-getInt :: WriteM Int
-getInt = gets (head . IR.temps) <* modify nextInt
-
-getLabel :: WriteM IR.Label
-getLabel = gets (head . IR.wlabels) <* modify nextLabels
-
-allocTemp64 :: WriteM IR.Temp
-allocTemp64 = IR.Temp64 <$> getInt
-
-allocTemp8 :: WriteM IR.Temp
-allocTemp8 = IR.Temp8 <$> getInt
-
-allocReg64 :: WriteM AbsReg
-allocReg64 = AllocReg64 <$> getInt
-
-allocReg8 :: WriteM AbsReg
-allocReg8 = AllocReg8 <$> getInt
-
-runWriteM :: IR.WriteSt -> WriteM a -> a
-runWriteM = flip evalState
-
--- | This should handle 'MovMem's of divers sizes but for now it just does
--- 1 byte or 8 bytes at a time.
-irEmit :: SizeEnv -> IR.Stmt -> WriteM [X86 AbsReg ()]
-irEmit _ (IR.Jump l) = pure [Jump () l]
-irEmit _ (IR.Labeled l) = pure [Label () l]
-irEmit _ (IR.KCall l) = pure [Call () l]
-irEmit _ IR.Ret = pure [Ret ()]
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () r' (toAbsReg r1), SubRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstInt i)) =
-    pure [ MovAC () (Reg $ toAbsReg r) i ]
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstBool b)) =
-    pure [ MovABool () (Reg $ toAbsReg r) (toByte b) ]
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstTag b)) =
-    pure [ MovACTag () (Reg $ toAbsReg r) b ]
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntTimesIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () r' (toAbsReg r1), ImulRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg8
-    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg8
-    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg8
-    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg8
-    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg64
-    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg64
-    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
-    { r' <- allocReg64
-    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntEqIR (IR.Reg r1) (IR.Reg r2))) = do -- TODO: int eq more general (Reg r1) could be e1 &c.
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Je () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntLtIR (IR.Reg r1) (IR.Reg r2))) = do
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jl () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntGtIR (IR.Reg r1) (IR.Reg r2))) = do
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jg () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntGeqIR (IR.Reg r1) (IR.Reg r2))) = do
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jge () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntNeqIR (IR.Reg r1) (IR.Reg r2))) = do
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jne () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntLeqIR (IR.Reg r1) (IR.Reg r2))) = do
-    { l0 <- getLabel
-    ; l1 <- getLabel
-    ; l2 <- getLabel
-    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jle () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
-    }
-irEmit _ (IR.MovTemp r1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r2) (IR.ConstInt i))) | r1 == r2 = do
-    pure [ SubRC () (toAbsReg r1) i ]
-irEmit _ (IR.MovTemp r1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r2) (IR.ConstInt i))) | r1 == r2 = do
-    pure [ AddRC () (toAbsReg r1) i ]
-irEmit env (IR.CCall (is, []) b) | all (\i -> size' env i <= 8) is && length is <= 6 =
-    pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"]
-irEmit env (IR.CCall (is, [o]) b) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 =
-    pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"]
--- For 128-bit returns we'd have to use rax and rdx
-irEmit env (IR.WrapKCall Cabi (is, [o]) n l) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 = do
-    { let offs = scanl' (+) 0 (fmap (size' env) is)
-    ; let totalSize = sizeStack env is
-    ; let argRegs = [CArg1, CArg2, CArg3, CArg4, CArg5, CArg6]
-    ; pure $ [BSLabel () n, MovRL () DataPointer "kempe_data", NasmMacro0 () "calleesave"] ++ zipWith (\r i-> MovAR () (AddrRCPlus DataPointer i) r) argRegs offs ++ [AddRC () DataPointer totalSize, Call () l, MovRA () CRet (AddrRCMinus DataPointer (size' env o)), NasmMacro0 () "calleerestore", Ret ()] -- TODO: bytes on the stack eh
-    }
-irEmit _ (IR.WrapKCall Kabi (_, _) n l) =
-    pure [BSLabel () n, Call () l, Ret ()]
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstInt8 i)) =
-    pure [ MovACi8 () (Reg $ toAbsReg r) i ]
-    -- see: https://github.com/cirosantilli/x86-assembly-cheat/blob/master/x86-64/movabs.asm for why we don't do this ^ for words
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntXorIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () r' (toAbsReg r1), XorRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () r' (toAbsReg r1), AddRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.WordShiftRIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () r' (toAbsReg r1), ShiftRRR () r' ShiftExponent, MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.WordShiftLIR (IR.Reg r1) (IR.Reg r2))) = do
-    { r' <- allocReg64
-    ; pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () r' (toAbsReg r1), ShiftLRR () r' ShiftExponent, MovAR () (Reg $ toAbsReg r) r' ]
-    }
-irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntModIR (IR.Reg r1) (IR.Reg r2))) =
-    -- QuotRes is rax, so move r1 to rax first
-    pure [ MovRR () QuotRes (toAbsReg r1), Cqo (), IdivR () (toAbsReg r2), MovAR () (Reg $ toAbsReg r) RemRes ]
-irEmit _ (IR.MovTemp r e) = evalE e r
-irEmit _ (IR.MovMem (IR.Reg r) 1 e) = do
-    { r' <- allocTemp8
-    ; put <- evalE e r'
-    ; pure $ put ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')]
-    }
-irEmit _ (IR.MovMem e 8 e') = do
-    { r <- allocTemp64
-    ; r' <- allocTemp64
-    ; eEval <- evalE e r
-    ; e'Eval <- evalE e' r'
-    ; pure (eEval ++ e'Eval ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')])
-    }
-irEmit _ (IR.MovMem e 1 e') = do
-    { r <- allocTemp64
-    ; r' <- allocTemp8
-    ; eEval <- evalE e r
-    ; e'Eval <- evalE e' r'
-    ; pure (eEval ++ e'Eval ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')])
-    }
-irEmit _ (IR.CJump (IR.Mem 1 (IR.Reg r)) l l') =
-    pure [CmpAddrBool () (Reg (toAbsReg r)) 1, Je () l, Jump () l']
-irEmit _ (IR.MJump (IR.Mem 1 (IR.Reg r)) l) =
-    pure [CmpAddrBool () (Reg (toAbsReg r)) 1, Je () l]
-irEmit _ (IR.CJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r) (IR.ConstInt i))) l l') =
-    pure [CmpAddrBool () (AddrRCMinus (toAbsReg r) i) 1, Je () l, Jump () l']
-irEmit _ (IR.MJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r) (IR.ConstInt i))) l) =
-    pure [CmpAddrBool () (AddrRCMinus (toAbsReg r) i) 1, Je () l]
-irEmit _ (IR.CJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r) (IR.ConstInt i))) l l') =
-    pure [CmpAddrBool () (AddrRCPlus (toAbsReg r) i) 1, Je () l, Jump () l']
-irEmit _ (IR.MJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r) (IR.ConstInt i))) l) =
-    pure [CmpAddrBool () (AddrRCPlus (toAbsReg r) i) 1, Je () l]
-irEmit _ (IR.CJump e l l') = do
-    { r <- allocTemp8
-    ; bEval <- evalE e r
-    ; pure (bEval ++ [CmpRegBool () (toAbsReg r) 1, Je () l, Jump () l'])
-    }
-irEmit _ (IR.MJump (IR.EqByte (IR.Mem 1 (IR.Reg r)) (IR.ConstTag b)) l) =
-    pure [CmpAddrBool () (Reg $ toAbsReg r) b, Je () l]
-irEmit _ (IR.MJump (IR.EqByte e0 e1) l) = do
-    { r0 <- allocTemp8
-    ; r1 <- allocTemp8
-    ; placeE0 <- evalE e0 r0
-    ; placeE1 <- evalE e1 r1
-    ; pure $ placeE0 ++ placeE1 ++ [CmpRegReg () (toAbsReg r0) (toAbsReg r1), Je () l]
-    }
-irEmit _ (IR.MJump e l) = do
-    { r <- allocTemp8
-    ; bEval <- evalE e r
-    ; pure (bEval ++ [CmpRegBool () (toAbsReg r) 1, Je () l])
-    }
-
--- | Code to evaluate and put some expression in a chosen 'Temp'
---
--- This more or less conforms to maximal munch.
-evalE :: IR.Exp -> IR.Temp -> WriteM [X86 AbsReg ()]
-evalE (IR.ConstInt i) r                                             = pure [MovRC () (toAbsReg r) i]
-evalE (IR.ConstBool b) r                                            = pure [MovRCBool () (toAbsReg r) (toByte b)]
-evalE (IR.ConstInt8 i) r                                            = pure [MovRCi8 () (toAbsReg r) i]
-evalE (IR.ConstWord w) r                                            = pure [MovRWord () (toAbsReg r) w]
-evalE (IR.ConstTag b) r                                             = pure [MovRCTag () (toAbsReg r) b]
-evalE (IR.Reg r') r                                                 = pure [MovRR () (toAbsReg r) (toAbsReg r')]
-evalE (IR.Mem _ (IR.Reg r1)) r                                      = pure [MovRA () (toAbsReg r) (Reg $ toAbsReg r1) ] -- TODO: sanity check reg/mem access size?
-evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i)) r | r == r1 = pure [SubRC () (toAbsReg r) i]
-evalE (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt i)) r  | r == r1 = pure [AddRC () (toAbsReg r) i]
-evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt 0)) r = pure [MovRR () (toAbsReg r) (toAbsReg r1)]
-evalE (IR.Mem 8 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i))) r =
-    pure [ MovRA () (toAbsReg r) (AddrRCMinus (toAbsReg r1) i) ]
-evalE (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt i))) r =
-    pure [ MovRA () (toAbsReg r) (AddrRCPlus (toAbsReg r1) i) ]
-evalE (IR.Mem _ e) r = do -- don't need to check size b/c we're storing in r
-    { r' <- allocTemp64
-    ; placeE <- evalE e r'
-    ; pure $ placeE ++ [MovRA () (toAbsReg r) (Reg $ toAbsReg r')]
-    }
-evalE (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.Reg r2)) r =
-    pure [ MovRR () (toAbsReg r) (toAbsReg r1), AddRR () (toAbsReg r) (toAbsReg r2) ]
-evalE (IR.ExprIntBinOp IR.IntTimesIR (IR.Reg r1) (IR.Reg r2)) r = do
-    pure [ MovRR () (toAbsReg r) (toAbsReg r1), ImulRR () (toAbsReg r) (toAbsReg r2) ]
-evalE (IR.ExprIntBinOp IR.IntXorIR (IR.Reg r1) (IR.Reg r2)) r = do
-    pure [ MovRR () (toAbsReg r) (toAbsReg r1), XorRR () (toAbsReg r) (toAbsReg r2) ]
-evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i)) r = do
-    pure [ MovRR () (toAbsReg r) (toAbsReg r1), SubRC () (toAbsReg r) i ]
-evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.Reg r2)) r = do
-    pure [ MovRR () (toAbsReg r) (toAbsReg r1), SubRR () (toAbsReg r) (toAbsReg r2) ]
--- FIXME: because my linear register allocator is shitty, I can't keep
--- registers across jumps... so evaluating = or < as an expression in
--- general is hard ?
-evalE (IR.ExprIntBinOp IR.WordShiftLIR (IR.Reg r1) (IR.Reg r2)) r =
-    pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () (toAbsReg r) (toAbsReg r1), ShiftLRR () (toAbsReg r) ShiftExponent ]
-evalE (IR.ExprIntBinOp IR.WordShiftRIR (IR.Reg r1) (IR.Reg r2)) r = -- FIXME: maximal munch use evalE recursively
-    pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () (toAbsReg r) (toAbsReg r1), ShiftRRR () (toAbsReg r) ShiftExponent]
-evalE (IR.ExprIntBinOp IR.WordShiftLIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp8
-    ; placeE0 <- evalE e0 r0
-    ; placeE1 <- evalE e1 r1
-    ; pure $ placeE0 ++ placeE1 ++ [ MovRR () ShiftExponent (toAbsReg r0), MovRR () (toAbsReg r) (toAbsReg r1), ShiftLRR () (toAbsReg r) ShiftExponent ]
-    }
-evalE (IR.ExprIntBinOp IR.WordShiftRIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp8
-    ; placeE0 <- evalE e0 r0
-    ; placeE1 <- evalE e1 r1
-    ; pure $ placeE0 ++ placeE1 ++ [ MovRR () ShiftExponent (toAbsReg r0), MovRR () (toAbsReg r) (toAbsReg r1), ShiftRRR () (toAbsReg r) ShiftExponent ]
-    }
-evalE (IR.ExprIntBinOp IR.IntModIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    -- QuotRes is rax, so move r1 to rax first
-    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), Cqo (), IdivR () (toAbsReg r1), MovRR () (toAbsReg r) RemRes ]
-    }
-evalE (IR.ExprIntBinOp IR.IntDivIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), Cqo (), IdivR () (toAbsReg r1), MovRR () (toAbsReg r) QuotRes ]
-    }
-evalE (IR.ExprIntBinOp IR.WordDivIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), XorRR () RemRes RemRes, DivR () (toAbsReg r1), MovRR () (toAbsReg r) QuotRes ]
-    }
-evalE (IR.ExprIntBinOp IR.WordModIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), XorRR () RemRes RemRes, DivR () (toAbsReg r1), MovRR () (toAbsReg r) RemRes ]
-    }
-evalE (IR.BoolBinOp IR.BoolAnd e0 e1) r = do
-    { r0 <- allocTemp8
-    ; r1 <- allocTemp8
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), AndRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.BoolBinOp IR.BoolOr e0 e1) r = do
-    { r0 <- allocTemp8
-    ; r1 <- allocTemp8
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), OrRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.BoolBinOp IR.BoolXor e0 e1) r = do
-    { r0 <- allocTemp8
-    ; r1 <- allocTemp8
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), XorRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.ExprIntBinOp IR.IntMinusIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), SubRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.ExprIntBinOp IR.IntPlusIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), AddRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.ExprIntBinOp IR.IntTimesIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), ImulRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.ExprIntBinOp IR.IntXorIR e0 e1) r = do
-    { r0 <- allocTemp64
-    ; r1 <- allocTemp64
-    ; placeE <- evalE e0 r0
-    ; placeE' <- evalE e1 r1
-    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), XorRR () (toAbsReg r) (toAbsReg r1) ]
-    }
-evalE (IR.PopcountIR e0) r = do
-    { r' <- allocTemp64
-    ; placeE <- evalE e0 r'
-    ; pure $ placeE ++ [ PopcountRR () (toAbsReg r) (toAbsReg r') ]
-    }
-evalE (IR.IntNegIR e) r = do
-    { placeE <- evalE e r
-    ; pure $ placeE ++ [ NegR () (toAbsReg r) ]
-    }
-
-toByte :: Bool -> Word8
-toByte False = 0
-toByte True  = 1
-
--- I wonder if I could use a hylo.?
diff --git a/src/Kempe/Asm/X86/Trans.hs b/src/Kempe/Asm/X86/Trans.hs
new file mode 100644
--- /dev/null
+++ b/src/Kempe/Asm/X86/Trans.hs
@@ -0,0 +1,375 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Started out trying to implement maximal munch but ended with something
+-- "flatter" that works with Kempe IR and my shitty register allocator.
+module Kempe.Asm.X86.Trans ( irToX86
+                           ) where
+
+import           Control.Monad.State.Strict (State, evalState, gets, modify)
+import           Data.Foldable.Ext
+import           Data.List                  (scanl')
+import           Data.Word                  (Word8)
+import           Kempe.AST.Size
+import           Kempe.Asm.X86.Type
+import qualified Kempe.IR.Type              as IR
+
+toAbsReg :: IR.Temp -> AbsReg
+toAbsReg (IR.Temp8 i)   = AllocReg8 i
+toAbsReg (IR.Temp64 i)  = AllocReg64 i
+toAbsReg IR.DataPointer = DataPointer
+
+type WriteM = State IR.WriteSt
+
+irToX86 :: SizeEnv -> IR.WriteSt -> [IR.Stmt] -> [X86 AbsReg ()]
+irToX86 env w = runWriteM w . foldMapA (irEmit env)
+
+nextLabels :: IR.WriteSt -> IR.WriteSt
+nextLabels (IR.WriteSt ls ts) = IR.WriteSt (tail ls) ts
+
+nextInt :: IR.WriteSt -> IR.WriteSt
+nextInt (IR.WriteSt ls ts) = IR.WriteSt ls (tail ts)
+
+getInt :: WriteM Int
+getInt = gets (head . IR.temps) <* modify nextInt
+
+getLabel :: WriteM IR.Label
+getLabel = gets (head . IR.wlabels) <* modify nextLabels
+
+allocTemp64 :: WriteM IR.Temp
+allocTemp64 = IR.Temp64 <$> getInt
+
+allocTemp8 :: WriteM IR.Temp
+allocTemp8 = IR.Temp8 <$> getInt
+
+allocReg64 :: WriteM AbsReg
+allocReg64 = AllocReg64 <$> getInt
+
+allocReg8 :: WriteM AbsReg
+allocReg8 = AllocReg8 <$> getInt
+
+runWriteM :: IR.WriteSt -> WriteM a -> a
+runWriteM = flip evalState
+
+-- | This should handle 'MovMem's of divers sizes but for now it just does
+-- 1 byte or 8 bytes at a time.
+irEmit :: SizeEnv -> IR.Stmt -> WriteM [X86 AbsReg ()]
+irEmit _ (IR.Jump l) = pure [Jump () l]
+irEmit _ (IR.Labeled l) = pure [Label () l]
+irEmit _ (IR.KCall l) = pure [Call () l]
+irEmit _ IR.Ret = pure [Ret ()]
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () r' (toAbsReg r1), SubRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstInt i)) =
+    pure [ MovAC () (Reg $ toAbsReg r) i ]
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstBool b)) =
+    pure [ MovABool () (Reg $ toAbsReg r) (toByte b) ]
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstTag b)) =
+    pure [ MovACTag () (Reg $ toAbsReg r) b ]
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntTimesIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () r' (toAbsReg r1), ImulRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg8
+    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg8
+    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg8
+    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg8
+    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg64
+    ; pure [ MovRA () r' (AddrRCMinus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg64
+    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCMinus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r0) (IR.ConstInt i)) _ (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt j)))) = do
+    { r' <- allocReg64
+    ; pure [ MovRA () r' (AddrRCPlus (toAbsReg r1) j), MovAR () (AddrRCPlus (toAbsReg r0) i) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntEqIR (IR.Reg r1) (IR.Reg r2))) = do -- TODO: int eq more general (Reg r1) could be e1 &c.
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Je () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntLtIR (IR.Reg r1) (IR.Reg r2))) = do
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jl () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntGtIR (IR.Reg r1) (IR.Reg r2))) = do
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jg () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntGeqIR (IR.Reg r1) (IR.Reg r2))) = do
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jge () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntNeqIR (IR.Reg r1) (IR.Reg r2))) = do
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jne () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntRel IR.IntLeqIR (IR.Reg r1) (IR.Reg r2))) = do
+    { l0 <- getLabel
+    ; l1 <- getLabel
+    ; l2 <- getLabel
+    ; pure [ CmpRegReg () (toAbsReg r1) (toAbsReg r2), Jle () l0, Jump () l1, Label () l0, MovABool () (Reg $ toAbsReg r) 1, Jump () l2, Label () l1, MovABool () (Reg $ toAbsReg r) 0, Label () l2 ]
+    }
+irEmit _ (IR.MovTemp r1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r2) (IR.ConstInt i))) | r1 == r2 = do
+    pure [ SubRC () (toAbsReg r1) i ]
+irEmit _ (IR.MovTemp r1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r2) (IR.ConstInt i))) | r1 == r2 = do
+    pure [ AddRC () (toAbsReg r1) i ]
+irEmit env (IR.CCall (is, []) b) | all (\i -> size' env i <= 8) is && length is <= 6 =
+    pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"]
+irEmit env (IR.CCall (is, [o]) b) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 =
+    pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"]
+-- For 128-bit returns we'd have to use rax and rdx
+irEmit env (IR.WrapKCall Cabi (is, [o]) n l) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 = do
+    { let offs = scanl' (+) 0 (fmap (size' env) is)
+    ; let totalSize = sizeStack env is
+    ; let argRegs = [CArg1, CArg2, CArg3, CArg4, CArg5, CArg6]
+    ; pure $ [BSLabel () n, MovRL () DataPointer "kempe_data", NasmMacro0 () "calleesave"] ++ zipWith (\r i-> MovAR () (AddrRCPlus DataPointer i) r) argRegs offs ++ [AddRC () DataPointer totalSize, Call () l, MovRA () CRet (AddrRCMinus DataPointer (size' env o)), NasmMacro0 () "calleerestore", Ret ()] -- TODO: bytes on the stack eh
+    }
+irEmit _ (IR.WrapKCall Kabi (_, _) n l) =
+    pure [BSLabel () n, Call () l, Ret ()]
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ConstInt8 i)) =
+    pure [ MovACi8 () (Reg $ toAbsReg r) i ]
+    -- see: https://github.com/cirosantilli/x86-assembly-cheat/blob/master/x86-64/movabs.asm for why we don't do this ^ for words
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntXorIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () r' (toAbsReg r1), XorRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () r' (toAbsReg r1), AddRR () r' (toAbsReg r2), MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.WordShiftRIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () r' (toAbsReg r1), ShiftRRR () r' ShiftExponent, MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.WordShiftLIR (IR.Reg r1) (IR.Reg r2))) = do
+    { r' <- allocReg64
+    ; pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () r' (toAbsReg r1), ShiftLRR () r' ShiftExponent, MovAR () (Reg $ toAbsReg r) r' ]
+    }
+irEmit _ (IR.MovMem (IR.Reg r) _ (IR.ExprIntBinOp IR.IntModIR (IR.Reg r1) (IR.Reg r2))) =
+    -- QuotRes is rax, so move r1 to rax first
+    pure [ MovRR () QuotRes (toAbsReg r1), Cqo (), IdivR () (toAbsReg r2), MovAR () (Reg $ toAbsReg r) RemRes ]
+irEmit _ (IR.MovTemp r e) = evalE e r
+irEmit _ (IR.MovMem (IR.Reg r) 1 e) = do
+    { r' <- allocTemp8
+    ; put <- evalE e r'
+    ; pure $ put ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')]
+    }
+irEmit _ (IR.MovMem e 8 e') = do
+    { r <- allocTemp64
+    ; r' <- allocTemp64
+    ; eEval <- evalE e r
+    ; e'Eval <- evalE e' r'
+    ; pure (eEval ++ e'Eval ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')])
+    }
+irEmit _ (IR.MovMem e 1 e') = do
+    { r <- allocTemp64
+    ; r' <- allocTemp8
+    ; eEval <- evalE e r
+    ; e'Eval <- evalE e' r'
+    ; pure (eEval ++ e'Eval ++ [MovAR () (Reg $ toAbsReg r) (toAbsReg r')])
+    }
+irEmit _ (IR.CJump (IR.Mem 1 (IR.Reg r)) l l') =
+    pure [CmpAddrBool () (Reg (toAbsReg r)) 1, Je () l, Jump () l']
+irEmit _ (IR.MJump (IR.Mem 1 (IR.Reg r)) l) =
+    pure [CmpAddrBool () (Reg (toAbsReg r)) 1, Je () l]
+irEmit _ (IR.CJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r) (IR.ConstInt i))) l l') =
+    pure [CmpAddrBool () (AddrRCMinus (toAbsReg r) i) 1, Je () l, Jump () l']
+irEmit _ (IR.MJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r) (IR.ConstInt i))) l) =
+    pure [CmpAddrBool () (AddrRCMinus (toAbsReg r) i) 1, Je () l]
+irEmit _ (IR.CJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r) (IR.ConstInt i))) l l') =
+    pure [CmpAddrBool () (AddrRCPlus (toAbsReg r) i) 1, Je () l, Jump () l']
+irEmit _ (IR.MJump (IR.Mem 1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r) (IR.ConstInt i))) l) =
+    pure [CmpAddrBool () (AddrRCPlus (toAbsReg r) i) 1, Je () l]
+irEmit _ (IR.CJump e l l') = do
+    { r <- allocTemp8
+    ; bEval <- evalE e r
+    ; pure (bEval ++ [CmpRegBool () (toAbsReg r) 1, Je () l, Jump () l'])
+    }
+irEmit _ (IR.MJump (IR.EqByte (IR.Mem 1 (IR.Reg r)) (IR.ConstTag b)) l) =
+    pure [CmpAddrBool () (Reg $ toAbsReg r) b, Je () l]
+irEmit _ (IR.MJump (IR.EqByte e0 e1) l) = do
+    { r0 <- allocTemp8
+    ; r1 <- allocTemp8
+    ; placeE0 <- evalE e0 r0
+    ; placeE1 <- evalE e1 r1
+    ; pure $ placeE0 ++ placeE1 ++ [CmpRegReg () (toAbsReg r0) (toAbsReg r1), Je () l]
+    }
+irEmit _ (IR.MJump e l) = do
+    { r <- allocTemp8
+    ; bEval <- evalE e r
+    ; pure (bEval ++ [CmpRegBool () (toAbsReg r) 1, Je () l])
+    }
+
+-- | Code to evaluate and put some expression in a chosen 'Temp'
+--
+-- This more or less conforms to maximal munch.
+evalE :: IR.Exp -> IR.Temp -> WriteM [X86 AbsReg ()]
+evalE (IR.ConstInt i) r                                             = pure [MovRC () (toAbsReg r) i]
+evalE (IR.ConstBool b) r                                            = pure [MovRCBool () (toAbsReg r) (toByte b)]
+evalE (IR.ConstInt8 i) r                                            = pure [MovRCi8 () (toAbsReg r) i]
+evalE (IR.ConstWord w) r                                            = pure [MovRWord () (toAbsReg r) w]
+evalE (IR.ConstTag b) r                                             = pure [MovRCTag () (toAbsReg r) b]
+evalE (IR.Reg r') r                                                 = pure [MovRR () (toAbsReg r) (toAbsReg r')]
+evalE (IR.Mem _ (IR.Reg r1)) r                                      = pure [MovRA () (toAbsReg r) (Reg $ toAbsReg r1) ] -- TODO: sanity check reg/mem access size?
+evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i)) r | r == r1 = pure [SubRC () (toAbsReg r) i]
+evalE (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt i)) r  | r == r1 = pure [AddRC () (toAbsReg r) i]
+evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt 0)) r = pure [MovRR () (toAbsReg r) (toAbsReg r1)]
+evalE (IR.Mem 8 (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i))) r =
+    pure [ MovRA () (toAbsReg r) (AddrRCMinus (toAbsReg r1) i) ]
+evalE (IR.Mem 8 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.ConstInt i))) r =
+    pure [ MovRA () (toAbsReg r) (AddrRCPlus (toAbsReg r1) i) ]
+evalE (IR.Mem _ e) r = do -- don't need to check size b/c we're storing in r
+    { r' <- allocTemp64
+    ; placeE <- evalE e r'
+    ; pure $ placeE ++ [MovRA () (toAbsReg r) (Reg $ toAbsReg r')]
+    }
+evalE (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r1) (IR.Reg r2)) r =
+    pure [ MovRR () (toAbsReg r) (toAbsReg r1), AddRR () (toAbsReg r) (toAbsReg r2) ]
+evalE (IR.ExprIntBinOp IR.IntTimesIR (IR.Reg r1) (IR.Reg r2)) r = do
+    pure [ MovRR () (toAbsReg r) (toAbsReg r1), ImulRR () (toAbsReg r) (toAbsReg r2) ]
+evalE (IR.ExprIntBinOp IR.IntXorIR (IR.Reg r1) (IR.Reg r2)) r = do
+    pure [ MovRR () (toAbsReg r) (toAbsReg r1), XorRR () (toAbsReg r) (toAbsReg r2) ]
+evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.ConstInt i)) r = do
+    pure [ MovRR () (toAbsReg r) (toAbsReg r1), SubRC () (toAbsReg r) i ]
+evalE (IR.ExprIntBinOp IR.IntMinusIR (IR.Reg r1) (IR.Reg r2)) r = do
+    pure [ MovRR () (toAbsReg r) (toAbsReg r1), SubRR () (toAbsReg r) (toAbsReg r2) ]
+-- FIXME: because my linear register allocator is shitty, I can't keep
+-- registers across jumps... so evaluating = or < as an expression in
+-- general is hard ?
+evalE (IR.ExprIntBinOp IR.WordShiftLIR (IR.Reg r1) (IR.Reg r2)) r =
+    pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () (toAbsReg r) (toAbsReg r1), ShiftLRR () (toAbsReg r) ShiftExponent ]
+evalE (IR.ExprIntBinOp IR.WordShiftRIR (IR.Reg r1) (IR.Reg r2)) r = -- FIXME: maximal munch use evalE recursively
+    pure [ MovRR () ShiftExponent (toAbsReg r2), MovRR () (toAbsReg r) (toAbsReg r1), ShiftRRR () (toAbsReg r) ShiftExponent]
+evalE (IR.ExprIntBinOp IR.WordShiftLIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp8
+    ; placeE0 <- evalE e0 r0
+    ; placeE1 <- evalE e1 r1
+    ; pure $ placeE0 ++ placeE1 ++ [ MovRR () ShiftExponent (toAbsReg r0), MovRR () (toAbsReg r) (toAbsReg r1), ShiftLRR () (toAbsReg r) ShiftExponent ]
+    }
+evalE (IR.ExprIntBinOp IR.WordShiftRIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp8
+    ; placeE0 <- evalE e0 r0
+    ; placeE1 <- evalE e1 r1
+    ; pure $ placeE0 ++ placeE1 ++ [ MovRR () ShiftExponent (toAbsReg r0), MovRR () (toAbsReg r) (toAbsReg r1), ShiftRRR () (toAbsReg r) ShiftExponent ]
+    }
+evalE (IR.ExprIntBinOp IR.IntModIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    -- QuotRes is rax, so move r1 to rax first
+    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), Cqo (), IdivR () (toAbsReg r1), MovRR () (toAbsReg r) RemRes ]
+    }
+evalE (IR.ExprIntBinOp IR.IntDivIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), Cqo (), IdivR () (toAbsReg r1), MovRR () (toAbsReg r) QuotRes ]
+    }
+evalE (IR.ExprIntBinOp IR.WordDivIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), XorRR () RemRes RemRes, DivR () (toAbsReg r1), MovRR () (toAbsReg r) QuotRes ]
+    }
+evalE (IR.ExprIntBinOp IR.WordModIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () QuotRes (toAbsReg r0), XorRR () RemRes RemRes, DivR () (toAbsReg r1), MovRR () (toAbsReg r) RemRes ]
+    }
+evalE (IR.BoolBinOp IR.BoolAnd e0 e1) r = do
+    { r0 <- allocTemp8
+    ; r1 <- allocTemp8
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), AndRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.BoolBinOp IR.BoolOr e0 e1) r = do
+    { r0 <- allocTemp8
+    ; r1 <- allocTemp8
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), OrRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.BoolBinOp IR.BoolXor e0 e1) r = do
+    { r0 <- allocTemp8
+    ; r1 <- allocTemp8
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), XorRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.ExprIntBinOp IR.IntMinusIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), SubRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.ExprIntBinOp IR.IntPlusIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), AddRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.ExprIntBinOp IR.IntTimesIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), ImulRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.ExprIntBinOp IR.IntXorIR e0 e1) r = do
+    { r0 <- allocTemp64
+    ; r1 <- allocTemp64
+    ; placeE <- evalE e0 r0
+    ; placeE' <- evalE e1 r1
+    ; pure $ placeE ++ placeE' ++ [ MovRR () (toAbsReg r) (toAbsReg r0), XorRR () (toAbsReg r) (toAbsReg r1) ]
+    }
+evalE (IR.PopcountIR e0) r = do
+    { r' <- allocTemp64
+    ; placeE <- evalE e0 r'
+    ; pure $ placeE ++ [ PopcountRR () (toAbsReg r) (toAbsReg r') ]
+    }
+evalE (IR.IntNegIR e) r = do
+    { placeE <- evalE e r
+    ; pure $ placeE ++ [ NegR () (toAbsReg r) ]
+    }
+
+toByte :: Bool -> Word8
+toByte False = 0
+toByte True  = 1
+
+-- I wonder if I could use a hylo.?
diff --git a/src/Kempe/Pipeline.hs b/src/Kempe/Pipeline.hs
--- a/src/Kempe/Pipeline.hs
+++ b/src/Kempe/Pipeline.hs
@@ -10,9 +10,9 @@
 import           Kempe.AST
 import           Kempe.AST.Size
 import           Kempe.Asm.Liveness
-import           Kempe.Asm.X86
 import           Kempe.Asm.X86.ControlFlow
 import           Kempe.Asm.X86.Linear
+import           Kempe.Asm.X86.Trans
 import           Kempe.Asm.X86.Type
 import           Kempe.Check.Restrict
 import           Kempe.IR
diff --git a/src/Kempe/TyAssign.hs b/src/Kempe/TyAssign.hs
--- a/src/Kempe/TyAssign.hs
+++ b/src/Kempe/TyAssign.hs
@@ -503,7 +503,7 @@
     pure $ StackType (S.singleton aN) [TyVar () aN] []
 tyPattern PatternInt{} = pure $ StackType S.empty [TyBuiltin () TyInt] []
 tyPattern PatternBool{} = pure $ StackType S.empty [TyBuiltin () TyBool] []
-tyPattern (PatternCons _ tn) = renameStack =<< (flipStackType <$> consLookup (void tn))
+tyPattern (PatternCons _ tn) = renameStack . flipStackType =<< consLookup (void tn)
 
 assignPattern :: Pattern b a -> TypeM () (StackType (), Pattern (StackType ()) (StackType ()))
 assignPattern (PatternInt _ i) =
@@ -512,7 +512,7 @@
 assignPattern (PatternBool _ i) =
     let sTy = StackType S.empty [TyBuiltin () TyBool] []
         in pure (sTy, PatternBool sTy i)
-assignPattern (PatternCons _ tn) = do { ty <- renameStack =<< (flipStackType <$> consLookup (void tn)) ; pure (ty, PatternCons ty (tn $> ty)) }
+assignPattern (PatternCons _ tn) = do { ty <- renameStack . flipStackType =<< consLookup (void tn) ; pure (ty, PatternCons ty (tn $> ty)) }
 assignPattern PatternWildcard{} = do
     aN <- dummyName "a"
     let resType = StackType (S.singleton aN) [TyVar () aN] []
diff --git a/test/golden/gaussian.ir b/test/golden/gaussian.ir
--- a/test/golden/gaussian.ir
+++ b/test/golden/gaussian.ir
@@ -44,14 +44,279 @@
 (ret)
 
 kmp3:
-(movtemp datapointer (- (reg datapointer) (int 25)))
+(movtemp datapointer (- (reg datapointer) (int 17)))
+(call kmp1)
+(movmem (- (reg datapointer) (int 0)) (mem [1] (+ (reg datapointer) (int 17))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 18))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (+ (reg datapointer) (int 19))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (+ (reg datapointer) (int 20))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (+ (reg datapointer) (int 21))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (+ (reg datapointer) (int 22))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (+ (reg datapointer) (int 23))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (+ (reg datapointer) (int 24))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (+ (reg datapointer) (int 25))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (+ (reg datapointer) (int 26))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (+ (reg datapointer) (int 27))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (+ (reg datapointer) (int 28))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (+ (reg datapointer) (int 29))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (+ (reg datapointer) (int 30))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (+ (reg datapointer) (int 31))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (+ (reg datapointer) (int 32))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 33))))
+(movmem (- (reg datapointer) (int 0)) (mem [8] (- (reg datapointer) (int 24))))
+(movmem (- (reg datapointer) (int 24)) (mem [8] (- (reg datapointer) (int 16))))
+(movmem (- (reg datapointer) (int 16)) (mem [8] (- (reg datapointer) (int 0))))
+(movtemp datapointer (- (reg datapointer) (int 8)))
 (movtemp t_5 (mem [8] (reg datapointer)))
-(movmem (reg datapointer) (~ (reg t_5)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_6 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (* (reg t_6) (reg t_5)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_7 (mem [8] (reg datapointer)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_8 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (* (reg t_8) (reg t_7)))
 (movtemp datapointer (+ (reg datapointer) (int 8)))
+(movmem (- (reg datapointer) (int 0)) (mem [8] (+ (reg datapointer) (int 8))))
+(movtemp t_9 (mem [8] (reg datapointer)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_10 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (- (reg t_10) (reg t_9)))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
+(ret)
+
+kmp4:
+(movmem (- (reg datapointer) (int 0)) (mem [1] (- (reg datapointer) (int 17))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 16))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 15))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 14))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 13))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 12))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 11))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 10))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 9))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 8))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 7))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 6))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 5))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 4))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 3))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 2))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 17)) (mem [1] (- (reg datapointer) (int 34))))
+(movmem (- (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 33))))
+(movmem (- (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 32))))
+(movmem (- (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 31))))
+(movmem (- (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 30))))
+(movmem (- (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 29))))
+(movmem (- (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 28))))
+(movmem (- (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 27))))
+(movmem (- (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 26))))
+(movmem (- (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 25))))
+(movmem (- (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 24))))
+(movmem (- (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 23))))
+(movmem (- (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 22))))
+(movmem (- (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 21))))
+(movmem (- (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 20))))
+(movmem (- (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 19))))
+(movmem (- (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 18))))
+(movtemp datapointer (+ (reg datapointer) (int 17)))
+(movmem (- (reg datapointer) (int 0)) (mem [1] (- (reg datapointer) (int 34))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 33))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 32))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 31))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 30))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 29))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 28))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 27))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 26))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 25))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 24))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 23))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 22))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 21))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 20))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 19))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 18))))
+(movmem (- (reg datapointer) (int 34)) (mem [1] (- (reg datapointer) (int 17))))
+(movmem (- (reg datapointer) (int 33)) (mem [1] (- (reg datapointer) (int 16))))
+(movmem (- (reg datapointer) (int 32)) (mem [1] (- (reg datapointer) (int 15))))
+(movmem (- (reg datapointer) (int 31)) (mem [1] (- (reg datapointer) (int 14))))
+(movmem (- (reg datapointer) (int 30)) (mem [1] (- (reg datapointer) (int 13))))
+(movmem (- (reg datapointer) (int 29)) (mem [1] (- (reg datapointer) (int 12))))
+(movmem (- (reg datapointer) (int 28)) (mem [1] (- (reg datapointer) (int 11))))
+(movmem (- (reg datapointer) (int 27)) (mem [1] (- (reg datapointer) (int 10))))
+(movmem (- (reg datapointer) (int 26)) (mem [1] (- (reg datapointer) (int 9))))
+(movmem (- (reg datapointer) (int 25)) (mem [1] (- (reg datapointer) (int 8))))
+(movmem (- (reg datapointer) (int 24)) (mem [1] (- (reg datapointer) (int 7))))
+(movmem (- (reg datapointer) (int 23)) (mem [1] (- (reg datapointer) (int 6))))
+(movmem (- (reg datapointer) (int 22)) (mem [1] (- (reg datapointer) (int 5))))
+(movmem (- (reg datapointer) (int 21)) (mem [1] (- (reg datapointer) (int 4))))
+(movmem (- (reg datapointer) (int 20)) (mem [1] (- (reg datapointer) (int 3))))
+(movmem (- (reg datapointer) (int 19)) (mem [1] (- (reg datapointer) (int 2))))
+(movmem (- (reg datapointer) (int 18)) (mem [1] (- (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 17)) (mem [1] (- (reg datapointer) (int 0))))
+(movmem (- (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 15)) (mem [1] (+ (reg datapointer) (int 2))))
+(movmem (- (reg datapointer) (int 14)) (mem [1] (+ (reg datapointer) (int 3))))
+(movmem (- (reg datapointer) (int 13)) (mem [1] (+ (reg datapointer) (int 4))))
+(movmem (- (reg datapointer) (int 12)) (mem [1] (+ (reg datapointer) (int 5))))
+(movmem (- (reg datapointer) (int 11)) (mem [1] (+ (reg datapointer) (int 6))))
+(movmem (- (reg datapointer) (int 10)) (mem [1] (+ (reg datapointer) (int 7))))
+(movmem (- (reg datapointer) (int 9)) (mem [1] (+ (reg datapointer) (int 8))))
+(movmem (- (reg datapointer) (int 8)) (mem [1] (+ (reg datapointer) (int 9))))
+(movmem (- (reg datapointer) (int 7)) (mem [1] (+ (reg datapointer) (int 10))))
+(movmem (- (reg datapointer) (int 6)) (mem [1] (+ (reg datapointer) (int 11))))
+(movmem (- (reg datapointer) (int 5)) (mem [1] (+ (reg datapointer) (int 12))))
+(movmem (- (reg datapointer) (int 4)) (mem [1] (+ (reg datapointer) (int 13))))
+(movmem (- (reg datapointer) (int 3)) (mem [1] (+ (reg datapointer) (int 14))))
+(movmem (- (reg datapointer) (int 2)) (mem [1] (+ (reg datapointer) (int 15))))
+(movmem (- (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 16))))
+(movmem (- (reg datapointer) (int 0)) (mem [1] (- (reg datapointer) (int 17))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 16))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 15))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 14))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 13))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 12))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 11))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 10))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 9))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 8))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 7))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 6))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 5))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 4))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 3))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 2))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 17)) (mem [1] (- (reg datapointer) (int 34))))
+(movmem (- (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 33))))
+(movmem (- (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 32))))
+(movmem (- (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 31))))
+(movmem (- (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 30))))
+(movmem (- (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 29))))
+(movmem (- (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 28))))
+(movmem (- (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 27))))
+(movmem (- (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 26))))
+(movmem (- (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 25))))
+(movmem (- (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 24))))
+(movmem (- (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 23))))
+(movmem (- (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 22))))
+(movmem (- (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 21))))
+(movmem (- (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 20))))
+(movmem (- (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 19))))
+(movmem (- (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 18))))
+(movtemp datapointer (+ (reg datapointer) (int 17)))
+(movmem (- (reg datapointer) (int 0)) (mem [1] (- (reg datapointer) (int 34))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 33))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (- (reg datapointer) (int 32))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (- (reg datapointer) (int 31))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (- (reg datapointer) (int 30))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (- (reg datapointer) (int 29))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (- (reg datapointer) (int 28))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (- (reg datapointer) (int 27))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (- (reg datapointer) (int 26))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (- (reg datapointer) (int 25))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (- (reg datapointer) (int 24))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (- (reg datapointer) (int 23))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (- (reg datapointer) (int 22))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (- (reg datapointer) (int 21))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (- (reg datapointer) (int 20))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (- (reg datapointer) (int 19))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (- (reg datapointer) (int 18))))
+(movmem (- (reg datapointer) (int 34)) (mem [1] (- (reg datapointer) (int 17))))
+(movmem (- (reg datapointer) (int 33)) (mem [1] (- (reg datapointer) (int 16))))
+(movmem (- (reg datapointer) (int 32)) (mem [1] (- (reg datapointer) (int 15))))
+(movmem (- (reg datapointer) (int 31)) (mem [1] (- (reg datapointer) (int 14))))
+(movmem (- (reg datapointer) (int 30)) (mem [1] (- (reg datapointer) (int 13))))
+(movmem (- (reg datapointer) (int 29)) (mem [1] (- (reg datapointer) (int 12))))
+(movmem (- (reg datapointer) (int 28)) (mem [1] (- (reg datapointer) (int 11))))
+(movmem (- (reg datapointer) (int 27)) (mem [1] (- (reg datapointer) (int 10))))
+(movmem (- (reg datapointer) (int 26)) (mem [1] (- (reg datapointer) (int 9))))
+(movmem (- (reg datapointer) (int 25)) (mem [1] (- (reg datapointer) (int 8))))
+(movmem (- (reg datapointer) (int 24)) (mem [1] (- (reg datapointer) (int 7))))
+(movmem (- (reg datapointer) (int 23)) (mem [1] (- (reg datapointer) (int 6))))
+(movmem (- (reg datapointer) (int 22)) (mem [1] (- (reg datapointer) (int 5))))
+(movmem (- (reg datapointer) (int 21)) (mem [1] (- (reg datapointer) (int 4))))
+(movmem (- (reg datapointer) (int 20)) (mem [1] (- (reg datapointer) (int 3))))
+(movmem (- (reg datapointer) (int 19)) (mem [1] (- (reg datapointer) (int 2))))
+(movmem (- (reg datapointer) (int 18)) (mem [1] (- (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 17)) (mem [1] (- (reg datapointer) (int 0))))
+(movmem (- (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 1))))
+(movmem (- (reg datapointer) (int 15)) (mem [1] (+ (reg datapointer) (int 2))))
+(movmem (- (reg datapointer) (int 14)) (mem [1] (+ (reg datapointer) (int 3))))
+(movmem (- (reg datapointer) (int 13)) (mem [1] (+ (reg datapointer) (int 4))))
+(movmem (- (reg datapointer) (int 12)) (mem [1] (+ (reg datapointer) (int 5))))
+(movmem (- (reg datapointer) (int 11)) (mem [1] (+ (reg datapointer) (int 6))))
+(movmem (- (reg datapointer) (int 10)) (mem [1] (+ (reg datapointer) (int 7))))
+(movmem (- (reg datapointer) (int 9)) (mem [1] (+ (reg datapointer) (int 8))))
+(movmem (- (reg datapointer) (int 8)) (mem [1] (+ (reg datapointer) (int 9))))
+(movmem (- (reg datapointer) (int 7)) (mem [1] (+ (reg datapointer) (int 10))))
+(movmem (- (reg datapointer) (int 6)) (mem [1] (+ (reg datapointer) (int 11))))
+(movmem (- (reg datapointer) (int 5)) (mem [1] (+ (reg datapointer) (int 12))))
+(movmem (- (reg datapointer) (int 4)) (mem [1] (+ (reg datapointer) (int 13))))
+(movmem (- (reg datapointer) (int 3)) (mem [1] (+ (reg datapointer) (int 14))))
+(movmem (- (reg datapointer) (int 2)) (mem [1] (+ (reg datapointer) (int 15))))
+(movmem (- (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 16))))
+(movtemp datapointer (- (reg datapointer) (int 17)))
+(call kmp1)
+(movmem (- (reg datapointer) (int 0)) (mem [1] (+ (reg datapointer) (int 17))))
+(movmem (+ (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 18))))
+(movmem (+ (reg datapointer) (int 2)) (mem [1] (+ (reg datapointer) (int 19))))
+(movmem (+ (reg datapointer) (int 3)) (mem [1] (+ (reg datapointer) (int 20))))
+(movmem (+ (reg datapointer) (int 4)) (mem [1] (+ (reg datapointer) (int 21))))
+(movmem (+ (reg datapointer) (int 5)) (mem [1] (+ (reg datapointer) (int 22))))
+(movmem (+ (reg datapointer) (int 6)) (mem [1] (+ (reg datapointer) (int 23))))
+(movmem (+ (reg datapointer) (int 7)) (mem [1] (+ (reg datapointer) (int 24))))
+(movmem (+ (reg datapointer) (int 8)) (mem [1] (+ (reg datapointer) (int 25))))
+(movmem (+ (reg datapointer) (int 9)) (mem [1] (+ (reg datapointer) (int 26))))
+(movmem (+ (reg datapointer) (int 10)) (mem [1] (+ (reg datapointer) (int 27))))
+(movmem (+ (reg datapointer) (int 11)) (mem [1] (+ (reg datapointer) (int 28))))
+(movmem (+ (reg datapointer) (int 12)) (mem [1] (+ (reg datapointer) (int 29))))
+(movmem (+ (reg datapointer) (int 13)) (mem [1] (+ (reg datapointer) (int 30))))
+(movmem (+ (reg datapointer) (int 14)) (mem [1] (+ (reg datapointer) (int 31))))
+(movmem (+ (reg datapointer) (int 15)) (mem [1] (+ (reg datapointer) (int 32))))
+(movmem (+ (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 33))))
+(movtemp datapointer (- (reg datapointer) (int 16)))
+(movtemp t_11 (mem [8] (reg datapointer)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_12 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (* (reg t_12) (reg t_11)))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
+(movmem (- (reg datapointer) (int 0)) (mem [8] (+ (reg datapointer) (int 8))))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
+(movmem (- (reg datapointer) (int 0)) (mem [8] (- (reg datapointer) (int 16))))
+(movmem (- (reg datapointer) (int 16)) (mem [8] (- (reg datapointer) (int 8))))
+(movmem (- (reg datapointer) (int 8)) (mem [8] (- (reg datapointer) (int 0))))
+(movtemp datapointer (- (reg datapointer) (int 16)))
+(movtemp t_13 (mem [8] (reg datapointer)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_14 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (* (reg t_14) (reg t_13)))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
+(movmem (- (reg datapointer) (int 0)) (mem [8] (+ (reg datapointer) (int 8))))
+(movtemp t_15 (mem [8] (reg datapointer)))
+(movtemp datapointer (- (reg datapointer) (int 8)))
+(movtemp t_16 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (+ (reg t_16) (reg t_15)))
+(call kmp3)
+(movmem (- (reg datapointer) (int 0)) (mem [8] (+ (reg datapointer) (int 8))))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
 (movmem (reg datapointer) (tag 0x0))
 (movtemp datapointer (+ (reg datapointer) (int 1)))
 (ret)
 
+kmp5:
+(movtemp datapointer (- (reg datapointer) (int 25)))
+(movtemp t_17 (mem [8] (reg datapointer)))
+(movmem (reg datapointer) (~ (reg t_17)))
+(movtemp datapointer (+ (reg datapointer) (int 8)))
+(movmem (reg datapointer) (tag 0x0))
+(movtemp datapointer (+ (reg datapointer) (int 1)))
+(ret)
+
 export add {Gaussian_1 Gaussian_1 -- Gaussian_1} kmp2
 
-export conjugate {Gaussian_1 -- Gaussian_1} kmp3
+export conjugate {Gaussian_1 -- Gaussian_1} kmp5
+
+export mult {Gaussian_1 Gaussian_1 -- Gaussian_1} kmp4
