diff --git a/Harpy.hs b/Harpy.hs
new file mode 100644
--- /dev/null
+++ b/Harpy.hs
@@ -0,0 +1,22 @@
+--------------------------------------------------------------------------
+-- |
+-- Module:      Harpy
+-- Copyright:   (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
+-- License:     GPL
+-- 
+-- Maintainer:  {magr,klee}@cs.tu-berlin.de
+-- Stability:   provisional
+-- Portability: portable
+--
+-- Harpy is a library for run-time code generation of x86 machine code.
+--
+-- This is a convenience module which re-exports the modules which are
+-- essential for using Harpy.
+----------------------------------------------------------------------------
+module Harpy(module Harpy.CodeGenMonad,
+             module Harpy.Call,
+             module Harpy.X86Assembler) where
+
+import Harpy.CodeGenMonad
+import Harpy.Call
+import Harpy.X86Assembler
diff --git a/Harpy/Call.hs b/Harpy/Call.hs
--- a/Harpy/Call.hs
+++ b/Harpy/Call.hs
@@ -2,7 +2,7 @@
 
 --------------------------------------------------------------------------
 -- |
--- Module      :  Call
+-- Module      :  Harpy.Call
 -- Copyright   :  (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
 -- License     :  GPL
 -- 
diff --git a/Harpy/CodeGenMonad.hs b/Harpy/CodeGenMonad.hs
--- a/Harpy/CodeGenMonad.hs
+++ b/Harpy/CodeGenMonad.hs
@@ -2,13 +2,13 @@
 
 --------------------------------------------------------------------------
 -- |
--- Module      :  CodeGenMonad
--- Copyright   :  (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
--- License     :  GPL
+-- Module:      Harpy.CodeGenMonad
+-- Copyright:   (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
+-- License:     GPL
 -- 
--- Maintainer  :  {magr,klee}@cs.tu-berlin.de
--- Stability   :  provisional
--- Portability :  portable (but generated code non-portable)
+-- Maintainer:  {magr,klee}@cs.tu-berlin.de
+-- Stability:   provisional
+-- Portability: portable (but generated code non-portable)
 --
 -- Monad for generating x86 machine code at runtime.
 --
@@ -16,20 +16,21 @@
 -- the details of handling code buffers, emitting binary data,
 -- relocation etc.
 --
--- All the code generation functions in module "Harpy.X86CodeGen"
--- live in this monad and use its error reporting facilities as well
--- as the internal state maintained by the monad.  The user state is
--- independent from the internal state and may be used by
--- higher-level code generation libraries to maintain their own
--- state across code generation operations.
+-- All the code generation functions in module "Harpy.X86CodeGen" live
+-- in this monad and use its error reporting facilities as well as the
+-- internal state maintained by the monad.  
 --
---------------------------------------------------------------------------
+-- The library user can pass a user environment and user state through
+-- the monad.  This state is independent from the internal state and
+-- may be used by higher-level code generation libraries to maintain
+-- their own state across code generation operations.
+-- --------------------------------------------------------------------------
 
 module Harpy.CodeGenMonad(
     -- * Types
           CodeGen,
-          RelocKind(..),
           ErrMsg,
+          RelocKind(..),
           Reloc,
           Label,
           FixupKind(..),
@@ -50,6 +51,7 @@
           withEnv,
     -- ** Label management
           newLabel,
+          newNamedLabel,
           setLabel,
           defineLabel,
           (@@),
@@ -78,12 +80,12 @@
 import Control.Monad
 
 import Text.PrettyPrint.HughesPJ
-import Text.Printf
 
-import Data.Word
+import Numeric
+
+import Data.List
 import qualified Data.Map as Map
 import Foreign
-import System.Cmd
 import System.IO
 
 import Control.Monad.Trans
@@ -98,37 +100,53 @@
 -- monad.
 newtype CodeGen e s a = CodeGen ((e, CodeGenEnv) -> (s, CodeGenState) -> IO ((s, CodeGenState), Either ErrMsg a))
 
--- | Configuration of the code generator.
-data CodeGenConfig = CodeGenConfig { codeBufferSize :: Int -- ^ Size of individual code buffer blocks. 
-                                     }
+-- | Configuration of the code generator.  There are currently two
+-- configuration options.  The first is the number fo bytes to use for
+-- allocating code buffers (the first as well as additional buffers
+-- created in calls to 'ensureBufferSize'.  The second allows to pass
+-- in a pre-allocated code buffer and its size.  When this option is
+-- used, Harpy does not perform any code buffer resizing (calls to
+-- 'ensureBufferSize' will be equivalent to calls to
+-- 'checkBufferSize').
+data CodeGenConfig = CodeGenConfig { 
+      codeBufferSize   :: Int,                   -- ^ Size of individual code buffer blocks. 
+      customCodeBuffer :: Maybe (Ptr Word8, Int) -- ^ Code buffer passed in.
+    }
 
 -- | Internal state of the code generator
-data CodeGenState = CodeGenState { buffer :: Ptr Word8,
-                                   bufferList :: [(Ptr Word8, Int)],
-                                   firstBuffer :: Ptr Word8,
-                                   bufferOfs :: Int,
-                                   bufferSize :: Int,
-                                   relocEntries :: [Reloc],
-                                   nextLabel :: Int,
-                                   definedLabels :: Map.Map Int (Ptr Word8, Int),
-                                   pendingFixups :: Map.Map Int [FixupEntry],
-                                   config :: CodeGenConfig}
+data CodeGenState = CodeGenState { 
+      buffer        :: Ptr Word8,                    -- ^ Pointer to current code buffer.
+      bufferList    :: [(Ptr Word8, Int)],           -- ^ List of all other code buffers.
+      firstBuffer   :: Ptr Word8,                    -- ^ Pointer to first buffer.
+      bufferOfs     :: Int,                          -- ^ Current offset into buffer where next instruction will be stored.
+      bufferSize    :: Int,                          -- ^ Size of current buffer.
+      relocEntries  :: [Reloc],                      -- ^ List of all emitted relocation entries.
+      nextLabel     :: Int,                          -- ^ Counter for generating labels.
+      definedLabels :: Map.Map Int (Ptr Word8, Int, String), -- ^ Map of already defined labels.
+      pendingFixups :: Map.Map Int [FixupEntry],     -- ^ Map of labels which have been referenced, but not defined.
+      config        :: CodeGenConfig                 -- ^ Configuration record.
+    }
 
-data FixupKind = Fixup8
-               | Fixup16
-               | Fixup32
-               | Fixup32Absolute
-               deriving (Show)
+data FixupEntry = FixupEntry { 
+      fueBuffer :: Ptr Word8,
+      fueOfs    :: Int,
+      fueKind   :: FixupKind 
+    }
 
-data FixupEntry = FixupEntry { fueBuffer :: Ptr Word8,
-                               fueOfs :: Int,
-                               fueKind :: FixupKind }
+-- | Kind of a fixup entry.  When a label is emitted with
+-- 'defineLabel', all prior references to this label must be fixed
+-- up.  This data type tells how to perform the fixup operation.
+data FixupKind = Fixup8          -- ^ 8-bit relative reference
+               | Fixup16         -- ^ 16-bit relative reference
+               | Fixup32         -- ^ 32-bit relative reference
+               | Fixup32Absolute -- ^ 32-bit absolute reference
+               deriving (Show)
 
 data CodeGenEnv = CodeGenEnv { tailContext :: Bool }
    deriving (Show)
 
 -- | Kind of relocation, for example PC-relative
-data RelocKind = RelocPCRel -- ^ PC-relative relocation
+data RelocKind = RelocPCRel    -- ^ PC-relative relocation
                | RelocAbsolute -- ^ Absolute address
    deriving (Show)
 
@@ -143,7 +161,7 @@
    deriving (Show)
 
 -- | Label
-data Label = Label Int
+data Label = Label Int String
 
 unCg :: CodeGen e s a -> ((e, CodeGenEnv) -> (s, CodeGenState) -> IO ((s, CodeGenState), Either ErrMsg a))
 unCg (CodeGen a) = a
@@ -153,11 +171,13 @@
     fail err = cgFail err
     m >>= k = cgBind m k
 
--- {-# INLINE cgReturn #-}
+cgReturn :: a -> CodeGen e s a
 cgReturn x = CodeGen (\_env state -> return (state, Right x))
--- {-# INLINE cgFail #-}
+
+cgFail :: String -> CodeGen e s a
 cgFail err = CodeGen (\_env state -> return (state, Left (text err)))
--- {-# INLINE cgBind #-}
+
+cgBind :: CodeGen e s a -> (a -> CodeGen e s a1) -> CodeGen e s a1
 cgBind m k = CodeGen (\env state -> 
                do r1 <- unCg m env state
                   case r1 of
@@ -183,29 +203,44 @@
                                    pendingFixups = Map.empty,
                                    config = defaultCodeGenConfig}
 
+-- | Default code generation configuration.  The code buffer size is
+-- set to 4KB, and code buffer management is automatic.  This value is
+-- intended to be used with record update syntax, for example:
+--
+-- >  runCodeGenWithConfig ... defaultCodeGenConfig{codeBufferSize = 128} ...
 defaultCodeGenConfig :: CodeGenConfig
-defaultCodeGenConfig = CodeGenConfig { codeBufferSize = defaultCodeBufferSize }
+defaultCodeGenConfig = CodeGenConfig { codeBufferSize = defaultCodeBufferSize,
+                                       customCodeBuffer = Nothing }
 
 defaultCodeBufferSize :: Int
-defaultCodeBufferSize = 128
+defaultCodeBufferSize = 4096
 
--- | Execute code generation, given a user environment and state.
--- The result is a tuple of the resulting user state and either an
--- error message (when code generation failed) or the result of the
--- code generation.
+-- | Execute code generation, given a user environment and state.  The
+-- result is a tuple of the resulting user state and either an error
+-- message (when code generation failed) or the result of the code
+-- generation.  This function runs 'runCodeGenWithConfig' with a
+-- sensible default configuration.
 runCodeGen :: CodeGen e s a -> e -> s -> IO (s, Either ErrMsg a)
 runCodeGen cg uenv ustate =
     runCodeGenWithConfig cg uenv ustate defaultCodeGenConfig
 
+-- | Like 'runCodeGen', but allows more control over the code
+-- generation process.  In addition to a code generator and a user
+-- environment and state, a code generation configuration must be
+-- provided.  A code generation configuration allows control over the
+-- allocation of code buffers, for example.
 runCodeGenWithConfig :: CodeGen e s a -> e -> s -> CodeGenConfig -> IO (s, Either ErrMsg a)
 runCodeGenWithConfig (CodeGen cg) uenv ustate conf =
-    do let initSize = codeBufferSize conf
-       arr <- mallocBytes initSize
+    do (buf, sze) <- case customCodeBuffer conf of
+                       Nothing -> do let initSize = codeBufferSize conf
+                                     arr <- mallocBytes initSize
+                                     return (arr, initSize)
+                       Just (buf, sze) -> return (buf, sze)
        let env = CodeGenEnv {tailContext = True}
-       let state = emptyCodeGenState{buffer = arr,
+       let state = emptyCodeGenState{buffer = buf,
                                      bufferList = [],
-                                     firstBuffer = arr,
-                                     bufferSize = initSize,
+                                     firstBuffer = buf,
+                                     bufferSize = sze,
                                      config = conf}
        ((ustate', _), res) <- cg (uenv, env) (ustate, state)
        return (ustate', res)
@@ -215,6 +250,9 @@
 -- whenever it cannot be guaranteed that the code buffer is large
 -- enough to hold all the generated code.  Lets the code generation
 -- monad fail when the buffer overflows.
+--
+-- /Note:/ Starting with version 0.4, Harpy automatically checks for
+-- buffer overflow, so you do not need to call this function anymore.
 checkBufferSize :: Int -> CodeGen e s ()
 checkBufferSize needed =
     do state <- getInternalState
@@ -226,57 +264,63 @@
                             int (bufferSize state) <> text ")"))
 
 -- | Make sure that the code buffer has room for at least the given
--- number of bytes.  This should be called by code generators
--- whenever it cannot be guaranteed that the code buffer is large
--- enough to hold all the generated code.  Creates a new buffer and
--- places a jump to the new buffer when there is not sufficient space
--- available
+-- number of bytes.  This should be called by code generators whenever
+-- it cannot be guaranteed that the code buffer is large enough to
+-- hold all the generated code.  Creates a new buffer and places a
+-- jump to the new buffer when there is not sufficient space
+-- available.  When code generation was invoked with a pre-defined
+-- code buffer, code generation is aborted on overflow.
+--
+-- /Note:/ Starting with version 0.4, Harpy automatically checks for
+-- buffer overflow, so you do not need to call this function anymore.
 ensureBufferSize :: Int -> CodeGen e s ()
 ensureBufferSize needed =
     do state <- getInternalState
-       unless (bufferOfs state + needed + 5 <= bufferSize state)
-              (do let incrSize = max (needed + 16) 
-                                     (codeBufferSize (config state))
-                  arr <- liftIO $ mallocBytes incrSize
-                  ofs <- getCodeOffset
-                  let buf = buffer state
-                      disp :: Int
-                      disp = arr `minusPtr` (buf `plusPtr` ofs) - 5
-                  emit8 0xe9
-                  emit32 (fromIntegral disp)
-                  st <- getInternalState
-                  setInternalState st{buffer = arr, bufferList = bufferList st ++ [(buffer st, bufferOfs st)], bufferOfs = 0})
+       case (customCodeBuffer (config state)) of
+         Nothing ->
+             unless (bufferOfs state + needed + 5 <= bufferSize state)
+                        (do let incrSize = max (needed + 16) (codeBufferSize (config state))
+                            arr <- liftIO $ mallocBytes incrSize
+                            ofs <- getCodeOffset
+                            let buf = buffer state
+                                disp :: Int
+                                disp = arr `minusPtr` (buf `plusPtr` ofs) - 5
+                            emit8 0xe9    -- FIXME: Machine dependent!
+                            emit32 (fromIntegral disp)
+                            st <- getInternalState
+                            setInternalState st{buffer = arr, bufferList = bufferList st ++ [(buffer st, bufferOfs st)], bufferOfs = 0})
+         Just (_, _) -> checkBufferSize needed
 
 -- | Return a pointer to the beginning of the first code buffer, which
 -- is normally the entry point to the generated code.
 getEntryPoint :: CodeGen e s (Ptr Word8)
 getEntryPoint =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       return $ ((ustate, state), Right (firstBuffer state)))
 
 -- | Return the current offset in the code buffer, e.g. the offset
 -- at which the next instruction will be emitted.
 getCodeOffset :: CodeGen e s Int
 getCodeOffset =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       return $ ((ustate, state), Right (bufferOfs state)))
 
 -- | Set the user state to the given value. 
 setState :: s -> CodeGen e s ()
 setState st =
-    CodeGen (\ env (_, state) -> 
+    CodeGen (\ _ (_, state) -> 
       return $ ((st, state), Right ()))
 
 -- | Return the current user state.
 getState :: CodeGen e s s
 getState =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       return $ ((ustate, state), Right (ustate)))
 
 -- | Return the current user environment.
 getEnv :: CodeGen e s e
 getEnv =
-    CodeGen (\ (uenv, env) state -> 
+    CodeGen (\ (uenv, _) state -> 
       return $ (state, Right uenv))
 
 -- | Set the environment to the given value and execute the given
@@ -289,20 +333,19 @@
 -- | Set the user state to the given value. 
 setInternalState :: CodeGenState -> CodeGen e s ()
 setInternalState st =
-    CodeGen (\ env (ustate, _) -> 
+    CodeGen (\ _ (ustate, _) -> 
       return $ ((ustate, st), Right ()))
 
 -- | Return the current user state.
 getInternalState :: CodeGen e s CodeGenState
 getInternalState =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       return $ ((ustate, state), Right (state)))
 
 -- | Return the pointer to the start of the code buffer.
--- {-# INLINE getBasePtr #-}
 getBasePtr :: CodeGen e s (Ptr Word8)
 getBasePtr =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       return $ ((ustate, state), Right (buffer state)))
 
 -- | Return a list of all code buffers and their respective size 
@@ -312,14 +355,24 @@
                        return $ bufferList st ++ [(buffer st, bufferOfs st)]
 
 -- | Generate a new label to be used with the label operations
--- 'emitRelocInfo', 'emitFixup' and 'defineLabel'.
+-- 'emitFixup' and 'defineLabel'.
 newLabel :: CodeGen e s Label
 newLabel =
     do state <- getInternalState
        let lab = nextLabel state
        setInternalState state{nextLabel = lab + 1}
-       return (Label lab)
+       return (Label lab "")
 
+-- | Generate a new label to be used with the label operations
+-- 'emitFixup' and 'defineLabel'.  The given name is used for
+-- diagnostic purposes, and will appear in the disassembly.
+newNamedLabel :: String -> CodeGen e s Label
+newNamedLabel name =
+    do state <- getInternalState
+       let lab = nextLabel state
+       setInternalState state{nextLabel = lab + 1}
+       return (Label lab name)
+
 -- | Generate a new label and define it at once
 setLabel :: CodeGen e s Label
 setLabel =
@@ -330,58 +383,52 @@
 -- | Emit a relocation entry for the given offset, relocation kind 
 -- and target address.
 emitRelocInfo :: Int -> RelocKind -> FunPtr a -> CodeGen e s ()
-emitRelocInfo ofs kind addr = 
-    CodeGen (\ env (ustate, state) -> 
-      do let newState = state{relocEntries =
+emitRelocInfo ofs knd addr = 
+    do state <- getInternalState
+       setInternalState state{relocEntries =
                               Reloc{offset = ofs, 
-                                    kind = kind,
+                                    kind = knd,
                                     address = castFunPtr addr} : 
                               (relocEntries state)}
-         return $ ((ustate, newState), Right ()))
 
 -- | Emit a byte value to the code buffer. 
--- {-# INLINE emit8 #-}
 emit8 :: Word8 -> CodeGen e s ()
 emit8 op = 
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       do let buf = buffer state
              ptr = bufferOfs state
          pokeByteOff buf ptr op
          return $ ((ustate, state{bufferOfs = ptr + 1}), Right ()))
 
 -- | Store a byte value at the given offset into the code buffer.
--- {-# INLINE emit8At #-}
 emit8At :: Int -> Word8 -> CodeGen e s ()
 emit8At pos op = 
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       do let buf = buffer state
          pokeByteOff buf pos op
          return $ ((ustate, state), Right ()))
 
 -- | Return the byte value at the given offset in the code buffer.
--- {-# INLINE peek8At #-}
 peek8At :: Int -> CodeGen e s Word8
 peek8At pos =
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       do let buf = buffer state
          b <- peekByteOff buf pos
          return $ ((ustate, state), Right b))
 
 -- | Like 'emit8', but for a 32-bit value.
--- {-# INLINE emit32 #-}
 emit32 :: Word32 -> CodeGen e s ()
 emit32 op = 
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       do let buf = buffer state
              ptr = bufferOfs state
          pokeByteOff buf ptr op
          return $ ((ustate, state{bufferOfs = ptr + 4}), Right ()))
 
 -- | Like 'emit8At', but for a 32-bit value.
--- {-# INLINE emit32At #-}
 emit32At :: Int -> Word32 -> CodeGen e s ()
 emit32At pos op = 
-    CodeGen (\ env (ustate, state) -> 
+    CodeGen (\ _ (ustate, state) -> 
       do let buf = buffer state
          pokeByteOff buf pos op
          return $ ((ustate, state), Right ()))
@@ -389,19 +436,23 @@
 -- | Emit a label at the current offset in the code buffer.  All
 -- references to the label will be relocated to this offset.
 defineLabel :: Label -> CodeGen e s ()
-defineLabel (Label lab) = 
+defineLabel (Label lab name) = 
     do state <- getInternalState
+       case Map.lookup lab (definedLabels state) of
+         Just _ -> failCodeGen $ text "duplicate definition of label" <+> 
+                     int lab
+         _ -> return ()
        case Map.lookup lab (pendingFixups state) of
          Just fixups -> do mapM_ (performFixup (buffer state) (bufferOfs state)) fixups
                            setInternalState state{pendingFixups = Map.delete lab (pendingFixups state)}
          Nothing -> return ()
-       state <- getInternalState
-       setInternalState state{definedLabels = Map.insert lab (buffer state, bufferOfs state) (definedLabels state)}
+       state1 <- getInternalState
+       setInternalState state1{definedLabels = Map.insert lab (buffer state1, bufferOfs state1, name) (definedLabels state1)}
 
 performFixup :: Ptr Word8 -> Int -> FixupEntry -> CodeGen e s ()
-performFixup labBuf labOfs (FixupEntry{fueBuffer = buf, fueOfs = ofs, fueKind = kind}) =
+performFixup labBuf labOfs (FixupEntry{fueBuffer = buf, fueOfs = ofs, fueKind = knd}) =
     do let diff = (labBuf `plusPtr` labOfs) `minusPtr` (buf `plusPtr` (ofs + 4))
-       liftIO $ case kind of
+       liftIO $ case knd of
                   Fixup8 -> pokeByteOff buf ofs (fromIntegral diff :: Word8)
                   Fixup16 -> pokeByteOff buf ofs (fromIntegral diff :: Word16)
                   Fixup32 -> pokeByteOff buf ofs (fromIntegral diff :: Word32)
@@ -409,6 +460,11 @@
        return ()
 
 
+-- | This operator gives neat syntax for defining labels.  When @l@ is a label, the code
+--
+-- > l @@ mov eax ebx
+--
+-- associates the label l with the following @mov@ instruction.
 (@@) :: Label -> CodeGen e s a -> CodeGen e s a
 (@@) lab gen = do defineLabel lab
                   gen
@@ -419,40 +475,72 @@
 -- be patched to target the address associated with this label when
 -- it is defined later.
 emitFixup :: Label -> Int -> FixupKind -> CodeGen e s ()
-emitFixup (Label lab) ofs kind = 
+emitFixup (Label lab _) ofs knd = 
     do state <- getInternalState 
        let base = buffer state
            ptr = bufferOfs state
        case Map.lookup lab (definedLabels state) of
-         Just (labBuf, labOfs) -> performFixup labBuf labOfs (FixupEntry{fueBuffer = base,
-                                                                         fueOfs = ptr + ofs,
-                                                                         fueKind = kind})
+         Just (labBuf, labOfs, _) -> performFixup labBuf labOfs (FixupEntry{fueBuffer = base,
+                                                                            fueOfs = ptr + ofs,
+                                                                            fueKind = knd})
          Nothing -> setInternalState state{pendingFixups = Map.insertWith (++) lab [FixupEntry{fueBuffer = base,
                                                                                           fueOfs = ptr + ofs,
-                                                                                          fueKind = kind}]
+                                                                                          fueKind = knd}]
                                                                                           (pendingFixups state)}
 
 -- | Return the address of a label, fail if the label is not yet defined.
 labelAddress :: Label -> CodeGen e s (Ptr a)
-labelAddress (Label lab) = do
+labelAddress (Label lab name) = do
   state <- getInternalState
   case Map.lookup lab (definedLabels state) of
-    Just (labBuf, labOfs) -> return $ plusPtr labBuf labOfs
-    Nothing -> fail $ "Label " ++ show lab ++ " not yet defined"
+    Just (labBuf, labOfs, _) -> return $ plusPtr labBuf labOfs
+    Nothing -> fail $ "Label " ++ show lab ++ "(" ++ name ++ ") not yet defined"
 
 
--- | Disassemble all code buffers.
+-- | Disassemble all code buffers.  The result is a list of
+-- disassembled instructions which can be converted to strings using
+-- the 'Dis.showIntel' or 'Dis.showAtt' functions from module
+-- "Harpy.X86Disassembler".
 disassemble :: CodeGen e s [Dis.Instruction]
 disassemble = do
   s <- getInternalState
   let buffers = bufferList s
-  r <- mapM (\ (buffer, length) -> do
-             r <- liftIO $ Dis.disassembleBlock buffer length
+  r <- mapM (\ (buff, len) -> do
+             r <- liftIO $ Dis.disassembleBlock buff len
              case r of
                     Left err -> cgFail $ show err
                     Right instr -> return instr
             ) $ buffers ++ [(buffer s, bufferOfs s)]
-  return $ concat r
+  r' <- insertLabels (concat r)
+  return r'
+ where insertLabels :: [Dis.Instruction] -> CodeGen e s [Dis.Instruction]
+       insertLabels = liftM concat . mapM ins
+       ins :: Dis.Instruction -> CodeGen e s [Dis.Instruction]
+       ins i@(Dis.BadInstruction{}) = return [i]
+       ins i@(Dis.PseudoInstruction{}) = return [i]
+       ins i@(Dis.Instruction{Dis.address = addr}) =
+           do state <- getInternalState
+              let labs = Map.toList (definedLabels state)
+                  lab = find (\ (_, (buf, ofs, _)) -> fromIntegral (ptrToWordPtr (buf `plusPtr` ofs)) == addr) labs
+              case lab of
+                Nothing -> return [i]
+                Just (l, (buf, ofs, name)) -> return [Dis.PseudoInstruction addr
+                                                         (case name of
+                                                           "" ->
+                                                               "label " ++ show l ++ 
+                                                                " [" ++ 
+                                                                hex32 (fromIntegral (ptrToWordPtr (buf `plusPtr` ofs))) ++ 
+                                                                "]"
+                                                           _ -> name ++ ": [" ++ 
+                                                                  hex32 (fromIntegral (ptrToWordPtr (buf `plusPtr` ofs))) ++ 
+                                                                  "]"), 
+                                                            i]
+       hex32 :: Int -> String
+       hex32 i =
+              let w :: Word32
+                  w = fromIntegral i
+                  s = showHex w ""
+              in take (8 - length s) (repeat '0') ++ s
 
 #ifndef __HADDOCK__
 
@@ -460,7 +548,7 @@
 callDecl ns qt =  do
     t0 <- qt
     let (tvars, cxt, t) = case t0 of
-                         ForallT vs c t -> (vs, c, t)
+                         ForallT vs c t' -> (vs, c, t')
                          _ -> ([], [], t0)
     let name = mkName ns
     let funptr = AppT (ConT $ mkName "FunPtr") t
diff --git a/Harpy/X86Assembler.hs b/Harpy/X86Assembler.hs
new file mode 100644
--- /dev/null
+++ b/Harpy/X86Assembler.hs
@@ -0,0 +1,3746 @@
+--------------------------------------------------------------------------
+-- |
+-- Module      :  Harpy.X86Assembler
+-- Copyright   :  (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
+-- License     :  GPL
+-- 
+-- Maintainer  :  {magr,klee}@cs.tu-berlin.de
+-- Stability   :  provisional
+-- Portability :  non-portable
+--
+-- A type class based layer on top of X86CodeGen
+-- which determines the addressing modes from the types of the
+-- operands.
+--------------------------------------------------------------------------
+module Harpy.X86Assembler where
+
+import Harpy.X86CodeGen
+import Harpy.CodeGenMonad
+import Data.Word
+import Foreign.Ptr
+
+import qualified Text.PrettyPrint.HughesPJ as PP
+
+
+-- address modes used in this module:
+
+-- Word8/16/32	   	     immediate values
+-- Reg8/16/32	             register
+-- Addr Word32		     absolut
+-- Ind Reg32		     register indirect
+-- (Disp, Reg32)		     register indirect with displacement
+-- (Reg32, Reg32, Scale)	     (base, index, scale), effective address is (base + index * scale)
+-- (Disp, Reg32, Scale)	     (disp, index, scale), effective address is (disp + index * scale)
+-- (Disp, Reg32, Reg32, Scale)  (base, index, scale) + displacement (only ebp is allowed as base register)
+-- Label                        not-yet-specified label
+
+onlyEbp = failCodeGen (PP.text "only epb is allowed as base register for disp/base/index/scale addressing")
+onlyCl  = failCodeGen (PP.text "only cl is allowed as shift count")
+
+
+-- x86 Registers
+
+newtype Reg8 = Reg8 Word8
+al, cl, dl, bl, ah, ch, dh, bh :: Reg8
+
+al = Reg8 0
+cl = Reg8 1
+dl = Reg8 2
+bl = Reg8 3
+ah = Reg8 4
+ch = Reg8 5
+dh = Reg8 6
+bh = Reg8 7
+
+newtype Reg16 = Reg16 Word8
+ax, cx, dx, bx, sp, bp, si, di :: Reg16
+
+ax = Reg16 0
+cx = Reg16 1
+dx = Reg16 2
+bx = Reg16 3
+sp = Reg16 4
+bp = Reg16 5
+si = Reg16 6
+di = Reg16 7
+
+newtype Reg32 = Reg32 Word8 deriving Eq
+eax, ecx, edx, ebx, esp, ebp, esi, edi :: Reg32
+
+eax = Reg32 0
+ecx = Reg32 1
+edx = Reg32 2
+ebx = Reg32 3
+esp = Reg32 4
+ebp = Reg32 5
+esi = Reg32 6
+edi = Reg32 7
+
+newtype XMMReg = XMMReg Word8
+
+xmm0 = XMMReg 0
+xmm1 = XMMReg 1
+xmm2 = XMMReg 2
+xmm3 = XMMReg 3
+xmm4 = XMMReg 4
+xmm5 = XMMReg 5
+xmm6 = XMMReg 6
+xmm7 = XMMReg 7
+
+-- TODO: instances for other registers
+
+instance Show Reg32 where
+ show (Reg32 0) = "eax"
+ show (Reg32 1) = "ecx"
+ show (Reg32 2) = "edx"
+ show (Reg32 3) = "ebx"
+ show (Reg32 4) = "esp"
+ show (Reg32 5) = "ebp"
+ show (Reg32 6) = "esi"
+ show (Reg32 7) = "edi"
+
+-- memory addresses
+
+newtype Addr  = Addr Word32
+newtype Ind   = Ind Reg32
+newtype Disp  = Disp Word32
+
+data    Scale = S1 | S2 | S4 | S8
+
+scaleToShift :: Scale -> Word8
+scaleToShift S1 = 0
+scaleToShift S2 = 1
+scaleToShift S4 = 2
+scaleToShift S8 = 3
+
+newtype FPReg = FPReg Word8
+
+data FPTopReg = FPTopReg
+
+fpTop = FPTopReg
+
+fp0 = FPReg 0
+fp1 = FPReg 1
+fp2 = FPReg 2
+fp3 = FPReg 3
+fp4 = FPReg 4
+fp5 = FPReg 5
+fp6 = FPReg 6
+fp7 = FPReg 7
+
+-- int 3
+
+breakpoint = ensureBufferSize x86_max_instruction_bytes >> x86_breakpoint
+
+
+-- clear direction flag
+
+cld = ensureBufferSize x86_max_instruction_bytes >> x86_cld
+
+
+-- store string
+
+stosb = ensureBufferSize x86_max_instruction_bytes >> x86_stosb
+stosl = ensureBufferSize x86_max_instruction_bytes >> x86_stosl
+stosd = ensureBufferSize x86_max_instruction_bytes >> x86_stosd
+
+
+-- move string
+
+movsb = ensureBufferSize x86_max_instruction_bytes >> x86_movsb
+movsl = ensureBufferSize x86_max_instruction_bytes >> x86_movsl
+--movsd = ensureBufferSize x86_max_instruction_bytes >> x86_movsd
+
+
+-- read time stamp counter
+
+rdtsc = ensureBufferSize x86_max_instruction_bytes >> x86_rdtsc
+
+
+-- compare and exchange
+
+class Cmpxchg a b where
+  cmpxchg :: a -> b -> CodeGen e s ()
+
+instance Cmpxchg Reg32 Reg32 where
+  cmpxchg (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmpxchg_reg_reg dest source
+
+instance Cmpxchg Addr Reg32 where
+  cmpxchg (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmpxchg_mem_reg dest source
+
+instance Cmpxchg (Disp, Reg32) Reg32 where
+  cmpxchg (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmpxchg_membase_reg dest disp source
+
+instance Cmpxchg Ind Reg32 where
+  cmpxchg (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmpxchg_membase_reg dest 0 source
+
+
+
+-- exchange memory/register with register
+
+class Xchg a b where
+  xchg :: a -> b -> CodeGen e s ()
+
+instance Xchg Reg8 Reg8 where
+  xchg (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_reg_reg dest source 1
+
+instance Xchg Reg32 Reg32 where
+  xchg (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_reg_reg dest source 4
+
+instance Xchg Addr Reg8 where
+  xchg (Addr dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_mem_reg dest source 1
+
+instance Xchg Addr Reg32 where
+  xchg (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_mem_reg dest source 4
+
+instance Xchg (Disp, Reg32) Reg8 where
+  xchg (Disp disp, Reg32 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_membase_reg dest disp source 1
+
+instance Xchg Ind Reg8 where
+  xchg (Ind (Reg32 dest)) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_membase_reg dest 0 source 1
+
+instance Xchg (Disp, Reg32) Reg32 where
+  xchg (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_membase_reg dest disp source 4
+
+instance Xchg Ind Reg32 where
+  xchg (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xchg_membase_reg dest 0 source 4
+
+
+-- exchange and add
+
+class Xadd a b where
+  xadd :: a -> b -> CodeGen e s ()
+
+instance Xadd Reg8 Reg8 where
+  xadd (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_reg_reg dest source 1
+
+instance Xadd Reg32 Reg32 where
+  xadd (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_reg_reg dest source 4
+
+instance Xadd Addr Reg8 where
+  xadd (Addr dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_mem_reg dest source 1
+
+instance Xadd Addr Reg32 where
+  xadd (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_mem_reg dest source 4
+
+instance Xadd (Disp, Reg32) Reg8 where
+  xadd (Disp disp, Reg32 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_membase_reg dest disp source 1
+
+instance Xadd Ind Reg8 where
+  xadd (Ind (Reg32 dest)) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_xadd_membase_reg dest 0 source 1
+
+instance Xadd (Disp, Reg32) Reg32 where
+  xadd (Disp disp, Reg32 dest) (Reg32 source) =  ensureBufferSize x86_max_instruction_bytes >> x86_xadd_membase_reg dest disp source 4
+
+instance Xadd Ind Reg32 where
+  xadd (Ind (Reg32 dest)) (Reg32 source) =  ensureBufferSize x86_max_instruction_bytes >> x86_xadd_membase_reg dest 0 source 4
+
+
+-- Increment by 1
+
+class Inc a where
+  inc :: a -> CodeGen e s ()
+
+instance Inc Addr where
+  inc (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_inc_mem dest
+
+instance Inc (Disp, Reg32) where
+  inc (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_inc_membase dest disp
+
+instance Inc Ind where
+  inc (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_inc_membase dest 0
+
+instance Inc Reg32 where
+  inc (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_inc_reg dest
+
+
+-- Decrement by 1
+
+class Dec a where
+  dec :: a -> CodeGen e s ()
+
+instance Dec Addr where
+  dec (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_dec_mem dest
+
+instance Dec (Disp, Reg32) where
+  dec (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_dec_membase dest disp
+
+instance Dec Ind where
+  dec (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_dec_membase dest 0
+
+instance Dec Reg32 where
+  dec (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_dec_reg dest
+
+
+-- One's complement negation
+
+class Not a where
+  not :: a -> CodeGen e s ()
+
+instance Not Addr where
+  not (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_not_mem dest
+
+instance Not (Disp, Reg32) where
+  not (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_not_membase dest disp
+
+instance Not Ind where
+  not (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_not_membase dest 0
+
+instance Not Reg32 where
+  not (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_not_reg dest
+
+
+-- Two's complement negation
+
+class Neg a where
+  neg :: a -> CodeGen e s ()
+
+instance Neg Addr where
+  neg (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_neg_mem dest
+
+instance Neg (Disp, Reg32) where
+  neg (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_neg_membase dest disp
+
+instance Neg Ind where
+  neg (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_neg_membase dest 0
+
+instance Neg Reg32 where
+  neg (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_neg_reg dest
+
+
+-- No operation
+
+nop = ensureBufferSize x86_max_instruction_bytes >> x86_nop
+
+
+-- ALU operations
+
+-- Calling "x86_alu_reg8_reg8 _ _ _ *False* *False*" is a little bit hackish: the last two
+-- arguments are set to True for the "high byte registers" ah, bh, ch and dh.
+-- x86_reg8_emit then sets the 3rd bit in the register number. This bit is set in our
+-- encoding anyway to the right value, so we simply skip this part.
+
+class Add a b where
+  add :: a -> b -> CodeGen e s ()
+
+instance Add Reg32 Word32 where
+  add (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_add dest (fromIntegral imm)
+
+instance Add Addr Word32 where
+  add (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_add dest (fromIntegral imm)
+
+instance Add (Disp, Reg32) Word32 where
+  add (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_add dest disp (fromIntegral imm)
+
+instance Add Ind Word32 where
+  add (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_add dest 0 (fromIntegral imm)
+
+instance Add (Disp, Reg32) Word8 where
+  add (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_add dest disp (fromIntegral imm)
+
+instance Add Ind Word8 where
+  add (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_add dest 0 (fromIntegral imm)
+
+instance Add Addr Reg32 where
+  add (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_add dest source
+
+instance Add (Disp, Reg32) Reg32 where
+  add (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_add dest disp source
+
+instance Add Ind Reg32 where
+  add (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_add dest 0 source
+
+instance Add Reg32 Reg32 where
+  add (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_add dest source
+
+instance Add Reg8 Reg8 where
+  add (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_add dest source False False
+
+instance Add Reg32 Addr where
+  add (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_add dest source
+
+instance Add Reg32 (Disp, Reg32) where
+  add (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_add dest source disp
+
+instance Add Reg32 Ind where
+  add (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_add dest source 0
+
+
+class Or a b where
+  or :: a -> b -> CodeGen e s ()
+
+instance Or Reg32 Word32 where
+  or (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_or dest (fromIntegral imm)
+
+instance Or Addr Word32 where
+  or (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_or dest (fromIntegral imm)
+
+instance Or (Disp, Reg32) Word32 where
+  or (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_or dest disp (fromIntegral imm)
+
+instance Or Ind Word32 where
+  or (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_or dest 0 (fromIntegral imm)
+
+instance Or (Disp, Reg32) Word8 where
+  or (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_or dest disp (fromIntegral imm)
+
+instance Or Ind Word8 where
+  or (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_or dest 0 (fromIntegral imm)
+
+instance Or Addr Reg32 where
+  or (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_or dest source
+
+instance Or (Disp, Reg32) Reg32 where
+  or (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_or dest disp source
+
+instance Or Ind Reg32 where
+  or (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_or dest 0 source
+
+instance Or Reg32 Reg32 where
+  or (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_or dest source
+
+instance Or Reg8 Reg8 where
+  or (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_or dest source False False
+
+instance Or Reg32 Addr where
+  or (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_or dest source
+
+instance Or Reg32 (Disp, Reg32) where
+  or (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_or dest source disp
+
+instance Or Reg32 Ind where
+  or (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_or dest source 0
+
+
+class Adc a b where
+  adc :: a -> b -> CodeGen e s ()
+
+instance Adc Reg32 Word32 where
+  adc (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_adc dest (fromIntegral imm)
+
+instance Adc Addr Word32 where
+  adc (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_adc dest (fromIntegral imm)
+
+instance Adc (Disp, Reg32) Word32 where
+  adc (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_adc dest disp (fromIntegral imm)
+
+instance Adc Ind Word32 where
+  adc (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_adc dest 0 (fromIntegral imm)
+
+instance Adc (Disp, Reg32) Word8 where
+  adc (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_adc dest disp (fromIntegral imm)
+
+instance Adc Ind Word8 where
+  adc (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_adc dest 0 (fromIntegral imm)
+
+instance Adc Addr Reg32 where
+  adc (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_adc dest source
+
+instance Adc (Disp, Reg32) Reg32 where
+  adc (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_adc dest disp source
+
+instance Adc Ind Reg32 where
+  adc (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_adc dest 0 source
+
+instance Adc Reg32 Reg32 where
+  adc (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_adc dest source
+
+instance Adc Reg8 Reg8 where
+  adc (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_adc dest source False False
+
+instance Adc Reg32 Addr where
+  adc (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_adc dest source
+
+instance Adc Reg32 (Disp, Reg32) where
+  adc (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_adc dest source disp
+
+instance Adc Reg32 Ind where
+  adc (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_adc dest source 0
+
+
+class Sbb a b where
+  sbb :: a -> b -> CodeGen e s ()
+
+instance Sbb Reg32 Word32 where
+  sbb (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_sbb dest (fromIntegral imm)
+
+instance Sbb Addr Word32 where
+  sbb (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_sbb dest (fromIntegral imm)
+
+instance Sbb (Disp, Reg32) Word32 where
+  sbb (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_sbb dest disp (fromIntegral imm)
+
+instance Sbb Ind Word32 where
+  sbb (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_sbb dest 0 (fromIntegral imm)
+
+instance Sbb (Disp, Reg32) Word8 where
+  sbb (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_sbb dest disp (fromIntegral imm)
+
+instance Sbb Ind Word8 where
+  sbb (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_sbb dest 0 (fromIntegral imm)
+
+instance Sbb Addr Reg32 where
+  sbb (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_sbb dest source
+
+instance Sbb (Disp, Reg32) Reg32 where
+  sbb (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_sbb dest disp source
+
+instance Sbb Ind Reg32 where
+  sbb (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_sbb dest 0 source
+
+instance Sbb Reg32 Reg32 where
+  sbb (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_sbb dest source
+
+instance Sbb Reg8 Reg8 where
+  sbb (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_sbb dest source False False
+
+instance Sbb Reg32 Addr where
+  sbb (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_sbb dest source
+
+instance Sbb Reg32 (Disp, Reg32) where
+  sbb (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_sbb dest source disp
+
+instance Sbb Reg32 Ind where
+  sbb (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_sbb dest source 0
+
+
+class And a b where
+  and :: a -> b -> CodeGen e s ()
+
+instance And Reg32 Word32 where
+  and (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_and dest (fromIntegral imm)
+
+instance And Addr Word32 where
+  and (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_and dest (fromIntegral imm)
+
+instance And (Disp, Reg32) Word32 where
+  and (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_and dest disp (fromIntegral imm)
+
+instance And Ind Word32 where
+  and (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_and dest 0 (fromIntegral imm)
+
+instance And (Disp, Reg32) Word8 where
+  and (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_and dest disp (fromIntegral imm)
+
+instance And Ind Word8 where
+  and (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_and dest 0 (fromIntegral imm)
+
+instance And Addr Reg32 where
+  and (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_and dest source
+
+instance And (Disp, Reg32) Reg32 where
+  and (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_and dest disp source
+
+instance And Ind Reg32 where
+  and (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_and dest 0 source
+
+instance And Reg32 Reg32 where
+  and (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_and dest source
+
+instance And Reg8 Reg8 where
+  and (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_and dest source False False
+
+instance And Reg32 Addr where
+  and (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_and dest source
+
+instance And Reg32 (Disp, Reg32) where
+  and (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_and dest source disp
+
+instance And Reg32 Ind where
+  and (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_and dest source 0
+
+
+class Sub a b where
+  sub :: a -> b -> CodeGen e s ()
+
+instance Sub Reg32 Word32 where
+  sub (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_sub dest (fromIntegral imm)
+
+instance Sub Addr Word32 where
+  sub (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_sub dest (fromIntegral imm)
+
+instance Sub (Disp, Reg32) Word32 where
+  sub (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_sub dest disp (fromIntegral imm)
+
+instance Sub Ind Word32 where
+  sub (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_sub dest 0 (fromIntegral imm)
+
+instance Sub (Disp, Reg32) Word8 where
+  sub (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_sub dest disp (fromIntegral imm)
+
+instance Sub Ind Word8 where
+  sub (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_sub dest 0 (fromIntegral imm)
+
+instance Sub Addr Reg32 where
+  sub (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_sub dest source
+
+instance Sub (Disp, Reg32) Reg32 where
+  sub (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_sub dest disp source
+
+instance Sub Ind Reg32 where
+  sub (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_sub dest 0 source
+
+instance Sub Reg32 Reg32 where
+  sub (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_sub dest source
+
+instance Sub Reg8 Reg8 where
+  sub (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_sub dest source False False
+
+instance Sub Reg32 Addr where
+  sub (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_sub dest source
+
+instance Sub Reg32 (Disp, Reg32) where
+  sub (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_sub dest source disp
+
+instance Sub Reg32 Ind where
+  sub (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_sub dest source 0
+
+
+class Xor a b where
+  xor :: a -> b -> CodeGen e s ()
+
+instance Xor Reg32 Word32 where
+  xor (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_xor dest (fromIntegral imm)
+
+instance Xor Addr Word32 where
+  xor (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_xor dest (fromIntegral imm)
+
+instance Xor (Disp, Reg32) Word32 where
+  xor (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_xor dest disp (fromIntegral imm)
+
+instance Xor Ind Word32 where
+  xor (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_xor dest 0 (fromIntegral imm)
+
+instance Xor (Disp, Reg32) Word8 where
+  xor (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_xor dest disp (fromIntegral imm)
+
+instance Xor Ind Word8 where
+  xor (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_xor dest 0 (fromIntegral imm)
+
+instance Xor Addr Reg32 where
+  xor (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_xor dest source
+
+instance Xor (Disp, Reg32) Reg32 where
+  xor (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_xor dest disp source
+
+instance Xor Ind Reg32 where
+  xor (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_xor dest 0 source
+
+instance Xor Reg32 Reg32 where
+  xor (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_xor dest source
+
+instance Xor Reg8 Reg8 where
+  xor (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_xor dest source False False
+
+instance Xor Reg32 Addr where
+  xor (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_xor dest source
+
+instance Xor Reg32 (Disp, Reg32) where
+  xor (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_xor dest source disp
+
+instance Xor Reg32 Ind where
+  xor (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_xor dest source 0
+
+
+class Cmp a b where
+  cmp :: a -> b -> CodeGen e s ()
+
+instance Cmp Reg32 Word32 where
+  cmp (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_cmp dest (fromIntegral imm)
+
+instance Cmp Reg32 Label where
+  cmp (Reg32 dest) lab = do
+      ensureBufferSize x86_max_instruction_bytes
+      x86_alu_reg_imm x86_cmp dest 0xf0f0f0f0
+      emitFixup lab (-4) Fixup32Absolute
+
+instance Cmp Addr Word32 where
+  cmp (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest (fromIntegral imm)
+
+instance Cmp Addr Label where
+  cmp (Addr dest) lab = do
+      ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest 0xf0f0f0f0
+      emitFixup lab (-4) Fixup32Absolute
+
+instance Cmp (Disp, Reg32) Word32 where
+  cmp (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp (fromIntegral imm)
+
+instance Cmp (Disp, Reg32) Label where
+  cmp (Disp disp, Reg32 dest) lab = do
+                                   ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp 0xf0f0f0f0
+                                   emitFixup lab (-4) Fixup32Absolute
+
+instance Cmp Ind Word32 where
+  cmp (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 (fromIntegral imm)
+
+instance Cmp Ind Label where
+  cmp (Ind (Reg32 dest)) lab = do
+                         ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 0xf0f0f0f0
+                         emitFixup lab (-4) Fixup32Absolute
+
+instance Cmp (Disp, Reg32) Word8 where
+  cmp (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_cmp dest disp imm
+
+instance Cmp Ind Word8 where
+  cmp (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase8_imm x86_cmp dest 0 imm
+
+instance Cmp Addr Reg32 where
+  cmp (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_reg x86_cmp dest source
+
+instance Cmp (Disp, Reg32) Reg32 where
+  cmp (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_cmp dest disp source
+
+instance Cmp Ind Reg32 where
+  cmp (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_reg x86_cmp dest 0 source
+
+instance Cmp Reg32 Reg32 where
+  cmp (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_reg x86_cmp dest source
+
+instance Cmp Reg8 Reg8 where
+  cmp (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg8_reg8 x86_cmp dest source False False
+
+instance Cmp Reg32 Addr where
+  cmp (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_mem x86_cmp dest source
+
+instance Cmp Reg32 (Disp, Reg32) where
+  cmp (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_cmp dest source disp
+
+instance Cmp Reg32 Ind where
+  cmp (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_membase x86_cmp dest source 0
+
+
+-- logical compare
+
+class Test a b where
+  test :: a -> b -> CodeGen e s ()
+
+instance Test Reg32 Word32 where
+  test (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_test_reg_imm dest imm 
+
+instance Test Addr Word32 where
+  test (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_test_mem_imm dest imm 
+
+instance Test (Disp, Reg32) Word32 where
+  test (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_test_membase_imm dest disp imm 
+
+instance Test Ind Word32 where
+  test (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_test_membase_imm dest 0 imm 
+
+instance Test Reg32 Reg32 where
+  test (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_test_reg_reg dest source 
+
+instance Test Addr Reg32 where
+  test (Addr dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_test_mem_reg dest source 
+
+instance Test (Disp, Reg32) Reg32 where
+  test (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_test_membase_reg dest disp source 
+
+instance Test Ind Reg32 where
+  test (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_test_membase_reg dest 0 source 
+
+
+-- shift and rotate
+
+class Rol a b where
+  rol :: a -> b -> CodeGen e s ()
+
+instance Rol Reg32 Word8 where
+  rol (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_rol dest imm 
+
+instance Rol Addr Word8 where
+  rol (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_rol dest imm 
+
+instance Rol (Disp, Reg32) Word8 where
+  rol (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rol dest disp imm 
+
+instance Rol Ind Word8 where
+  rol (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rol dest 0 imm 
+
+instance Rol Reg32 Reg8 where
+  rol (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_rol dest
+  rol _ _ = onlyCl
+
+instance Rol Addr Reg8 where
+  rol (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_rol dest
+  rol _ _ = onlyCl
+
+instance Rol (Disp, Reg32) Reg8 where
+  rol (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rol dest disp
+
+instance Rol Ind Reg8 where
+  rol (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rol dest 0
+  rol _ _ = onlyCl
+
+class Ror a b where
+  ror :: a -> b -> CodeGen e s ()
+
+instance Ror Reg32 Word8 where
+  ror (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_ror dest imm 
+
+instance Ror Addr Word8 where
+  ror (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_ror dest imm 
+
+instance Ror (Disp, Reg32) Word8 where
+  ror (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_ror dest disp imm 
+
+instance Ror Ind Word8 where
+  ror (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_ror dest 0 imm 
+
+instance Ror Reg32 Reg8 where
+  ror (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_ror dest
+  ror _ _ = onlyCl
+
+instance Ror Addr Reg8 where
+  ror (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_ror dest
+  ror _ _ = onlyCl
+
+instance Ror (Disp, Reg32) Reg8 where
+  ror (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_ror dest disp
+
+instance Ror Ind Reg8 where
+  ror (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_ror dest 0
+  ror _ _ = onlyCl
+
+class Rcl a b where
+  rcl :: a -> b -> CodeGen e s ()
+
+instance Rcl Reg32 Word8 where
+  rcl (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_rcl dest imm 
+
+instance Rcl Addr Word8 where
+  rcl (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_rcl dest imm 
+
+instance Rcl (Disp, Reg32) Word8 where
+  rcl (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rcl dest disp imm 
+
+instance Rcl Ind Word8 where
+  rcl (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rcl dest 0 imm 
+
+instance Rcl Reg32 Reg8 where
+  rcl (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_rcl dest
+  rcl _ _ = onlyCl
+
+instance Rcl Addr Reg8 where
+  rcl (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_rcl dest
+  rcl _ _ = onlyCl
+
+instance Rcl (Disp, Reg32) Reg8 where
+  rcl (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rcl dest disp
+
+instance Rcl Ind Reg8 where
+  rcl (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rcl dest 0
+  rcl _ _ = onlyCl
+
+class Rcr a b where
+  rcr :: a -> b -> CodeGen e s ()
+
+instance Rcr Reg32 Word8 where
+  rcr (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_rcr dest imm 
+
+instance Rcr Addr Word8 where
+  rcr (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_rcr dest imm 
+
+instance Rcr (Disp, Reg32) Word8 where
+  rcr (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rcr dest disp imm 
+
+instance Rcr Ind Word8 where
+  rcr (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_rcr dest 0 imm 
+
+instance Rcr Reg32 Reg8 where
+  rcr (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_rcr dest
+  rcr _ _ = onlyCl
+
+instance Rcr Addr Reg8 where
+  rcr (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_rcr dest
+  rcr _ _ = onlyCl
+
+instance Rcr (Disp, Reg32) Reg8 where
+  rcr (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rcr dest disp
+
+instance Rcr Ind Reg8 where
+  rcr (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_rcr dest 0
+  rcr _ _ = onlyCl
+
+class Shl a b where
+  shl :: a -> b -> CodeGen e s ()
+
+instance Shl Reg32 Word8 where
+  shl (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_shl dest imm 
+
+instance Shl Addr Word8 where
+  shl (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_shl dest imm 
+
+instance Shl (Disp, Reg32) Word8 where
+  shl (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shl dest disp imm 
+
+instance Shl Ind Word8 where
+  shl (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shl dest 0 imm 
+
+instance Shl Reg32 Reg8 where
+  shl (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_shl dest
+  shl _ _ = onlyCl
+
+instance Shl Addr Reg8 where
+  shl (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_shl dest
+  shl _ _ = onlyCl
+
+instance Shl (Disp, Reg32) Reg8 where
+  shl (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shl dest disp
+
+instance Shl Ind Reg8 where
+  shl (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shl dest 0
+  shl _ _ = onlyCl
+
+class Shr a b where
+  shr :: a -> b -> CodeGen e s ()
+
+instance Shr Reg32 Word8 where
+  shr (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_shr dest imm 
+
+instance Shr Addr Word8 where
+  shr (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_shr dest imm 
+
+instance Shr (Disp, Reg32) Word8 where
+  shr (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shr dest disp imm 
+
+instance Shr Ind Word8 where
+  shr (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shr dest 0 imm 
+
+instance Shr Reg32 Reg8 where
+  shr (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_shr dest
+  shr _ _ = onlyCl
+
+instance Shr Addr Reg8 where
+  shr (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_shr dest
+  shr _ _ = onlyCl
+
+instance Shr (Disp, Reg32) Reg8 where
+  shr (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shr dest disp
+
+instance Shr Ind Reg8 where
+  shr (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shr dest 0
+  shr _ _ = onlyCl
+
+class Sar a b where
+  sar :: a -> b -> CodeGen e s ()
+
+instance Sar Reg32 Word8 where
+  sar (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_sar dest imm 
+
+instance Sar Addr Word8 where
+  sar (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_sar dest imm 
+
+instance Sar (Disp, Reg32) Word8 where
+  sar (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_sar dest disp imm 
+
+instance Sar Ind Word8 where
+  sar (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_sar dest 0 imm 
+
+instance Sar Reg32 Reg8 where
+  sar (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_sar dest
+  sar _ _ = onlyCl
+
+instance Sar Addr Reg8 where
+  sar (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_sar dest
+  sar _ _ = onlyCl
+
+instance Sar (Disp, Reg32) Reg8 where
+  sar (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_sar dest disp
+
+instance Sar Ind Reg8 where
+  sar (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_sar dest 0
+  sar _ _ = onlyCl
+
+class Sal a b where
+  sal :: a -> b -> CodeGen e s ()
+
+instance Sal Reg32 Word8 where
+  sal (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg_imm x86_shl dest imm 
+
+instance Sal Addr Word8 where
+  sal (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem_imm x86_shl dest imm 
+
+instance Sal (Disp, Reg32) Word8 where
+  sal (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shl dest disp imm 
+
+instance Sal Ind Word8 where
+  sal (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase_imm x86_shl dest 0 imm 
+
+instance Sal Reg32 Reg8 where
+  sal (Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_reg x86_shl dest
+  sal _ _ = onlyCl
+
+instance Sal Addr Reg8 where
+  sal (Addr dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_mem x86_shl dest
+  sal _ _ = onlyCl
+
+instance Sal (Disp, Reg32) Reg8 where
+  sal (Disp disp, Reg32 dest) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shl dest disp
+
+instance Sal Ind Reg8 where
+  sal (Ind (Reg32 dest)) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shift_membase x86_shl dest 0
+  sal _ _ = onlyCl
+
+
+-- double precision shift right
+
+class Shrd a b c where
+  shrd :: a -> b -> c -> CodeGen e s ()
+
+instance Shrd Reg32 Reg32 Reg8 where
+  shrd (Reg32 dest) (Reg32 source) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shrd_reg dest source
+  shrd _ _ _ = onlyCl
+
+instance Shrd Reg32 Reg32 Word8 where
+  shrd (Reg32 dest) (Reg32 source) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shrd_reg_imm dest source imm 
+
+
+-- double precision shift left
+
+class Shld a b c where
+  shld :: a -> b -> c -> CodeGen e s ()
+
+instance Shld Reg32 Reg32 Reg8 where
+  shld (Reg32 dest) (Reg32 source) (Reg8 1) = ensureBufferSize x86_max_instruction_bytes >> x86_shld_reg dest source
+  shld _ _ _ = onlyCl
+
+instance Shld Reg32 Reg32 Word8 where
+  shld (Reg32 dest) (Reg32 source) imm = ensureBufferSize x86_max_instruction_bytes >> x86_shld_reg_imm dest source imm 
+
+
+-- unsigned multiply
+
+class Mul a where
+  mul :: a -> CodeGen e s ()
+
+instance Mul Reg32 where
+  mul (Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_reg arg False
+
+instance Mul Addr where
+  mul (Addr arg) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_mem arg False
+
+instance Mul (Disp, Reg32) where
+  mul (Disp disp, Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_membase arg disp False
+
+instance Mul Ind where
+  mul (Ind (Reg32 arg)) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_membase arg 0 False
+
+
+-- signed multiply
+
+data InPlace = InPlace
+
+-- if a == InPlace then
+--   b = b * c
+-- else
+--   a = b * c
+
+class Imul a b c where
+  imul :: a -> b -> c -> CodeGen e s ()
+
+instance Imul InPlace Reg32 Reg32 where
+  imul _ (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_reg dest source
+
+instance Imul InPlace Reg32 Addr where
+  imul _ (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_mem dest source
+
+instance Imul InPlace Reg32 (Disp, Reg32) where
+  imul _ (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_membase dest source disp
+
+instance Imul InPlace Reg32 Ind where
+  imul _ (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_membase dest source 0
+
+instance Imul Reg32 Reg32 Word32 where
+  imul (Reg32 dest) (Reg32 source) imm = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_reg_imm dest source imm 
+
+instance Imul Reg32 Addr Word32 where
+  imul (Reg32 dest) (Addr source) imm = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_mem_imm dest source imm 
+
+instance Imul Reg32 (Disp, Reg32) Word32 where
+  imul (Reg32 dest) (Disp disp, Reg32 source) imm = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_membase_imm dest source disp imm 
+
+instance Imul Reg32 Ind Word32 where
+  imul (Reg32 dest) (Ind (Reg32 source)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_imul_reg_membase_imm dest source 0 imm 
+
+
+-- divide EDX:EAX by rm;
+-- eax = quotient, edx = remainder
+
+-- unsigned divide
+
+class Div a where
+  div :: a -> CodeGen e s ()
+
+instance Div Reg32 where
+  div (Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_reg arg False
+
+instance Div Addr where
+  div (Addr arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_mem arg False
+
+instance Div (Disp, Reg32) where
+  div (Disp disp, Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_membase arg disp False
+
+instance Div Ind where
+  div (Ind (Reg32 arg)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_membase arg 0 False
+
+
+-- signed divide
+
+class Idiv a where
+  idiv :: a -> CodeGen e s ()
+
+instance Idiv Reg32 where
+  idiv (Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_reg arg True
+
+instance Idiv Addr where
+  idiv (Addr arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_mem arg True
+
+instance Idiv (Disp, Reg32) where
+  idiv (Disp disp, Reg32 arg) = ensureBufferSize x86_max_instruction_bytes >> x86_div_membase arg disp True
+
+instance Idiv Ind where
+  idiv (Ind (Reg32 arg)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_membase arg 0 True
+
+
+-- "mov" instruction for different sources and destinations
+
+class Mov a b where
+  mov :: a -> b -> CodeGen e s ()
+
+
+instance Mov Reg8 Reg8 where
+  mov (Reg8 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_reg dest source 1
+
+instance Mov Reg16 Reg16 where
+  mov (Reg16 dest) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_reg dest source 2
+
+instance Mov Reg32 Reg32 where
+  mov (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_reg dest source 4
+
+
+instance Mov Reg32 Word32 where
+  mov (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest (fromIntegral imm)
+
+instance Mov Reg32 Label where
+  mov (Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest 0
+                            emitFixup lab (-4) Fixup32Absolute
+
+instance Mov Addr Word8 where
+  mov (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest (fromIntegral imm) 1
+
+instance Mov Addr Word16 where
+  mov (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest (fromIntegral imm) 2
+
+instance Mov Addr Word32 where
+  mov (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest imm 4
+
+instance Mov Addr Label where
+  mov (Addr dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest 0 4
+                           emitFixup lab (-4) Fixup32Absolute
+
+instance Mov (Disp, Reg32) Word8 where
+  mov (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp (fromIntegral imm) 1
+
+instance Mov Ind Word8 where
+  mov (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 (fromIntegral imm) 1
+
+instance Mov (Disp, Reg32) Word16 where
+  mov (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp (fromIntegral imm) 2
+
+instance Mov Ind Word16 where
+  mov (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 (fromIntegral imm) 2
+
+instance Mov (Disp, Reg32) Word32 where
+  mov (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp imm 4
+
+instance Mov (Disp, Reg32) Label where
+  mov (Disp disp, Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp 0 4
+                                       emitFixup lab (-4) Fixup32Absolute
+
+instance Mov Ind Word32 where
+  mov (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 imm 4
+
+instance Mov Ind Label where
+  mov (Ind (Reg32 dest)) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 0 4
+                                  emitFixup lab (-4) Fixup32Absolute
+
+instance Mov (Reg32, Reg32, Scale) Word8 where
+  mov (Reg32 base, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) (fromIntegral imm) 1
+
+instance Mov (Reg32, Reg32, Scale) Word16 where
+  mov (Reg32 base, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) (fromIntegral imm) 2
+
+instance Mov (Reg32, Reg32, Scale) Word32 where
+  mov (Reg32 base, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) imm 4
+
+instance Mov (Reg32, Reg32, Scale) Label where
+  mov (Reg32 base, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) 0 4
+                                                emitFixup lab (-4) Fixup32Absolute
+
+instance Mov (Disp, Reg32, Scale) Word8 where
+  mov (Disp disp, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (fromIntegral imm) 1
+
+instance Mov (Disp, Reg32, Scale) Word16 where
+  mov (Disp disp, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (fromIntegral imm) 2
+
+instance Mov (Disp, Reg32, Scale) Word32 where
+  mov (Disp disp, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) imm 4
+
+instance Mov (Disp, Reg32, Scale) Label where
+  mov (Disp disp, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) 0 4
+                                               emitFixup lab (-4) Fixup32Absolute
+
+instance Mov (Disp, Reg32, Reg32, Scale) Word8 where
+  mov (Disp disp, Reg32 5, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) (fromIntegral imm) 1
+  mov _ _ = onlyEbp
+
+instance Mov (Disp, Reg32, Reg32, Scale) Word16 where
+  mov (Disp disp, Reg32 5, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) (fromIntegral imm) 2
+  mov _ _ = onlyEbp
+
+instance Mov (Disp, Reg32, Reg32, Scale) Word32 where
+  mov (Disp disp, Reg32 5, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) imm 4
+  mov _ _ = onlyEbp
+
+instance Mov (Disp, Reg32, Reg32, Scale) Label where
+  mov (Disp disp, Reg32 5, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) 0 4
+                                                        emitFixup lab (-4) Fixup32Absolute
+  mov _ _ = onlyEbp
+
+instance Mov Addr Reg8 where
+  mov (Addr a) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_reg a source 1
+
+instance Mov Addr Reg16 where
+  mov (Addr a) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_reg a source 2
+
+instance Mov Addr Reg32 where
+  mov (Addr a) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_reg a source 4
+
+instance Mov Reg8 Addr where
+  mov (Reg8 dest) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_mem dest a 1
+
+instance Mov Reg16 Addr where
+  mov (Reg16 dest) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_mem dest a 2
+
+instance Mov Reg32 Addr where
+  mov (Reg32 dest) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_mem dest a 4
+
+
+instance Mov Ind Reg8 where
+  mov (Ind (Reg32 dest)) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_regp_reg dest source 1
+
+instance Mov Ind Reg16 where
+  mov (Ind (Reg32 dest)) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_regp_reg dest source 2
+
+instance Mov Ind Reg32 where
+  mov (Ind (Reg32 dest)) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_regp_reg dest source 4
+
+instance Mov Reg8 Ind where
+  mov (Reg8 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_regp dest source 1
+
+instance Mov Reg16 Ind where
+  mov (Reg16 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_regp dest source 2
+
+instance Mov Reg32 Ind where
+  mov (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_regp dest source 4
+
+
+instance Mov (Disp, Reg32) Reg8 where
+  mov (Disp disp, Reg32 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_reg dest disp source 1
+
+instance Mov (Disp, Reg32) Reg16 where
+  mov (Disp disp, Reg32 dest) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_reg dest disp source 2
+
+instance Mov (Disp, Reg32) Reg32 where
+  mov (Disp disp, Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_reg dest disp source 4
+
+instance Mov Reg8 (Disp, Reg32) where
+  mov (Reg8 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_membase dest source disp 1
+
+instance Mov Reg16 (Disp, Reg32) where
+  mov (Reg16 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_membase dest source disp 2
+
+instance Mov Reg32 (Disp, Reg32) where
+  mov (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_membase dest source disp 4
+
+
+instance Mov (Reg32, Reg32, Scale) Reg8 where
+  mov (Reg32 base, Reg32 index, s) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg base 0 index (scaleToShift s) source 1
+
+instance Mov (Reg32, Reg32, Scale) Reg16 where
+  mov (Reg32 base, Reg32 index, s) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg base 0 index (scaleToShift s) source 2
+
+instance Mov (Reg32, Reg32, Scale) Reg32 where
+  mov (Reg32 base, Reg32 index, s) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg base 0 index (scaleToShift s) source 4
+
+instance Mov Reg8 (Reg32, Reg32, Scale) where
+  mov (Reg8 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest base 0 index (scaleToShift s) 1
+
+instance Mov Reg16 (Reg32, Reg32, Scale) where
+  mov (Reg16 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest base 0 index (scaleToShift s) 2
+
+instance Mov Reg32 (Reg32, Reg32, Scale) where
+  mov (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest base 0 index (scaleToShift s) 4
+
+
+instance Mov (Disp, Reg32, Scale) Reg8 where
+  mov (Disp disp, Reg32 index, s) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 1
+
+instance Mov (Disp, Reg32, Scale) Reg16 where
+  mov (Disp disp, Reg32 index, s) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 2
+
+instance Mov (Disp, Reg32, Scale) Reg32 where
+  mov (Disp disp, Reg32 index, s) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 4
+
+instance Mov Reg8 (Disp, Reg32, Scale) where
+  mov (Reg8 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 1
+
+instance Mov Reg16 (Disp, Reg32, Scale) where
+  mov (Reg16 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 2
+
+instance Mov Reg32 (Disp, Reg32, Scale) where
+  mov (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 4
+
+
+instance Mov (Disp, Reg32, Reg32, Scale) Reg8 where
+  mov (Disp disp, Reg32 5, Reg32 index, s) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg 5 disp index (scaleToShift s) source 1
+  mov _ _ = onlyEbp
+
+instance Mov (Disp, Reg32, Reg32, Scale) Reg16 where
+  mov (Disp disp, Reg32 5, Reg32 index, s) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg 5 disp index (scaleToShift s) source 2
+  mov _ _ = onlyEbp
+
+instance Mov (Disp, Reg32, Reg32, Scale) Reg32 where
+  mov (Disp disp, Reg32 5, Reg32 index, s) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_reg 5 disp index (scaleToShift s) source 4
+  mov _ _ = onlyEbp
+
+instance Mov Reg8 (Disp, Reg32, Reg32, Scale) where
+  mov (Reg8 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 1
+  mov _ _ = onlyEbp
+
+instance Mov Reg16 (Disp, Reg32, Reg32, Scale) where
+  mov (Reg16 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 2
+  mov _ _ = onlyEbp
+
+instance Mov Reg32 (Disp, Reg32, Reg32, Scale) where
+  mov (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 4
+  mov _ _ = onlyEbp
+
+
+-- move with sign-extension
+
+class Movsxb a b where
+  movsxb :: a -> b -> CodeGen e s ()
+
+instance Movsxb Reg32 Reg8 where
+  movsxb (Reg32 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_reg dest source True False
+
+instance Movsxb Reg32 Addr where
+  movsxb (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_mem dest source True False
+
+instance Movsxb Reg32 (Disp, Reg32) where
+  movsxb (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source disp True False
+
+instance Movsxb Reg32 Ind where
+  movsxb (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source 0 True False
+
+instance Movsxb Reg32 (Disp, Reg32, Reg32, Scale) where
+  movsxb (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest 5 disp index (scaleToShift s) True False
+  movsxb _ _ = onlyEbp
+
+instance Movsxb Reg32 (Disp, Reg32, Scale) where
+  movsxb (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) True False
+
+instance Movsxb Reg32 (Reg32, Reg32, Scale) where
+  movsxb (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest base 0 index (scaleToShift s) True False
+
+class Movsxw a b where
+  movsxw :: a -> b -> CodeGen e s ()
+
+instance Movsxw Reg32 Reg16 where
+  movsxw (Reg32 dest) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_reg dest source True True
+
+instance Movsxw Reg32 Addr where
+  movsxw (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_mem dest source True True
+
+instance Movsxw Reg32 (Disp, Reg32) where
+  movsxw (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source disp True True
+
+instance Movsxw Reg32 Ind where
+  movsxw (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source 0 True True
+
+instance Movsxw Reg32 (Disp, Reg32, Reg32, Scale) where
+  movsxw (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest 5 disp index (scaleToShift s) True True
+  movsxw _ _ = onlyEbp
+
+instance Movsxw Reg32 (Disp, Reg32, Scale) where
+  movsxw (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) True True
+
+instance Movsxw Reg32 (Reg32, Reg32, Scale) where
+  movsxw (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest base 0 index (scaleToShift s) True True
+
+
+-- move with zero-extension
+
+class Movzxb a b where
+  movzxb :: a -> b -> CodeGen e s ()
+
+instance Movzxb Reg32 Reg8 where
+  movzxb (Reg32 dest) (Reg8 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_reg dest source False False
+
+instance Movzxb Reg32 Addr where
+  movzxb (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_mem dest source False False
+
+instance Movzxb Reg32 (Disp, Reg32) where
+  movzxb (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source disp False False
+
+instance Movzxb Reg32 Ind where
+  movzxb (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source 0 False False
+
+instance Movzxb Reg32 (Disp, Reg32, Reg32, Scale) where
+  movzxb (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest 5 disp index (scaleToShift s) False False
+  movzxb _ _ = onlyEbp
+
+instance Movzxb Reg32 (Disp, Reg32, Scale) where
+  movzxb (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) False False
+
+instance Movzxb Reg32 (Reg32, Reg32, Scale) where
+  movzxb (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest base 0 index (scaleToShift s) False False
+
+class Movzxw a b where
+  movzxw :: a -> b -> CodeGen e s ()
+
+instance Movzxw Reg32 Reg16 where
+  movzxw (Reg32 dest) (Reg16 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_reg dest source False True
+
+instance Movzxw Reg32 Addr where
+  movzxw (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_mem dest source False True
+
+instance Movzxw Reg32 (Disp, Reg32) where
+  movzxw (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source disp False True
+
+instance Movzxw Reg32 Ind where
+  movzxw (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_membase dest source 0 False True
+
+instance Movzxw Reg32 (Disp, Reg32, Reg32, Scale) where
+  movzxw (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest 5 disp index (scaleToShift s) False True
+  movzxw _ _ = onlyEbp
+
+instance Movzxw Reg32 (Disp, Reg32, Scale) where
+  movzxw (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) False True
+
+instance Movzxw Reg32 (Reg32, Reg32, Scale) where
+  movzxw (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_widen_memindex dest base 0 index (scaleToShift s) False True
+
+
+-- load effective address
+
+class Lea a b where
+  lea :: a -> b -> CodeGen e s ()
+
+instance Lea Reg32 Addr where
+  lea (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_mem dest source 
+
+instance Lea Reg32 (Disp, Reg32) where
+  lea (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_membase dest source disp 
+
+instance Lea Reg32 Ind where
+  lea (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_membase dest source 0 
+
+instance Lea Reg32 (Disp, Reg32, Reg32, Scale) where
+  lea (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_memindex dest 5 disp index (scaleToShift s)
+  lea _ _ = onlyEbp
+
+instance Lea Reg32 (Disp, Reg32, Scale) where
+  lea (Reg32 dest) (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_memindex dest x86_nobasereg disp index (scaleToShift s)
+
+instance Lea Reg32 (Reg32, Reg32, Scale) where
+  lea (Reg32 dest) (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_lea_memindex dest base 0 index (scaleToShift s)
+
+
+-- convert word to doubleword
+
+cdq = ensureBufferSize x86_max_instruction_bytes >> x86_cdq
+
+
+-- wait for FPU
+
+wait = ensureBufferSize x86_max_instruction_bytes >> x86_wait
+
+
+-- push to stack
+
+class Push a where
+  push :: a -> CodeGen e s ()
+
+instance Push Reg32 where
+  push (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_push_reg source 
+
+instance Push Ind where
+  push (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_push_regp source
+
+instance Push Addr where
+  push (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_push_mem source 
+
+instance Push (Disp, Reg32) where
+  push (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_push_membase source disp 
+
+instance Push Word32 where
+  push imm = ensureBufferSize x86_max_instruction_bytes >> x86_push_imm imm 
+
+instance Push Label where
+  push l = do ensureBufferSize x86_max_instruction_bytes >> x86_push_imm_template
+              emitFixup l (-4) Fixup32Absolute
+
+instance Push (Disp, Reg32, Reg32, Scale) where
+  push (Disp disp, Reg32 5, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_push_memindex 5 disp index (scaleToShift s)
+  push _ = onlyEbp
+
+instance Push (Disp, Reg32, Scale) where
+  push (Disp disp, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_push_memindex x86_nobasereg disp index (scaleToShift s)
+
+instance Push (Reg32, Reg32, Scale) where
+  push (Reg32 base, Reg32 index, s) = ensureBufferSize x86_max_instruction_bytes >> x86_push_memindex base 0 index (scaleToShift s)
+
+
+-- pop from stack
+
+class Pop a where
+  pop :: a -> CodeGen e s ()
+
+instance Pop Reg32 where
+  pop (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_pop_reg dest 
+
+instance Pop Addr where
+  pop (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_pop_mem dest 
+
+instance Pop (Disp, Reg32) where
+  pop (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_pop_membase dest disp 
+
+instance Pop Ind where
+  pop (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_pop_membase dest 0 
+
+
+-- push/pop general purpose registers
+
+pushad = ensureBufferSize x86_max_instruction_bytes >> x86_pushad
+popad  = ensureBufferSize x86_max_instruction_bytes >> x86_popad
+
+
+-- push/pop EFLAGS
+
+pushfd = ensureBufferSize x86_max_instruction_bytes >> x86_pushfd
+popfd  = ensureBufferSize x86_max_instruction_bytes >> x86_popfd
+
+
+-- loop according to ECX couter
+
+loop   :: Word8 -> CodeGen e s ()
+loop w   = ensureBufferSize x86_max_instruction_bytes >> x86_loop w
+
+loope  :: Word8 -> CodeGen e s ()
+loope w  = ensureBufferSize x86_max_instruction_bytes >> x86_loope w
+
+loopne :: Word8 -> CodeGen e s ()
+loopne w = ensureBufferSize x86_max_instruction_bytes >> x86_loopne w
+
+
+-- jump
+
+class Jmp a where
+  jmp :: a -> CodeGen e s ()
+
+instance Jmp Word8 where
+  jmp imm = ensureBufferSize x86_max_instruction_bytes >> x86_jump8 imm 
+
+instance Jmp Word32 where
+  jmp imm = ensureBufferSize x86_max_instruction_bytes >> x86_jump32 imm 
+
+instance Jmp Reg32 where
+  jmp (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_jump_reg dest 
+
+instance Jmp Addr where
+  jmp (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_jump_mem dest 
+
+instance Jmp (Disp, Reg32) where
+  jmp (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_jump_membase dest disp 
+
+instance Jmp Ind where
+  jmp (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_jump_membase dest 0 
+
+instance Jmp Label where
+  jmp l = do ensureBufferSize x86_max_instruction_bytes >> x86_jump32 0
+             emitFixup l (-4) Fixup32
+            
+-- jump on condition code (branch)
+
+class Ja a where
+  ja :: a -> CodeGen e s ()
+
+instance Ja Word8 where
+  ja imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_a imm False
+
+instance Ja Word32 where
+  ja imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_a imm False
+
+instance Ja Label where
+  ja l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_a 0 False
+            emitFixup l (-4) Fixup32
+
+class Jae a where
+  jae :: a -> CodeGen e s ()
+
+instance Jae Word8 where
+  jae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_ae imm False
+
+instance Jae Word32 where
+  jae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ae imm False
+
+instance Jae Label where
+  jae l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ae 0 False
+             emitFixup l (-4) Fixup32
+
+class Jb a where
+  jb :: a -> CodeGen e s ()
+
+instance Jb Word8 where
+  jb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_b imm False
+
+instance Jb Word32 where
+  jb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_b imm False
+
+instance Jb Label where
+  jb l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_b 0 False
+            emitFixup l (-4) Fixup32
+
+class Jbe a where
+  jbe :: a -> CodeGen e s ()
+
+instance Jbe Word8 where
+  jbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_be imm False
+
+instance Jbe Word32 where
+  jbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_be imm False
+
+instance Jbe Label where
+  jbe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_be 0 False
+             emitFixup l (-4) Fixup32
+
+class Jc a where
+  jc :: a -> CodeGen e s ()
+
+instance Jc Word8 where
+  jc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_c imm False
+
+instance Jc Word32 where
+  jc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_c imm False
+
+instance Jc Label where
+  jc l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_c 0 False
+            emitFixup l (-4) Fixup32
+
+class Je a where
+  je :: a -> CodeGen e s ()
+
+instance Je Word8 where
+  je imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_e imm False
+
+instance Je Word32 where
+  je imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_e imm False
+
+instance Je Label where
+  je l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_e 0 False
+            emitFixup l (-4) Fixup32
+
+class Jna a where
+  jna :: a -> CodeGen e s ()
+
+instance Jna Word8 where
+  jna imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_na imm False
+
+instance Jna Word32 where
+  jna imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_na imm False
+
+instance Jna Label where
+  jna l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_na 0 False
+             emitFixup l (-4) Fixup32
+
+class Jnae a where
+  jnae :: a -> CodeGen e s ()
+
+instance Jnae Word8 where
+  jnae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_nae imm False
+
+instance Jnae Word32 where
+  jnae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nae imm False
+
+instance Jnae Label where
+  jnae l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nae 0 False
+              emitFixup l (-4) Fixup32
+
+class Jnb a where
+  jnb :: a -> CodeGen e s ()
+
+instance Jnb Word8 where
+  jnb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_nb imm False
+
+instance Jnb Word32 where
+  jnb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nb imm False
+
+instance Jnb Label where
+  jnb l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nb 0 False
+             emitFixup l (-4) Fixup32
+
+class Jnbe a where
+  jnbe :: a -> CodeGen e s ()
+
+instance Jnbe Word8 where
+  jnbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_nbe imm False
+
+instance Jnbe Word32 where
+  jnbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nbe imm False
+
+instance Jnbe Label where
+  jnbe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nbe 0 False
+              emitFixup l (-4) Fixup32
+
+class Jnc a where
+  jnc :: a -> CodeGen e s ()
+
+instance Jnc Word8 where
+  jnc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_nc imm False
+
+instance Jnc Word32 where
+  jnc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nc imm False
+
+instance Jnc Label where
+  jnc l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nc 0 False
+             emitFixup l (-4) Fixup32
+
+class Jne a where
+  jne :: a -> CodeGen e s ()
+
+instance Jne Word8 where
+  jne imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_ne imm False
+
+instance Jne Word32 where
+  jne imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ne imm False
+
+instance Jne Label where
+  jne l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ne 0 False
+             emitFixup l (-4) Fixup32
+
+class Jnp a where
+  jnp :: a -> CodeGen e s ()
+
+instance Jnp Word8 where
+  jnp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_np imm False
+
+instance Jnp Word32 where
+  jnp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_np imm False
+
+instance Jnp Label where
+  jnp l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_np 0 False
+             emitFixup l (-4) Fixup32
+
+class Jnz a where
+  jnz :: a -> CodeGen e s ()
+
+instance Jnz Word8 where
+  jnz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_nz imm False
+
+instance Jnz Word32 where
+  jnz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nz imm False
+
+instance Jnz Label where
+  jnz l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nz 0 False
+             emitFixup l (-4) Fixup32
+
+class Jp a where
+  jp :: a -> CodeGen e s ()
+
+instance Jp Word8 where
+  jp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_p imm False
+
+instance Jp Word32 where
+  jp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_p imm False
+
+instance Jp Label where
+  jp l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_p 0 False
+            emitFixup l (-4) Fixup32
+
+class Jpe a where
+  jpe :: a -> CodeGen e s ()
+
+instance Jpe Word8 where
+  jpe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_pe imm False
+
+instance Jpe Word32 where
+  jpe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_pe imm False
+
+instance Jpe Label where
+  jpe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_pe 0 False
+             emitFixup l (-4) Fixup32
+
+class Jpo a where
+  jpo :: a -> CodeGen e s ()
+
+instance Jpo Word8 where
+  jpo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_po imm False
+
+instance Jpo Word32 where
+  jpo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_po imm False
+
+instance Jpo Label where
+  jpo l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_po 0 False
+             emitFixup l (-4) Fixup32
+
+class Jz a where
+  jz :: a -> CodeGen e s ()
+
+instance Jz Word8 where
+  jz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_z imm False
+
+instance Jz Word32 where
+  jz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_z imm False
+
+instance Jz Label where
+  jz l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_z 0 False
+            emitFixup l (-4) Fixup32
+
+class Jg a where
+  jg :: a -> CodeGen e s ()
+
+instance Jg Word8 where
+  jg imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_gt imm True
+
+instance Jg Word32 where
+  jg imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt imm True
+
+instance Jg Label where
+  jg l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt 0 True
+            emitFixup l (-4) Fixup32
+
+class Jge a where
+  jge :: a -> CodeGen e s ()
+
+instance Jge Word8 where
+  jge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_ge imm True
+
+instance Jge Word32 where
+  jge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge imm True
+
+instance Jge Label where
+  jge l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge 0 True
+             emitFixup l (-4) Fixup32
+
+class Jl a where
+  jl :: a -> CodeGen e s ()
+
+instance Jl Word8 where
+  jl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_lt imm True
+
+instance Jl Word32 where
+  jl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt imm True
+
+instance Jl Label where
+  jl l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt 0 True
+            emitFixup l (-4) Fixup32
+
+class Jle a where
+  jle :: a -> CodeGen e s ()
+
+instance Jle Word8 where
+  jle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_le imm True
+
+instance Jle Word32 where
+  jle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le imm True
+
+instance Jle Label where
+  jle l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le 0 True
+             emitFixup l (-4) Fixup32
+
+class Jng a where
+  jng :: a -> CodeGen e s ()
+
+instance Jng Word8 where
+  jng imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_le imm True
+
+instance Jng Word32 where
+  jng imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le imm True
+
+instance Jng Label where
+  jng l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le 0 True
+             emitFixup l (-4) Fixup32
+
+class Jnge a where
+  jnge :: a -> CodeGen e s ()
+
+instance Jnge Word8 where
+  jnge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_lt imm True
+
+instance Jnge Word32 where
+  jnge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt imm True
+
+instance Jnge Label where
+  jnge l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt 0 True
+              emitFixup l (-4) Fixup32
+
+class Jnl a where
+  jnl :: a -> CodeGen e s ()
+
+instance Jnl Word8 where
+  jnl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_ge imm True
+
+instance Jnl Word32 where
+  jnl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge imm True
+
+instance Jnl Label where
+  jnl l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge 0 True
+             emitFixup l (-4) Fixup32
+
+class Jnle a where
+  jnle :: a -> CodeGen e s ()
+
+instance Jnle Word8 where
+  jnle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_gt imm True
+
+instance Jnle Word32 where
+  jnle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt imm True
+
+instance Jnle Label where
+  jnle l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt 0 True
+              emitFixup l (-4) Fixup32
+
+class Jno a where
+  jno :: a -> CodeGen e s ()
+
+instance Jno Word8 where
+  jno imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_no imm True
+
+instance Jno Word32 where
+  jno imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_no imm True
+
+instance Jno Label where
+  jno l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_no 0 True
+             emitFixup l (-4) Fixup32
+
+class Jns a where
+  jns :: a -> CodeGen e s ()
+
+instance Jns Word8 where
+  jns imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_ns imm True
+
+instance Jns Word32 where
+  jns imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ns imm True
+
+instance Jns Label where
+  jns l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ns 0 True
+             emitFixup l (-4) Fixup32
+
+class Jo a where
+  jo :: a -> CodeGen e s ()
+
+instance Jo Word8 where
+  jo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_o imm True
+
+instance Jo Word32 where
+  jo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_o imm True
+
+instance Jo Label where
+  jo l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_o 0 True
+            emitFixup l (-4) Fixup32
+
+class Js a where
+  js :: a -> CodeGen e s ()
+
+instance Js Word8 where
+  js imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch8 x86_cc_s imm True
+
+instance Js Word32 where
+  js imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_s imm True
+
+instance Js Label where
+  js l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_s 0 True
+            emitFixup l (-4) Fixup32
+
+-- jump if ecx register is 0
+
+jecxz :: Word8 -> CodeGen e s ()
+jecxz w = ensureBufferSize x86_max_instruction_bytes >> x86_jecxz w
+
+
+-- set byte on condition code
+
+class Seta a where
+  seta :: a -> CodeGen e s ()
+
+instance Seta Reg8 where
+  seta (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_a dest False
+
+instance Seta Addr where
+  seta (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_a dest False
+
+instance Seta (Disp, Reg32) where
+  seta (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_a dest disp False
+
+instance Seta Ind where
+  seta (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_a dest 0 False
+
+class Setae a where
+  setae :: a -> CodeGen e s ()
+
+instance Setae Reg8 where
+  setae (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_ae dest False
+
+instance Setae Addr where
+  setae (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_ae dest False
+
+instance Setae (Disp, Reg32) where
+  setae (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ae dest disp False
+
+instance Setae Ind where
+  setae (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ae dest 0 False
+
+class Setb a where
+  setb :: a -> CodeGen e s ()
+
+instance Setb Reg8 where
+  setb (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_b dest False
+
+instance Setb Addr where
+  setb (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_b dest False
+
+instance Setb (Disp, Reg32) where
+  setb (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_b dest disp False
+
+instance Setb Ind where
+  setb (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_b dest 0 False
+
+class Setbe a where
+  setbe :: a -> CodeGen e s ()
+
+instance Setbe Reg8 where
+  setbe (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_be dest False
+
+instance Setbe Addr where
+  setbe (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_be dest False
+
+instance Setbe (Disp, Reg32) where
+  setbe (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_be dest disp False
+
+instance Setbe Ind where
+  setbe (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_be dest 0 False
+
+class Setc a where
+  setc :: a -> CodeGen e s ()
+
+instance Setc Reg8 where
+  setc (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_c dest False
+
+instance Setc Addr where
+  setc (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_c dest False
+
+instance Setc (Disp, Reg32) where
+  setc (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_c dest disp False
+
+instance Setc Ind where
+  setc (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_c dest 0 False
+
+class Sete a where
+  sete :: a -> CodeGen e s ()
+
+instance Sete Reg8 where
+  sete (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_e dest False
+
+instance Sete Addr where
+  sete (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_e dest False
+
+instance Sete (Disp, Reg32) where
+  sete (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_e dest disp False
+
+instance Sete Ind where
+  sete (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_e dest 0 False
+
+class Setna a where
+  setna :: a -> CodeGen e s ()
+
+instance Setna Reg8 where
+  setna (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_na dest False
+
+instance Setna Addr where
+  setna (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_na dest False
+
+instance Setna (Disp, Reg32) where
+  setna (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_na dest disp False
+
+instance Setna Ind where
+  setna (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_na dest 0 False
+
+class Setnae a where
+  setnae :: a -> CodeGen e s ()
+
+instance Setnae Reg8 where
+  setnae (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_nae dest False
+
+instance Setnae Addr where
+  setnae (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_nae dest False
+
+instance Setnae (Disp, Reg32) where
+  setnae (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nae dest disp False
+
+instance Setnae Ind where
+  setnae (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nae dest 0 False
+
+class Setnb a where
+  setnb :: a -> CodeGen e s ()
+
+instance Setnb Reg8 where
+  setnb (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_nb dest False
+
+instance Setnb Addr where
+  setnb (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_nb dest False
+
+instance Setnb (Disp, Reg32) where
+  setnb (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nb dest disp False
+
+instance Setnb Ind where
+  setnb (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nb dest 0 False
+
+class Setnbe a where
+  setnbe :: a -> CodeGen e s ()
+
+instance Setnbe Reg8 where
+  setnbe (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_nbe dest False
+
+instance Setnbe Addr where
+  setnbe (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_nbe dest False
+
+instance Setnbe (Disp, Reg32) where
+  setnbe (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nbe dest disp False
+
+instance Setnbe Ind where
+  setnbe (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nbe dest 0 False
+
+class Setnc a where
+  setnc :: a -> CodeGen e s ()
+
+instance Setnc Reg8 where
+  setnc (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_nc dest False
+
+instance Setnc Addr where
+  setnc (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_nc dest False
+
+instance Setnc (Disp, Reg32) where
+  setnc (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nc dest disp False
+
+instance Setnc Ind where
+  setnc (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nc dest 0 False
+
+class Setne a where
+  setne :: a -> CodeGen e s ()
+
+instance Setne Reg8 where
+  setne (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_ne dest False
+
+instance Setne Addr where
+  setne (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_ne dest False
+
+instance Setne (Disp, Reg32) where
+  setne (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ne dest disp False
+
+instance Setne Ind where
+  setne (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ne dest 0 False
+
+class Setnp a where
+  setnp :: a -> CodeGen e s ()
+
+instance Setnp Reg8 where
+  setnp (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_np dest False
+
+instance Setnp Addr where
+  setnp (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_np dest False
+
+instance Setnp (Disp, Reg32) where
+  setnp (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_np dest disp False
+
+instance Setnp Ind where
+  setnp (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_np dest 0 False
+
+class Setnz a where
+  setnz :: a -> CodeGen e s ()
+
+instance Setnz Reg8 where
+  setnz (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_nz dest False
+
+instance Setnz Addr where
+  setnz (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_nz dest False
+
+instance Setnz (Disp, Reg32) where
+  setnz (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nz dest disp False
+
+instance Setnz Ind where
+  setnz (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_nz dest 0 False
+
+class Setp a where
+  setp :: a -> CodeGen e s ()
+
+instance Setp Reg8 where
+  setp (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_p dest False
+
+instance Setp Addr where
+  setp (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_p dest False
+
+instance Setp (Disp, Reg32) where
+  setp (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_p dest disp False
+
+instance Setp Ind where
+  setp (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_p dest 0 False
+
+class Setpe a where
+  setpe :: a -> CodeGen e s ()
+
+instance Setpe Reg8 where
+  setpe (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_pe dest False
+
+instance Setpe Addr where
+  setpe (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_pe dest False
+
+instance Setpe (Disp, Reg32) where
+  setpe (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_pe dest disp False
+
+instance Setpe Ind where
+  setpe (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_pe dest 0 False
+
+class Setpo a where
+  setpo :: a -> CodeGen e s ()
+
+instance Setpo Reg8 where
+  setpo (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_po dest False
+
+instance Setpo Addr where
+  setpo (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_po dest False
+
+instance Setpo (Disp, Reg32) where
+  setpo (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_po dest disp False
+
+instance Setpo Ind where
+  setpo (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_po dest 0 False
+
+class Setg a where
+  setg :: a -> CodeGen e s ()
+
+instance Setg Reg8 where
+  setg (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_gt dest True
+
+instance Setg Addr where
+  setg (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_gt dest True
+
+instance Setg (Disp, Reg32) where
+  setg (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_gt dest disp True
+
+instance Setg Ind where
+  setg (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_gt dest 0 True
+
+class Setge a where
+  setge :: a -> CodeGen e s ()
+
+instance Setge Reg8 where
+  setge (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_ge dest True
+
+instance Setge Addr where
+  setge (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_ge dest True
+
+instance Setge (Disp, Reg32) where
+  setge (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ge dest disp True
+
+instance Setge Ind where
+  setge (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ge dest 0 True
+
+class Setl a where
+  setl :: a -> CodeGen e s ()
+
+instance Setl Reg8 where
+  setl (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_lt dest True
+
+instance Setl Addr where
+  setl (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_lt dest True
+
+instance Setl (Disp, Reg32) where
+  setl (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_lt dest disp True
+
+instance Setl Ind where
+  setl (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_lt dest 0 True
+
+class Setle a where
+  setle :: a -> CodeGen e s ()
+
+instance Setle Reg8 where
+  setle (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_le dest True
+
+instance Setle Addr where
+  setle (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_le dest True
+
+instance Setle (Disp, Reg32) where
+  setle (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_le dest disp True
+
+instance Setle Ind where
+  setle (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_le dest 0 True
+
+class Setng a where
+  setng :: a -> CodeGen e s ()
+
+instance Setng Reg8 where
+  setng (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_le dest True
+
+instance Setng Addr where
+  setng (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_le dest True
+
+instance Setng (Disp, Reg32) where
+  setng (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_le dest disp True
+
+instance Setng Ind where
+  setng (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_le dest 0 True
+
+class Setnge a where
+  setnge :: a -> CodeGen e s ()
+
+instance Setnge Reg8 where
+  setnge (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_lt dest True
+
+instance Setnge Addr where
+  setnge (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_lt dest True
+
+instance Setnge (Disp, Reg32) where
+  setnge (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_lt dest disp True
+
+instance Setnge Ind where
+  setnge (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_lt dest 0 True
+
+class Setnl a where
+  setnl :: a -> CodeGen e s ()
+
+instance Setnl Reg8 where
+  setnl (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_ge dest True
+
+instance Setnl Addr where
+  setnl (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_ge dest True
+
+instance Setnl (Disp, Reg32) where
+  setnl (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ge dest disp True
+
+instance Setnl Ind where
+  setnl (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ge dest 0 True
+
+class Setnle a where
+  setnle :: a -> CodeGen e s ()
+
+instance Setnle Reg8 where
+  setnle (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_gt dest True
+
+instance Setnle Addr where
+  setnle (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_gt dest True
+
+instance Setnle (Disp, Reg32) where
+  setnle (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_gt dest disp True
+
+instance Setnle Ind where
+  setnle (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_gt dest 0 True
+
+class Setno a where
+  setno :: a -> CodeGen e s ()
+
+instance Setno Reg8 where
+  setno (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_no dest True
+
+instance Setno Addr where
+  setno (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_no dest True
+
+instance Setno (Disp, Reg32) where
+  setno (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_no dest disp True
+
+instance Setno Ind where
+  setno (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_no dest 0 True
+
+class Setns a where
+  setns :: a -> CodeGen e s ()
+
+instance Setns Reg8 where
+  setns (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_ns dest True
+
+instance Setns Addr where
+  setns (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_ns dest True
+
+instance Setns (Disp, Reg32) where
+  setns (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ns dest disp True
+
+instance Setns Ind where
+  setns (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_ns dest 0 True
+
+class Seto a where
+  seto :: a -> CodeGen e s ()
+
+instance Seto Reg8 where
+  seto (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_o dest True
+
+instance Seto Addr where
+  seto (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_o dest True
+
+instance Seto (Disp, Reg32) where
+  seto (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_o dest disp True
+
+instance Seto Ind where
+  seto (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_o dest 0 True
+
+class Sets a where
+  sets :: a -> CodeGen e s ()
+
+instance Sets Reg8 where
+  sets (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_s dest True
+
+instance Sets Addr where
+  sets (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_s dest True
+
+instance Sets (Disp, Reg32) where
+  sets (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_s dest disp True
+
+instance Sets Ind where
+  sets (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_s dest 0 True
+
+class Setz a where
+  setz :: a -> CodeGen e s ()
+
+instance Setz Reg8 where
+  setz (Reg8 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_reg x86_cc_z dest False
+
+instance Setz Addr where
+  setz (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_mem x86_cc_z dest False
+
+instance Setz (Disp, Reg32) where
+  setz (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_z dest disp False
+
+instance Setz Ind where
+  setz (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_set_membase x86_cc_z dest 0 False
+
+
+-- call procedure
+
+class Call a where
+  call :: a -> CodeGen e s ()
+
+instance Call Word32 where
+  call imm = ensureBufferSize x86_max_instruction_bytes >> x86_call_imm imm 
+
+instance Call Label where
+  call l = do ensureBufferSize x86_max_instruction_bytes >> x86_call_imm 0
+              emitFixup l (-4) Fixup32
+
+instance Call Reg32 where
+  call (Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_call_reg dest 
+
+instance Call Addr where
+  call (Addr dest) = ensureBufferSize x86_max_instruction_bytes >> x86_call_mem dest 
+
+instance Call (Disp, Reg32) where
+  call (Disp disp, Reg32 dest) = ensureBufferSize x86_max_instruction_bytes >> x86_call_membase dest disp 
+
+instance Call Ind where
+  call (Ind (Reg32 dest)) = ensureBufferSize x86_max_instruction_bytes >> x86_call_membase dest 0 
+
+instance Call (FunPtr a) where
+  call f = ensureBufferSize x86_max_instruction_bytes >> x86_call_hs f
+
+
+-- return from procedure
+
+ret :: CodeGen e s ()
+ret = ensureBufferSize x86_max_instruction_bytes >> x86_ret
+
+retN :: Word16 -> CodeGen e s ()
+retN n = ensureBufferSize x86_max_instruction_bytes >> x86_ret_imm n
+
+
+-- make stack frame
+
+enter :: Word16 -> CodeGen e s ()
+enter w = ensureBufferSize x86_max_instruction_bytes >> x86_enter w
+
+
+-- conditional move
+
+class Cmova a b where
+  cmova :: a -> b -> CodeGen e s ()
+
+instance Cmova Reg32 Reg32 where
+  cmova (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_a False dest source
+
+instance Cmova Reg32 Addr where
+  cmova (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_a False dest source
+
+instance Cmova Reg32 (Disp, Reg32) where
+  cmova (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_a False dest source disp
+
+instance Cmova Reg32 Ind where
+  cmova (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_a False dest source 0
+
+class Cmovae a b where
+  cmovae :: a -> b -> CodeGen e s ()
+
+instance Cmovae Reg32 Reg32 where
+  cmovae (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_ae False dest source
+
+instance Cmovae Reg32 Addr where
+  cmovae (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_ae False dest source
+
+instance Cmovae Reg32 (Disp, Reg32) where
+  cmovae (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ae False dest source disp
+
+instance Cmovae Reg32 Ind where
+  cmovae (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ae False dest source 0
+
+class Cmovb a b where
+  cmovb :: a -> b -> CodeGen e s ()
+
+instance Cmovb Reg32 Reg32 where
+  cmovb (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_b False dest source
+
+instance Cmovb Reg32 Addr where
+  cmovb (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_b False dest source
+
+instance Cmovb Reg32 (Disp, Reg32) where
+  cmovb (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_b False dest source disp
+
+instance Cmovb Reg32 Ind where
+  cmovb (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_b False dest source 0
+
+class Cmovbe a b where
+  cmovbe :: a -> b -> CodeGen e s ()
+
+instance Cmovbe Reg32 Reg32 where
+  cmovbe (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_be False dest source
+
+instance Cmovbe Reg32 Addr where
+  cmovbe (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_be False dest source
+
+instance Cmovbe Reg32 (Disp, Reg32) where
+  cmovbe (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_be False dest source disp
+
+instance Cmovbe Reg32 Ind where
+  cmovbe (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_be False dest source 0
+
+class Cmovc a b where
+  cmovc :: a -> b -> CodeGen e s ()
+
+instance Cmovc Reg32 Reg32 where
+  cmovc (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_c False dest source
+
+instance Cmovc Reg32 Addr where
+  cmovc (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_c False dest source
+
+instance Cmovc Reg32 (Disp, Reg32) where
+  cmovc (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_c False dest source disp
+
+instance Cmovc Reg32 Ind where
+  cmovc (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_c False dest source 0
+
+class Cmove a b where
+  cmove :: a -> b -> CodeGen e s ()
+
+instance Cmove Reg32 Reg32 where
+  cmove (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_e False dest source
+
+instance Cmove Reg32 Addr where
+  cmove (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_e False dest source
+
+instance Cmove Reg32 (Disp, Reg32) where
+  cmove (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_e False dest source disp
+
+instance Cmove Reg32 Ind where
+  cmove (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_e False dest source 0
+
+class Cmovna a b where
+  cmovna :: a -> b -> CodeGen e s ()
+
+instance Cmovna Reg32 Reg32 where
+  cmovna (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_na False dest source
+
+instance Cmovna Reg32 Addr where
+  cmovna (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_na False dest source
+
+instance Cmovna Reg32 (Disp, Reg32) where
+  cmovna (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_na False dest source disp
+
+instance Cmovna Reg32 Ind where
+  cmovna (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_na False dest source 0
+
+class Cmovnae a b where
+  cmovnae :: a -> b -> CodeGen e s ()
+
+instance Cmovnae Reg32 Reg32 where
+  cmovnae (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_nae False dest source
+
+instance Cmovnae Reg32 Addr where
+  cmovnae (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_nae False dest source
+
+instance Cmovnae Reg32 (Disp, Reg32) where
+  cmovnae (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nae False dest source disp
+
+instance Cmovnae Reg32 Ind where
+  cmovnae (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nae False dest source 0
+
+class Cmovnb a b where
+  cmovnb :: a -> b -> CodeGen e s ()
+
+instance Cmovnb Reg32 Reg32 where
+  cmovnb (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_nb False dest source
+
+instance Cmovnb Reg32 Addr where
+  cmovnb (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_nb False dest source
+
+instance Cmovnb Reg32 (Disp, Reg32) where
+  cmovnb (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nb False dest source disp
+
+instance Cmovnb Reg32 Ind where
+  cmovnb (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nb False dest source 0
+
+class Cmovnbe a b where
+  cmovnbe :: a -> b -> CodeGen e s ()
+
+instance Cmovnbe Reg32 Reg32 where
+  cmovnbe (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_nbe False dest source
+
+instance Cmovnbe Reg32 Addr where
+  cmovnbe (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_nbe False dest source
+
+instance Cmovnbe Reg32 (Disp, Reg32) where
+  cmovnbe (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nbe False dest source disp
+
+instance Cmovnbe Reg32 Ind where
+  cmovnbe (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nbe False dest source 0
+
+class Cmovnc a b where
+  cmovnc :: a -> b -> CodeGen e s ()
+
+instance Cmovnc Reg32 Reg32 where
+  cmovnc (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_nc False dest source
+
+instance Cmovnc Reg32 Addr where
+  cmovnc (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_nc False dest source
+
+instance Cmovnc Reg32 (Disp, Reg32) where
+  cmovnc (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nc False dest source disp
+
+instance Cmovnc Reg32 Ind where
+  cmovnc (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nc False dest source 0
+
+class Cmovne a b where
+  cmovne :: a -> b -> CodeGen e s ()
+
+instance Cmovne Reg32 Reg32 where
+  cmovne (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_ne False dest source
+
+instance Cmovne Reg32 Addr where
+  cmovne (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_ne False dest source
+
+instance Cmovne Reg32 (Disp, Reg32) where
+  cmovne (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ne False dest source disp
+
+instance Cmovne Reg32 Ind where
+  cmovne (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ne False dest source 0
+
+class Cmovnp a b where
+  cmovnp :: a -> b -> CodeGen e s ()
+
+instance Cmovnp Reg32 Reg32 where
+  cmovnp (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_np False dest source
+
+instance Cmovnp Reg32 Addr where
+  cmovnp (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_np False dest source
+
+instance Cmovnp Reg32 (Disp, Reg32) where
+  cmovnp (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_np False dest source disp
+
+instance Cmovnp Reg32 Ind where
+  cmovnp (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_np False dest source 0
+
+class Cmovnz a b where
+  cmovnz :: a -> b -> CodeGen e s ()
+
+instance Cmovnz Reg32 Reg32 where
+  cmovnz (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_nz False dest source
+
+instance Cmovnz Reg32 Addr where
+  cmovnz (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_nz False dest source
+
+instance Cmovnz Reg32 (Disp, Reg32) where
+  cmovnz (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nz False dest source disp
+
+instance Cmovnz Reg32 Ind where
+  cmovnz (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_nz False dest source 0
+
+class Cmovp a b where
+  cmovp :: a -> b -> CodeGen e s ()
+
+instance Cmovp Reg32 Reg32 where
+  cmovp (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_p False dest source
+
+instance Cmovp Reg32 Addr where
+  cmovp (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_p False dest source
+
+instance Cmovp Reg32 (Disp, Reg32) where
+  cmovp (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_p False dest source disp
+
+instance Cmovp Reg32 Ind where
+  cmovp (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_p False dest source 0
+
+class Cmovpe a b where
+  cmovpe :: a -> b -> CodeGen e s ()
+
+instance Cmovpe Reg32 Reg32 where
+  cmovpe (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_pe False dest source
+
+instance Cmovpe Reg32 Addr where
+  cmovpe (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_pe False dest source
+
+instance Cmovpe Reg32 (Disp, Reg32) where
+  cmovpe (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_pe False dest source disp
+
+instance Cmovpe Reg32 Ind where
+  cmovpe (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_pe False dest source 0
+
+class Cmovpo a b where
+  cmovpo :: a -> b -> CodeGen e s ()
+
+instance Cmovpo Reg32 Reg32 where
+  cmovpo (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_po False dest source
+
+instance Cmovpo Reg32 Addr where
+  cmovpo (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_po False dest source
+
+instance Cmovpo Reg32 (Disp, Reg32) where
+  cmovpo (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_po False dest source disp
+
+instance Cmovpo Reg32 Ind where
+  cmovpo (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_po False dest source 0
+
+class Cmovz a b where
+  cmovz :: a -> b -> CodeGen e s ()
+
+instance Cmovz Reg32 Reg32 where
+  cmovz (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_z False dest source
+
+instance Cmovz Reg32 Addr where
+  cmovz (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_z False dest source
+
+instance Cmovz Reg32 (Disp, Reg32) where
+  cmovz (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_z False dest source disp
+
+instance Cmovz Reg32 Ind where
+  cmovz (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_z False dest source 0
+
+class Cmovg a b where
+  cmovg :: a -> b -> CodeGen e s ()
+
+instance Cmovg Reg32 Reg32 where
+  cmovg (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_gt True dest source
+
+instance Cmovg Reg32 Addr where
+  cmovg (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_gt True dest source
+
+instance Cmovg Reg32 (Disp, Reg32) where
+  cmovg (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_gt True dest source disp
+
+instance Cmovg Reg32 Ind where
+  cmovg (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_gt True dest source 0
+
+class Cmovge a b where
+  cmovge :: a -> b -> CodeGen e s ()
+
+instance Cmovge Reg32 Reg32 where
+  cmovge (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_ge True dest source
+
+instance Cmovge Reg32 Addr where
+  cmovge (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_ge True dest source
+
+instance Cmovge Reg32 (Disp, Reg32) where
+  cmovge (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ge True dest source disp
+
+instance Cmovge Reg32 Ind where
+  cmovge (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ge True dest source 0
+
+class Cmovl a b where
+  cmovl :: a -> b -> CodeGen e s ()
+
+instance Cmovl Reg32 Reg32 where
+  cmovl (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_lt True dest source
+
+instance Cmovl Reg32 Addr where
+  cmovl (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_lt True dest source
+
+instance Cmovl Reg32 (Disp, Reg32) where
+  cmovl (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_lt True dest source disp
+
+instance Cmovl Reg32 Ind where
+  cmovl (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_lt True dest source 0
+
+class Cmovle a b where
+  cmovle :: a -> b -> CodeGen e s ()
+
+instance Cmovle Reg32 Reg32 where
+  cmovle (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_le True dest source
+
+instance Cmovle Reg32 Addr where
+  cmovle (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_le True dest source
+
+instance Cmovle Reg32 (Disp, Reg32) where
+  cmovle (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_le True dest source disp
+
+instance Cmovle Reg32 Ind where
+  cmovle (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_le True dest source 0
+
+class Cmovng a b where
+  cmovng :: a -> b -> CodeGen e s ()
+
+instance Cmovng Reg32 Reg32 where
+  cmovng (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_le True dest source
+
+instance Cmovng Reg32 Addr where
+  cmovng (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_le True dest source
+
+instance Cmovng Reg32 (Disp, Reg32) where
+  cmovng (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_le True dest source disp
+
+instance Cmovng Reg32 Ind where
+  cmovng (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_le True dest source 0
+
+class Cmovnge a b where
+  cmovnge :: a -> b -> CodeGen e s ()
+
+instance Cmovnge Reg32 Reg32 where
+  cmovnge (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_lt True dest source
+
+instance Cmovnge Reg32 Addr where
+  cmovnge (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_lt True dest source
+
+instance Cmovnge Reg32 (Disp, Reg32) where
+  cmovnge (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_lt True dest source disp
+
+instance Cmovnge Reg32 Ind where
+  cmovnge (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_lt True dest source 0
+
+class Cmovnl a b where
+  cmovnl :: a -> b -> CodeGen e s ()
+
+instance Cmovnl Reg32 Reg32 where
+  cmovnl (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_ge True dest source
+
+instance Cmovnl Reg32 Addr where
+  cmovnl (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_ge True dest source
+
+instance Cmovnl Reg32 (Disp, Reg32) where
+  cmovnl (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ge True dest source disp
+
+instance Cmovnl Reg32 Ind where
+  cmovnl (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ge True dest source 0
+
+class Cmovnle a b where
+  cmovnle :: a -> b -> CodeGen e s ()
+
+instance Cmovnle Reg32 Reg32 where
+  cmovnle (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_gt True dest source
+
+instance Cmovnle Reg32 Addr where
+  cmovnle (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_gt True dest source
+
+instance Cmovnle Reg32 (Disp, Reg32) where
+  cmovnle (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_gt True dest source disp
+
+instance Cmovnle Reg32 Ind where
+  cmovnle (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_gt True dest source 0
+
+class Cmovno a b where
+  cmovno :: a -> b -> CodeGen e s ()
+
+instance Cmovno Reg32 Reg32 where
+  cmovno (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_no True dest source
+
+instance Cmovno Reg32 Addr where
+  cmovno (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_no True dest source
+
+instance Cmovno Reg32 (Disp, Reg32) where
+  cmovno (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_no True dest source disp
+
+instance Cmovno Reg32 Ind where
+  cmovno (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_no True dest source 0
+
+class Cmovns a b where
+  cmovns :: a -> b -> CodeGen e s ()
+
+instance Cmovns Reg32 Reg32 where
+  cmovns (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_ns True dest source
+
+instance Cmovns Reg32 Addr where
+  cmovns (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_ns True dest source
+
+instance Cmovns Reg32 (Disp, Reg32) where
+  cmovns (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ns True dest source disp
+
+instance Cmovns Reg32 Ind where
+  cmovns (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_ns True dest source 0
+
+class Cmovo a b where
+  cmovo :: a -> b -> CodeGen e s ()
+
+instance Cmovo Reg32 Reg32 where
+  cmovo (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_o True dest source
+
+instance Cmovo Reg32 Addr where
+  cmovo (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_o True dest source
+
+instance Cmovo Reg32 (Disp, Reg32) where
+  cmovo (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_o True dest source disp
+
+instance Cmovo Reg32 Ind where
+  cmovo (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_o True dest source 0
+
+class Cmovs a b where
+  cmovs :: a -> b -> CodeGen e s ()
+
+instance Cmovs Reg32 Reg32 where
+  cmovs (Reg32 dest) (Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_reg x86_cc_s True dest source
+
+instance Cmovs Reg32 Addr where
+  cmovs (Reg32 dest) (Addr source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_mem x86_cc_s True dest source
+
+instance Cmovs Reg32 (Disp, Reg32) where
+  cmovs (Reg32 dest) (Disp disp, Reg32 source) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_s True dest source disp
+
+instance Cmovs Reg32 Ind where
+  cmovs (Reg32 dest) (Ind (Reg32 source)) = ensureBufferSize x86_max_instruction_bytes >> x86_cmov_membase x86_cc_s True dest source 0
+
+
+-- release stack frame
+
+leave :: CodeGen e s ()
+leave = ensureBufferSize x86_max_instruction_bytes >> x86_leave
+
+
+-- store ah into flags
+
+sahf :: CodeGen e s ()
+sahf = ensureBufferSize x86_max_instruction_bytes >> x86_sahf
+
+-- Floating point instructions
+
+fldz = ensureBufferSize x86_max_instruction_bytes >> x86_fldz
+fld1 = ensureBufferSize x86_max_instruction_bytes >> x86_fld1
+fldpi = ensureBufferSize x86_max_instruction_bytes >> x86_fldpi
+
+fstsw = ensureBufferSize x86_max_instruction_bytes >> x86_fstsw
+fnstsw = ensureBufferSize x86_max_instruction_bytes >> x86_fstsw
+
+fcompp = ensureBufferSize x86_max_instruction_bytes >> x86_fcompp
+fucompp = ensureBufferSize x86_max_instruction_bytes >> x86_fucompp
+
+fchs = ensureBufferSize x86_max_instruction_bytes >> x86_fchs
+frem = ensureBufferSize x86_max_instruction_bytes >> x86_frem
+
+fxch (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fxch idx
+
+fcomi (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fcomi idx
+fcomip (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fcomip idx
+fucomi (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fucomi idx
+fucomip (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fucomip idx
+
+class Fadd a b where
+    fadd :: a -> b -> CodeGen e s ()
+
+instance Fadd FPTopReg FPReg where
+    fadd FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fadd idx
+
+instance Fadd FPTopReg Addr where
+    fadd FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fadd a True
+
+instance Fadd FPTopReg (Disp, Reg32) where
+    fadd FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fadd r d True
+
+instance Fadd FPTopReg Ind where
+    fadd FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fadd r 0 True
+
+
+class Fsub a b where
+    fsub :: a -> b -> CodeGen e s ()
+
+instance Fsub FPTopReg FPReg where
+    fsub FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fsub idx
+
+instance Fsub FPTopReg Addr where
+    fsub FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fsub a True
+
+instance Fsub FPTopReg (Disp, Reg32) where
+    fsub FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fsub r d True
+
+instance Fsub FPTopReg Ind where
+    fsub FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fsub r 0 True
+
+
+class Fsubr a b where
+    fsubr :: a -> b -> CodeGen e s ()
+
+instance Fsubr FPTopReg FPReg where
+    fsubr FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fsubr idx
+
+instance Fsubr FPTopReg Addr where
+    fsubr FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fsubr a True
+
+instance Fsubr FPTopReg (Disp, Reg32) where
+    fsubr FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fsubr r d True
+
+instance Fsubr FPTopReg Ind where
+    fsubr FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fsubr r 0 True
+
+
+class Fmul a b where
+    fmul :: a -> b -> CodeGen e s ()
+
+instance Fmul FPTopReg FPReg where
+    fmul FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fmul idx
+
+instance Fmul FPTopReg Addr where
+    fmul FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fmul a True
+
+instance Fmul FPTopReg (Disp, Reg32) where
+    fmul FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fmul r d True
+
+instance Fmul FPTopReg Ind where
+    fmul FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fmul r 0 True
+
+
+class Fdiv a b where
+    fdiv :: a -> b -> CodeGen e s ()
+
+instance Fdiv FPTopReg FPReg where
+    fdiv FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fdiv idx
+
+instance Fdiv FPTopReg Addr where
+    fdiv FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fdiv a True
+
+instance Fdiv FPTopReg (Disp, Reg32) where
+    fdiv FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fdiv r d True
+
+instance Fdiv FPTopReg Ind where
+    fdiv FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fdiv r 0 True
+
+
+class Fdivr a b where
+    fdivr :: a -> b -> CodeGen e s ()
+
+instance Fdivr FPTopReg FPReg where
+    fdivr FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fdivr idx
+
+instance Fdivr FPTopReg Addr where
+    fdivr FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fdivr a True
+
+instance Fdivr FPTopReg (Disp, Reg32) where
+    fdivr FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fdivr r d True
+
+instance Fdivr FPTopReg Ind where
+    fdivr FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fdivr r 0 True
+
+
+class Fcom a b where
+    fcom :: a -> b -> CodeGen e s ()
+
+instance Fcom FPTopReg FPReg where
+    fcom FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fcom idx
+
+instance Fcom FPTopReg Addr where
+    fcom FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fcom a True
+
+instance Fcom FPTopReg (Disp, Reg32) where
+    fcom FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fcom r d True
+
+instance Fcom FPTopReg Ind where
+    fcom FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fcom r 0 True
+
+
+class Fcomp a b where
+    fcomp :: a -> b -> CodeGen e s ()
+
+instance Fcomp FPTopReg FPReg where
+    fcomp FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op x86_fcomp idx
+
+instance Fcomp FPTopReg Addr where
+    fcomp FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_mem x86_fcomp a True
+
+instance Fcomp FPTopReg (Disp, Reg32) where
+    fcomp FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fcomp r d True
+
+instance Fcomp FPTopReg Ind where
+    fcomp FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fcomp r 0 True
+
+
+class Fld a b where
+    fld :: a -> b -> CodeGen e s ()
+
+instance Fld FPTopReg FPReg where
+    fld FPTopReg (FPReg idx) = ensureBufferSize x86_max_instruction_bytes >> x86_fld_reg idx
+
+instance Fld FPTopReg Addr where 
+    fld FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fld a True
+
+instance Fld FPTopReg (Disp, Reg32) where 
+    fld FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fld_membase r d True
+
+instance Fld FPTopReg Ind where 
+    fld FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fld_membase r 0 True
+
+class Fld80 a b where
+    fld80 :: a -> b -> CodeGen e s ()
+
+instance Fld80 FPTopReg Addr where 
+    fld80 FPTopReg (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fld80_mem a
+
+instance Fld80 FPTopReg (Disp, Reg32) where 
+    fld80 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fld80_membase r d
+
+instance Fld80 FPTopReg Ind where 
+    fld80 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fld80_membase r 0
+
+class Fst a where
+    fst :: a -> CodeGen e s ()
+
+instance Fst Addr where
+    fst (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fst a True False
+
+instance Fst (Disp, Reg32) where
+    fst (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fst_membase r d True False
+
+instance Fst Ind where
+    fst (Ind (Reg32 r)) =  ensureBufferSize x86_max_instruction_bytes >> x86_fst_membase r 0 True False
+
+class Fstp a where
+    fstp :: a -> CodeGen e s ()
+
+instance Fstp FPReg where
+    fstp (FPReg r) = ensureBufferSize x86_max_instruction_bytes >> x86_fstp r
+
+instance Fstp Addr where
+    fstp (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fst a True True
+
+instance Fstp (Disp, Reg32) where
+    fstp (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fst_membase r d True True
+
+instance Fstp Ind where
+    fstp (Ind (Reg32 r)) =  ensureBufferSize x86_max_instruction_bytes >> x86_fst_membase r 0 True True
+
+
+class Fst80 a where
+    fst80 :: a -> CodeGen e s ()
+
+instance Fst80 Addr where
+    fst80 (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fst80_mem a
+
+instance Fst80 (Disp, Reg32) where
+    fst80 (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fst80_membase r d
+
+instance Fst80 Ind where
+    fst80 (Ind (Reg32 r)) =  ensureBufferSize x86_max_instruction_bytes >> x86_fst80_membase r 0
+
+
+class Fnstcw a where
+    fnstcw :: a -> CodeGen e s ()
+
+instance Fnstcw Addr where
+    fnstcw (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fnstcw a
+
+instance Fnstcw (Disp, Reg32) where
+    fnstcw (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fnstcw_membase r d
+
+instance Fnstcw Ind where
+    fnstcw (Ind (Reg32 r)) =  ensureBufferSize x86_max_instruction_bytes >> x86_fnstcw_membase r 0
+
+
+class Fldcw a where
+    fldcw :: a -> CodeGen e s ()
+
+instance Fldcw Addr where
+    fldcw (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fldcw a
+
+instance Fldcw (Disp, Reg32) where
+    fldcw (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fldcw_membase r d
+
+instance Fldcw Ind where
+    fldcw (Ind (Reg32 r)) =  ensureBufferSize x86_max_instruction_bytes >> x86_fldcw_membase r 0
+
+
+class Fild a where
+    fild :: a -> CodeGen e s ()
+
+instance Fild Addr where 
+    fild (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fild a False
+
+instance Fild (Disp, Reg32) where 
+    fild (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r d False
+
+instance Fild Ind where 
+    fild (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r 0 False
+
+
+class Fist a where
+    fist :: a -> CodeGen e s ()
+
+instance Fist (Disp, Reg32) where 
+    fist (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r d False
+
+instance Fist Ind where 
+    fist (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r 0 False
+
+
+class Fistp a where
+    fistp :: a -> CodeGen e s ()
+
+instance Fistp Addr where
+    fistp (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop a False
+
+instance Fistp (Disp, Reg32) where 
+    fistp (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r d False
+
+instance Fistp Ind where 
+    fistp (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r 0 False
+
+
+class Sqrtsd a b where
+    sqrtsd :: a -> b -> CodeGen e s ()
+
+instance Sqrtsd XMMReg XMMReg where
+    sqrtsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_reg x86_sse_sd xd xs
+
+instance Sqrtsd XMMReg Addr where
+    sqrtsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_mem x86_sse_sd xd a
+
+instance Sqrtsd XMMReg Ind where
+    sqrtsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_sd xd r 0
+
+instance Sqrtsd XMMReg (Disp, Reg32) where
+    sqrtsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_sd xd r d
+
+
+class Sqrtss a b where
+    sqrtss :: a -> b -> CodeGen e s ()
+
+instance Sqrtss XMMReg XMMReg where
+    sqrtss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_reg x86_sse_ss xd xs
+
+instance Sqrtss XMMReg Addr where
+    sqrtss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_mem x86_sse_ss xd a
+
+instance Sqrtss XMMReg Ind where
+    sqrtss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_ss xd r 0
+
+instance Sqrtss XMMReg (Disp, Reg32) where
+    sqrtss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_ss xd r d
+
+
+class Sqrtpd a b where
+    sqrtpd :: a -> b -> CodeGen e s ()
+
+instance Sqrtpd XMMReg XMMReg where
+    sqrtpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_reg x86_sse_pd xd xs
+
+instance Sqrtpd XMMReg Addr where
+    sqrtpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_mem x86_sse_pd xd a
+
+instance Sqrtpd XMMReg Ind where
+    sqrtpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_pd xd r 0
+
+instance Sqrtpd XMMReg (Disp, Reg32) where
+    sqrtpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_pd xd r d
+
+
+class Sqrtps a b where
+    sqrtps :: a -> b -> CodeGen e s ()
+
+instance Sqrtps XMMReg XMMReg where
+    sqrtps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_reg x86_sse_ps xd xs
+
+instance Sqrtps XMMReg Addr where
+    sqrtps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_mem x86_sse_ps xd a
+
+instance Sqrtps XMMReg Ind where
+    sqrtps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_ps xd r 0
+
+instance Sqrtps XMMReg (Disp, Reg32) where
+    sqrtps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sqrt_sse_reg_membase x86_sse_ps xd r d
+
+
+class Addsd a b where
+    addsd :: a -> b -> CodeGen e s ()
+
+instance Addsd XMMReg XMMReg where
+    addsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_reg x86_sse_sd xd xs
+
+instance Addsd XMMReg Addr where
+    addsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_mem x86_sse_sd xd a
+
+instance Addsd XMMReg Ind where
+    addsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_sd xd r 0
+
+instance Addsd XMMReg (Disp, Reg32) where
+    addsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_sd xd r d
+
+
+class Addss a b where
+    addss :: a -> b -> CodeGen e s ()
+
+instance Addss XMMReg XMMReg where
+    addss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_reg x86_sse_ss xd xs
+
+instance Addss XMMReg Addr where
+    addss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_mem x86_sse_ss xd a
+
+instance Addss XMMReg Ind where
+    addss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_ss xd r 0
+
+instance Addss XMMReg (Disp, Reg32) where
+    addss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_ss xd r d
+
+
+class Addpd a b where
+    addpd :: a -> b -> CodeGen e s ()
+
+instance Addpd XMMReg XMMReg where
+    addpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_reg x86_sse_pd xd xs
+
+instance Addpd XMMReg Addr where
+    addpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_mem x86_sse_pd xd a
+
+instance Addpd XMMReg Ind where
+    addpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_pd xd r 0
+
+instance Addpd XMMReg (Disp, Reg32) where
+    addpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_pd xd r d
+
+
+class Addps a b where
+    addps :: a -> b -> CodeGen e s ()
+
+instance Addps XMMReg XMMReg where
+    addps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_reg x86_sse_ps xd xs
+
+instance Addps XMMReg Addr where
+    addps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_mem x86_sse_ps xd a
+
+instance Addps XMMReg Ind where
+    addps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_ps xd r 0
+
+instance Addps XMMReg (Disp, Reg32) where
+    addps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_add_sse_reg_membase x86_sse_ps xd r d
+
+class Subsd a b where
+    subsd :: a -> b -> CodeGen e s ()
+
+instance Subsd XMMReg XMMReg where
+    subsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_reg x86_sse_sd xd xs
+
+instance Subsd XMMReg Addr where
+    subsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_mem x86_sse_sd xd a
+
+instance Subsd XMMReg Ind where
+    subsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_sd xd r 0
+
+instance Subsd XMMReg (Disp, Reg32) where
+    subsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_sd xd r d
+
+
+class Subss a b where
+    subss :: a -> b -> CodeGen e s ()
+
+instance Subss XMMReg XMMReg where
+    subss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_reg x86_sse_ss xd xs
+
+instance Subss XMMReg Addr where
+    subss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_mem x86_sse_ss xd a
+
+instance Subss XMMReg Ind where
+    subss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_ss xd r 0
+
+instance Subss XMMReg (Disp, Reg32) where
+    subss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_ss xd r d
+
+
+class Subpd a b where
+    subpd :: a -> b -> CodeGen e s ()
+
+instance Subpd XMMReg XMMReg where
+    subpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_reg x86_sse_pd xd xs
+
+instance Subpd XMMReg Addr where
+    subpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_mem x86_sse_pd xd a
+
+instance Subpd XMMReg Ind where
+    subpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_pd xd r 0
+
+instance Subpd XMMReg (Disp, Reg32) where
+    subpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_pd xd r d
+
+
+class Subps a b where
+    subps :: a -> b -> CodeGen e s ()
+
+instance Subps XMMReg XMMReg where
+    subps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_reg x86_sse_ps xd xs
+
+instance Subps XMMReg Addr where
+    subps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_mem x86_sse_ps xd a
+
+instance Subps XMMReg Ind where
+    subps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_ps xd r 0
+
+instance Subps XMMReg (Disp, Reg32) where
+    subps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_sub_sse_reg_membase x86_sse_ps xd r d
+
+class Mulsd a b where
+    mulsd :: a -> b -> CodeGen e s ()
+
+instance Mulsd XMMReg XMMReg where
+    mulsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_reg x86_sse_sd xd xs
+
+instance Mulsd XMMReg Addr where
+    mulsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_mem x86_sse_sd xd a
+
+instance Mulsd XMMReg Ind where
+    mulsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_sd xd r 0
+
+instance Mulsd XMMReg (Disp, Reg32) where
+    mulsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_sd xd r d
+
+
+class Mulss a b where
+    mulss :: a -> b -> CodeGen e s ()
+
+instance Mulss XMMReg XMMReg where
+    mulss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_reg x86_sse_ss xd xs
+
+instance Mulss XMMReg Addr where
+    mulss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_mem x86_sse_ss xd a
+
+instance Mulss XMMReg Ind where
+    mulss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_ss xd r 0
+
+instance Mulss XMMReg (Disp, Reg32) where
+    mulss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_ss xd r d
+
+
+class Mulpd a b where
+    mulpd :: a -> b -> CodeGen e s ()
+
+instance Mulpd XMMReg XMMReg where
+    mulpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_reg x86_sse_pd xd xs
+
+instance Mulpd XMMReg Addr where
+    mulpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_mem x86_sse_pd xd a
+
+instance Mulpd XMMReg Ind where
+    mulpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_pd xd r 0
+
+instance Mulpd XMMReg (Disp, Reg32) where
+    mulpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_pd xd r d
+
+
+class Mulps a b where
+    mulps :: a -> b -> CodeGen e s ()
+
+instance Mulps XMMReg XMMReg where
+    mulps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_reg x86_sse_ps xd xs
+
+instance Mulps XMMReg Addr where
+    mulps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_mem x86_sse_ps xd a
+
+instance Mulps XMMReg Ind where
+    mulps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_ps xd r 0
+
+instance Mulps XMMReg (Disp, Reg32) where
+    mulps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mul_sse_reg_membase x86_sse_ps xd r d
+
+
+class Divsd a b where
+    divsd :: a -> b -> CodeGen e s ()
+
+instance Divsd XMMReg XMMReg where
+    divsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_reg x86_sse_sd xd xs
+
+instance Divsd XMMReg Addr where
+    divsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_mem x86_sse_sd xd a
+
+instance Divsd XMMReg Ind where
+    divsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_sd xd r 0
+
+instance Divsd XMMReg (Disp, Reg32) where
+    divsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_sd xd r d
+
+
+class Divss a b where
+    divss :: a -> b -> CodeGen e s ()
+
+instance Divss XMMReg XMMReg where
+    divss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_reg x86_sse_ss xd xs
+
+instance Divss XMMReg Addr where
+    divss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_mem x86_sse_ss xd a
+
+instance Divss XMMReg Ind where
+    divss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_ss xd r 0
+
+instance Divss XMMReg (Disp, Reg32) where
+    divss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_ss xd r d
+
+
+class Divpd a b where
+    divpd :: a -> b -> CodeGen e s ()
+
+instance Divpd XMMReg XMMReg where
+    divpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_reg x86_sse_pd xd xs
+
+instance Divpd XMMReg Addr where
+    divpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_mem x86_sse_pd xd a
+
+instance Divpd XMMReg Ind where
+    divpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_pd xd r 0
+
+instance Divpd XMMReg (Disp, Reg32) where
+    divpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_pd xd r d
+
+
+class Divps a b where
+    divps :: a -> b -> CodeGen e s ()
+
+instance Divps XMMReg XMMReg where
+    divps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_reg x86_sse_ps xd xs
+
+instance Divps XMMReg Addr where
+    divps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_mem x86_sse_ps xd a
+
+instance Divps XMMReg Ind where
+    divps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_ps xd r 0
+
+instance Divps XMMReg (Disp, Reg32) where
+    divps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_div_sse_reg_membase x86_sse_ps xd r d
+
+class Minsd a b where
+    minsd :: a -> b -> CodeGen e s ()
+
+instance Minsd XMMReg XMMReg where
+    minsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_reg x86_sse_sd xd xs
+
+instance Minsd XMMReg Addr where
+    minsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_mem x86_sse_sd xd a
+
+instance Minsd XMMReg Ind where
+    minsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_sd xd r 0
+
+instance Minsd XMMReg (Disp, Reg32) where
+    minsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_sd xd r d
+
+
+class Minss a b where
+    minss :: a -> b -> CodeGen e s ()
+
+instance Minss XMMReg XMMReg where
+    minss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_reg x86_sse_ss xd xs
+
+instance Minss XMMReg Addr where
+    minss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_mem x86_sse_ss xd a
+
+instance Minss XMMReg Ind where
+    minss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_ss xd r 0
+
+instance Minss XMMReg (Disp, Reg32) where
+    minss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_ss xd r d
+
+
+class Minpd a b where
+    minpd :: a -> b -> CodeGen e s ()
+
+instance Minpd XMMReg XMMReg where
+    minpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_reg x86_sse_pd xd xs
+
+instance Minpd XMMReg Addr where
+    minpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_mem x86_sse_pd xd a
+
+instance Minpd XMMReg Ind where
+    minpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_pd xd r 0
+
+instance Minpd XMMReg (Disp, Reg32) where
+    minpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_pd xd r d
+
+
+class Minps a b where
+    minps :: a -> b -> CodeGen e s ()
+
+instance Minps XMMReg XMMReg where
+    minps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_reg x86_sse_ps xd xs
+
+instance Minps XMMReg Addr where
+    minps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_mem x86_sse_ps xd a
+
+instance Minps XMMReg Ind where
+    minps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_ps xd r 0
+
+instance Minps XMMReg (Disp, Reg32) where
+    minps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_min_sse_reg_membase x86_sse_ps xd r d
+
+
+class Maxsd a b where
+    maxsd :: a -> b -> CodeGen e s ()
+
+instance Maxsd XMMReg XMMReg where
+    maxsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_reg x86_sse_sd xd xs
+
+instance Maxsd XMMReg Addr where
+    maxsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_mem x86_sse_sd xd a
+
+instance Maxsd XMMReg Ind where
+    maxsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_sd xd r 0
+
+instance Maxsd XMMReg (Disp, Reg32) where
+    maxsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_sd xd r d
+
+
+class Maxss a b where
+    maxss :: a -> b -> CodeGen e s ()
+
+instance Maxss XMMReg XMMReg where
+    maxss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_reg x86_sse_ss xd xs
+
+instance Maxss XMMReg Addr where
+    maxss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_mem x86_sse_ss xd a
+
+instance Maxss XMMReg Ind where
+    maxss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_ss xd r 0
+
+instance Maxss XMMReg (Disp, Reg32) where
+    maxss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_ss xd r d
+
+
+class Maxpd a b where
+    maxpd :: a -> b -> CodeGen e s ()
+
+instance Maxpd XMMReg XMMReg where
+    maxpd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_reg x86_sse_pd xd xs
+
+instance Maxpd XMMReg Addr where
+    maxpd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_mem x86_sse_pd xd a
+
+instance Maxpd XMMReg Ind where
+    maxpd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_pd xd r 0
+
+instance Maxpd XMMReg (Disp, Reg32) where
+    maxpd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_pd xd r d
+
+
+class Maxps a b where
+    maxps :: a -> b -> CodeGen e s ()
+
+instance Maxps XMMReg XMMReg where
+    maxps (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_reg x86_sse_ps xd xs
+
+instance Maxps XMMReg Addr where
+    maxps (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_mem x86_sse_ps xd a
+
+instance Maxps XMMReg Ind where
+    maxps (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_ps xd r 0
+
+instance Maxps XMMReg (Disp, Reg32) where
+    maxps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_ps xd r d
+
+
+class Movsd a b where
+    movsd :: a -> b -> CodeGen e s ()
+
+instance Movsd XMMReg XMMReg where
+    movsd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_reg x86_sse_sd xd xs
+
+instance Movsd XMMReg Addr where
+    movsd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_mem x86_sse_sd xd a
+
+instance Movsd Addr XMMReg where
+    movsd (Addr a) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_mem_reg x86_sse_sd a xd
+
+instance Movsd XMMReg Ind where
+    movsd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_sd xd r 0
+
+instance Movsd Ind XMMReg where
+    movsd (Ind (Reg32 r)) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_sd r 0 xd
+
+instance Movsd XMMReg (Disp, Reg32) where
+    movsd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_sd xd r d
+
+instance Movsd (Disp, Reg32) XMMReg where
+    movsd (Disp d, Reg32 r) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_sd r d xd
+
+
+class Comisd a b where
+    comisd :: a -> b -> CodeGen e s ()
+
+instance Comisd XMMReg XMMReg where
+    comisd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_comisd_reg_reg xd xs
+
+instance Comisd XMMReg Addr where
+    comisd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_comisd_reg_mem xd a
+
+instance Comisd XMMReg Ind where
+    comisd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_comisd_reg_membase xd r 0
+
+instance Comisd XMMReg (Disp, Reg32) where
+    comisd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_comisd_reg_membase xd r d
+
+
+class Comiss a b where
+    comiss :: a -> b -> CodeGen e s ()
+
+instance Comiss XMMReg XMMReg where
+    comiss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_comiss_reg_reg xd xs
+
+instance Comiss XMMReg Addr where
+    comiss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_comiss_reg_mem xd a
+
+instance Comiss XMMReg Ind where
+    comiss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_comiss_reg_membase xd r 0
+
+instance Comiss XMMReg (Disp, Reg32) where
+    comiss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_comiss_reg_membase xd r d
+
+
+class Ucomisd a b where
+    ucomisd :: a -> b -> CodeGen e s ()
+
+instance Ucomisd XMMReg XMMReg where
+    ucomisd (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomisd_reg_reg xd xs
+
+instance Ucomisd XMMReg Addr where
+    ucomisd (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomisd_reg_mem xd a
+
+instance Ucomisd XMMReg Ind where
+    ucomisd (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomisd_reg_membase xd r 0
+
+instance Ucomisd XMMReg (Disp, Reg32) where
+    ucomisd (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomisd_reg_membase xd r d
+
+
+class Ucomiss a b where
+    ucomiss :: a -> b -> CodeGen e s ()
+
+instance Ucomiss XMMReg XMMReg where
+    ucomiss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomiss_reg_reg xd xs
+
+instance Ucomiss XMMReg Addr where
+    ucomiss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomiss_reg_mem xd a
+
+instance Ucomiss XMMReg Ind where
+    ucomiss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomiss_reg_membase xd r 0
+
+instance Ucomiss XMMReg (Disp, Reg32) where
+    ucomiss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomiss_reg_membase xd r d
+
+
diff --git a/Harpy/X86Assembler.lhs b/Harpy/X86Assembler.lhs
deleted file mode 100644
--- a/Harpy/X86Assembler.lhs
+++ /dev/null
@@ -1,2906 +0,0 @@
-
-> --------------------------------------------------------------------------
-> -- |
-> -- Module      :  X86Assembler
-> -- Copyright   :  (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
-> -- License     :  GPL
-> -- 
-> -- Maintainer  :  {magr,klee}@cs.tu-berlin.de
-> -- Stability   :  provisional
-> -- Portability :  non-portable
-> --
-> -- A type class based layer on top of X86CodeGen
-> -- which determines the addressing modes from the types of the
-> -- operands.
-> --------------------------------------------------------------------------
-
-
-This module provides simple assembler facilities.
-
-> module Harpy.X86Assembler where
-
-> import Harpy.X86CodeGen
-> import Harpy.CodeGenMonad
-> import Data.Word
-> import Foreign.Ptr
-
-> import qualified Text.PrettyPrint.HughesPJ as PP
-
-
-address modes used in this module:
-
-Word8/16/32	   	     immediate values
-Reg8/16/32	             register
-Addr Word32		     absolut
-Ind Reg32		     register indirect
-(Disp, Reg32)		     register indirect with displacement
-(Reg32, Reg32, Scale)	     (base, index, scale), effective address is (base + index * scale)
-(Disp, Reg32, Scale)	     (disp, index, scale), effective address is (disp + index * scale)
-(Disp, Reg32, Reg32, Scale)  (base, index, scale) + displacement (only ebp is allowed as base register)
-Label                        not-yet-specified label
- 
-> onlyEbp = failCodeGen (PP.text "only epb is allowed as base register for disp/base/index/scale addressing")
-> onlyCl  = failCodeGen (PP.text "only cl is allowed as shift count")
-
-
-x86 Registers
-
-> newtype Reg8 = Reg8 Word8
-> al, cl, dl, bl, ah, ch, dh, bh :: Reg8
-
-> al = Reg8 0
-> cl = Reg8 1
-> dl = Reg8 2
-> bl = Reg8 3
-> ah = Reg8 4
-> ch = Reg8 5
-> dh = Reg8 6
-> bh = Reg8 7
-
-> newtype Reg16 = Reg16 Word8
-> ax, cx, dx, bx, sp, bp, si, di :: Reg16
-
-> ax = Reg16 0
-> cx = Reg16 1
-> dx = Reg16 2
-> bx = Reg16 3
-> sp = Reg16 4
-> bp = Reg16 5
-> si = Reg16 6
-> di = Reg16 7
-
-> newtype Reg32 = Reg32 Word8 deriving Eq
-> eax, ecx, edx, ebx, esp, ebp, esi, edi :: Reg32
-
-> eax = Reg32 0
-> ecx = Reg32 1
-> edx = Reg32 2
-> ebx = Reg32 3
-> esp = Reg32 4
-> ebp = Reg32 5
-> esi = Reg32 6
-> edi = Reg32 7
-
--- TODO: instances for other registers
-
-> instance Show Reg32 where
->  show (Reg32 0) = "eax"
->  show (Reg32 1) = "ecx"
->  show (Reg32 2) = "edx"
->  show (Reg32 3) = "ebx"
->  show (Reg32 4) = "esp"
->  show (Reg32 5) = "ebp"
->  show (Reg32 6) = "esi"
->  show (Reg32 7) = "edi"
-
-memory addresses
-
-> newtype Addr  = Addr Word32
-> newtype Ind   = Ind Reg32
-> newtype Disp  = Disp Word32
-
-> data    Scale = S1 | S2 | S4 | S8
-
-> scaleToShift :: Scale -> Word8
-> scaleToShift S1 = 0
-> scaleToShift S2 = 1
-> scaleToShift S4 = 2
-> scaleToShift S8 = 3
-
-
-int 3
-
-> breakpoint = x86_breakpoint
-
-
-clear direction flag
-
-> cld = x86_cld
-
-
-store string
-
-> stosb = x86_stosb
-> stosl = x86_stosl
-> stosd = x86_stosd
-
-
-move string
-
-> movsb = x86_movsb
-> movsl = x86_movsl
-> movsd = x86_movsd
-
-
-read time stamp counter
-
-> rdtsc = x86_rdtsc
-
-
-compare and exchange
-
-> class Cmpxchg a b where
->   cmpxchg :: a -> b -> CodeGen e s ()
-
-> instance Cmpxchg Reg32 Reg32 where
->   cmpxchg (Reg32 dest) (Reg32 source) = x86_cmpxchg_reg_reg dest source
->
-> instance Cmpxchg Addr Reg32 where
->   cmpxchg (Addr dest) (Reg32 source) = x86_cmpxchg_mem_reg dest source
->
-> instance Cmpxchg (Disp, Reg32) Reg32 where
->   cmpxchg (Disp disp, Reg32 dest) (Reg32 source) = x86_cmpxchg_membase_reg dest disp source
->
-> instance Cmpxchg Ind Reg32 where
->   cmpxchg (Ind (Reg32 dest)) (Reg32 source) = x86_cmpxchg_membase_reg dest 0 source
-
-
-
-exchange memory/register with register
-
-> class Xchg a b where
->   xchg :: a -> b -> CodeGen e s ()
-
-> instance Xchg Reg8 Reg8 where
->   xchg (Reg8 dest) (Reg8 source) = x86_xchg_reg_reg dest source 1
->
-> instance Xchg Reg32 Reg32 where
->   xchg (Reg32 dest) (Reg32 source) = x86_xchg_reg_reg dest source 4
->
-> instance Xchg Addr Reg8 where
->   xchg (Addr dest) (Reg8 source) = x86_xchg_mem_reg dest source 1
->
-> instance Xchg Addr Reg32 where
->   xchg (Addr dest) (Reg32 source) = x86_xchg_mem_reg dest source 4
->
-> instance Xchg (Disp, Reg32) Reg8 where
->   xchg (Disp disp, Reg32 dest) (Reg8 source) = x86_xchg_membase_reg dest disp source 1
->
-> instance Xchg Ind Reg8 where
->   xchg (Ind (Reg32 dest)) (Reg8 source) = x86_xchg_membase_reg dest 0 source 1
->
-> instance Xchg (Disp, Reg32) Reg32 where
->   xchg (Disp disp, Reg32 dest) (Reg32 source) = x86_xchg_membase_reg dest disp source 4
->
-> instance Xchg Ind Reg32 where
->   xchg (Ind (Reg32 dest)) (Reg32 source) = x86_xchg_membase_reg dest 0 source 4
-
-
-exchange and add
-
-> class Xadd a b where
->   xadd :: a -> b -> CodeGen e s ()
-
-> instance Xadd Reg8 Reg8 where
->   xadd (Reg8 dest) (Reg8 source) = x86_xadd_reg_reg dest source 1
->
-> instance Xadd Reg32 Reg32 where
->   xadd (Reg32 dest) (Reg32 source) = x86_xadd_reg_reg dest source 4
->
-> instance Xadd Addr Reg8 where
->   xadd (Addr dest) (Reg8 source) = x86_xadd_mem_reg dest source 1
->
-> instance Xadd Addr Reg32 where
->   xadd (Addr dest) (Reg32 source) = x86_xadd_mem_reg dest source 4
->
-> instance Xadd (Disp, Reg32) Reg8 where
->   xadd (Disp disp, Reg32 dest) (Reg8 source) = x86_xadd_membase_reg dest disp source 1
->
-> instance Xadd Ind Reg8 where
->   xadd (Ind (Reg32 dest)) (Reg8 source) = x86_xadd_membase_reg dest 0 source 1
->
-> instance Xadd (Disp, Reg32) Reg32 where
->   xadd (Disp disp, Reg32 dest) (Reg32 source) =  x86_xadd_membase_reg dest disp source 4
->
-> instance Xadd Ind Reg32 where
->   xadd (Ind (Reg32 dest)) (Reg32 source) =  x86_xadd_membase_reg dest 0 source 4
-
-
-Increment by 1
-
-> class Inc a where
->   inc :: a -> CodeGen e s ()
-
-> instance Inc Addr where
->   inc (Addr dest) = x86_inc_mem dest
->
-> instance Inc (Disp, Reg32) where
->   inc (Disp disp, Reg32 dest) = x86_inc_membase dest disp
->
-> instance Inc Ind where
->   inc (Ind (Reg32 dest)) = x86_inc_membase dest 0
->
-> instance Inc Reg32 where
->   inc (Reg32 dest) = x86_inc_reg dest
-
-
-Decrement by 1
-
-> class Dec a where
->   dec :: a -> CodeGen e s ()
-
-> instance Dec Addr where
->   dec (Addr dest) = x86_dec_mem dest
->
-> instance Dec (Disp, Reg32) where
->   dec (Disp disp, Reg32 dest) = x86_dec_membase dest disp
->
-> instance Dec Ind where
->   dec (Ind (Reg32 dest)) = x86_dec_membase dest 0
->
-> instance Dec Reg32 where
->   dec (Reg32 dest) = x86_dec_reg dest
-
-
-One's complement negation
-
-> class Not a where
->   not :: a -> CodeGen e s ()
-
-> instance Not Addr where
->   not (Addr dest) = x86_not_mem dest
->
-> instance Not (Disp, Reg32) where
->   not (Disp disp, Reg32 dest) = x86_not_membase dest disp
->
-> instance Not Ind where
->   not (Ind (Reg32 dest)) = x86_not_membase dest 0
->
-> instance Not Reg32 where
->   not (Reg32 dest) = x86_not_reg dest
-
-
-Two's complement negation
-
-> class Neg a where
->   neg :: a -> CodeGen e s ()
-
-> instance Neg Addr where
->   neg (Addr dest) = x86_neg_mem dest
->
-> instance Neg (Disp, Reg32) where
->   neg (Disp disp, Reg32 dest) = x86_neg_membase dest disp
->
-> instance Neg Ind where
->   neg (Ind (Reg32 dest)) = x86_neg_membase dest 0
->
-> instance Neg Reg32 where
->   neg (Reg32 dest) = x86_neg_reg dest
-
-
-No operation
-
-> nop = x86_nop
-
-
-ALU operations
-
-Calling "x86_alu_reg8_reg8 _ _ _ *False* *False*" is a little bit hackish: the last two
-arguments are set to True for the "high byte registers" ah, bh, ch and dh.
-x86_reg8_emit then sets the 3rd bit in the register number. This bit is set in our
-encoding anyway to the right value, so we simply skip this part.
-
-> class Add a b where
->   add :: a -> b -> CodeGen e s ()
-
-> instance Add Reg32 Word32 where
->   add (Reg32 dest) imm = x86_alu_reg_imm x86_add dest (fromIntegral imm)
->
-> instance Add Addr Word32 where
->   add (Addr dest) imm = x86_alu_mem_imm x86_add dest (fromIntegral imm)
->
-> instance Add (Disp, Reg32) Word32 where
->   add (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_add dest disp (fromIntegral imm)
->
-> instance Add Ind Word32 where
->   add (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_add dest 0 (fromIntegral imm)
->
-> instance Add (Disp, Reg32) Word8 where
->   add (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_add dest disp (fromIntegral imm)
->
-> instance Add Ind Word8 where
->   add (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_add dest 0 (fromIntegral imm)
->
-> instance Add Addr Reg32 where
->   add (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_add dest source
->
-> instance Add (Disp, Reg32) Reg32 where
->   add (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_add dest disp source
->
-> instance Add Ind Reg32 where
->   add (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_add dest 0 source
->
-> instance Add Reg32 Reg32 where
->   add (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_add dest source
->
-> instance Add Reg8 Reg8 where
->   add (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_add dest source False False
->
-> instance Add Reg32 Addr where
->   add (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_add dest source
->
-> instance Add Reg32 (Disp, Reg32) where
->   add (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_add dest source disp
->
-> instance Add Reg32 Ind where
->   add (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_add dest source 0
-
-
-> class Or a b where
->   or :: a -> b -> CodeGen e s ()
-
-> instance Or Reg32 Word32 where
->   or (Reg32 dest) imm = x86_alu_reg_imm x86_or dest (fromIntegral imm)
->
-> instance Or Addr Word32 where
->   or (Addr dest) imm = x86_alu_mem_imm x86_or dest (fromIntegral imm)
->
-> instance Or (Disp, Reg32) Word32 where
->   or (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_or dest disp (fromIntegral imm)
->
-> instance Or Ind Word32 where
->   or (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_or dest 0 (fromIntegral imm)
->
-> instance Or (Disp, Reg32) Word8 where
->   or (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_or dest disp (fromIntegral imm)
->
-> instance Or Ind Word8 where
->   or (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_or dest 0 (fromIntegral imm)
->
-> instance Or Addr Reg32 where
->   or (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_or dest source
->
-> instance Or (Disp, Reg32) Reg32 where
->   or (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_or dest disp source
->
-> instance Or Ind Reg32 where
->   or (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_or dest 0 source
->
-> instance Or Reg32 Reg32 where
->   or (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_or dest source
->
-> instance Or Reg8 Reg8 where
->   or (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_or dest source False False
->
-> instance Or Reg32 Addr where
->   or (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_or dest source
->
-> instance Or Reg32 (Disp, Reg32) where
->   or (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_or dest source disp
->
-> instance Or Reg32 Ind where
->   or (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_or dest source 0
-
-
-> class Adc a b where
->   adc :: a -> b -> CodeGen e s ()
-
-> instance Adc Reg32 Word32 where
->   adc (Reg32 dest) imm = x86_alu_reg_imm x86_adc dest (fromIntegral imm)
->
-> instance Adc Addr Word32 where
->   adc (Addr dest) imm = x86_alu_mem_imm x86_adc dest (fromIntegral imm)
->
-> instance Adc (Disp, Reg32) Word32 where
->   adc (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_adc dest disp (fromIntegral imm)
->
-> instance Adc Ind Word32 where
->   adc (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_adc dest 0 (fromIntegral imm)
->
-> instance Adc (Disp, Reg32) Word8 where
->   adc (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_adc dest disp (fromIntegral imm)
->
-> instance Adc Ind Word8 where
->   adc (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_adc dest 0 (fromIntegral imm)
->
-> instance Adc Addr Reg32 where
->   adc (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_adc dest source
->
-> instance Adc (Disp, Reg32) Reg32 where
->   adc (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_adc dest disp source
->
-> instance Adc Ind Reg32 where
->   adc (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_adc dest 0 source
->
-> instance Adc Reg32 Reg32 where
->   adc (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_adc dest source
->
-> instance Adc Reg8 Reg8 where
->   adc (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_adc dest source False False
->
-> instance Adc Reg32 Addr where
->   adc (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_adc dest source
->
-> instance Adc Reg32 (Disp, Reg32) where
->   adc (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_adc dest source disp
->
-> instance Adc Reg32 Ind where
->   adc (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_adc dest source 0
-
-
-> class Sbb a b where
->   sbb :: a -> b -> CodeGen e s ()
-
-> instance Sbb Reg32 Word32 where
->   sbb (Reg32 dest) imm = x86_alu_reg_imm x86_sbb dest (fromIntegral imm)
->
-> instance Sbb Addr Word32 where
->   sbb (Addr dest) imm = x86_alu_mem_imm x86_sbb dest (fromIntegral imm)
->
-> instance Sbb (Disp, Reg32) Word32 where
->   sbb (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_sbb dest disp (fromIntegral imm)
->
-> instance Sbb Ind Word32 where
->   sbb (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_sbb dest 0 (fromIntegral imm)
->
-> instance Sbb (Disp, Reg32) Word8 where
->   sbb (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_sbb dest disp (fromIntegral imm)
->
-> instance Sbb Ind Word8 where
->   sbb (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_sbb dest 0 (fromIntegral imm)
->
-> instance Sbb Addr Reg32 where
->   sbb (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_sbb dest source
->
-> instance Sbb (Disp, Reg32) Reg32 where
->   sbb (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_sbb dest disp source
->
-> instance Sbb Ind Reg32 where
->   sbb (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_sbb dest 0 source
->
-> instance Sbb Reg32 Reg32 where
->   sbb (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_sbb dest source
->
-> instance Sbb Reg8 Reg8 where
->   sbb (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_sbb dest source False False
->
-> instance Sbb Reg32 Addr where
->   sbb (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_sbb dest source
->
-> instance Sbb Reg32 (Disp, Reg32) where
->   sbb (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_sbb dest source disp
->
-> instance Sbb Reg32 Ind where
->   sbb (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_sbb dest source 0
-
-
-> class And a b where
->   and :: a -> b -> CodeGen e s ()
-
-> instance And Reg32 Word32 where
->   and (Reg32 dest) imm = x86_alu_reg_imm x86_and dest (fromIntegral imm)
->
-> instance And Addr Word32 where
->   and (Addr dest) imm = x86_alu_mem_imm x86_and dest (fromIntegral imm)
->
-> instance And (Disp, Reg32) Word32 where
->   and (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_and dest disp (fromIntegral imm)
->
-> instance And Ind Word32 where
->   and (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_and dest 0 (fromIntegral imm)
->
-> instance And (Disp, Reg32) Word8 where
->   and (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_and dest disp (fromIntegral imm)
->
-> instance And Ind Word8 where
->   and (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_and dest 0 (fromIntegral imm)
->
-> instance And Addr Reg32 where
->   and (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_and dest source
->
-> instance And (Disp, Reg32) Reg32 where
->   and (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_and dest disp source
->
-> instance And Ind Reg32 where
->   and (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_and dest 0 source
->
-> instance And Reg32 Reg32 where
->   and (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_and dest source
->
-> instance And Reg8 Reg8 where
->   and (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_and dest source False False
->
-> instance And Reg32 Addr where
->   and (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_and dest source
->
-> instance And Reg32 (Disp, Reg32) where
->   and (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_and dest source disp
->
-> instance And Reg32 Ind where
->   and (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_and dest source 0
->
-
-> class Sub a b where
->   sub :: a -> b -> CodeGen e s ()
-
-> instance Sub Reg32 Word32 where
->   sub (Reg32 dest) imm = x86_alu_reg_imm x86_sub dest (fromIntegral imm)
->
-> instance Sub Addr Word32 where
->   sub (Addr dest) imm = x86_alu_mem_reg x86_sub dest (fromIntegral imm)
->
-> instance Sub (Disp, Reg32) Word32 where
->   sub (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_sub dest disp (fromIntegral imm)
->
-> instance Sub Ind Word32 where
->   sub (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_sub dest 0 (fromIntegral imm)
->
-> instance Sub (Disp, Reg32) Word8 where
->   sub (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_sub dest disp (fromIntegral imm)
->
-> instance Sub Ind Word8 where
->   sub (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_sub dest 0 (fromIntegral imm)
->
-> instance Sub Addr Reg32 where
->   sub (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_sub dest source
->
-> instance Sub (Disp, Reg32) Reg32 where
->   sub (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_sub dest disp source
->
-> instance Sub Ind Reg32 where
->   sub (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_sub dest 0 source
->
-> instance Sub Reg32 Reg32 where
->   sub (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_sub dest source
->
-> instance Sub Reg8 Reg8 where
->   sub (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_sub dest source False False
->
-> instance Sub Reg32 Addr where
->   sub (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_sub dest source
->
-> instance Sub Reg32 (Disp, Reg32) where
->   sub (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_sub dest source disp
->
-> instance Sub Reg32 Ind where
->   sub (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_sub dest source 0
-
-
-> class Xor a b where
->   xor :: a -> b -> CodeGen e s ()
-
-> instance Xor Reg32 Word32 where
->   xor (Reg32 dest) imm = x86_alu_reg_imm x86_xor dest (fromIntegral imm)
->
-> instance Xor Addr Word32 where
->   xor (Addr dest) imm = x86_alu_mem_imm x86_xor dest (fromIntegral imm)
->
-> instance Xor (Disp, Reg32) Word32 where
->   xor (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_xor dest disp (fromIntegral imm)
->
-> instance Xor Ind Word32 where
->   xor (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_xor dest 0 (fromIntegral imm)
->
-> instance Xor (Disp, Reg32) Word8 where
->   xor (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_xor dest disp (fromIntegral imm)
->
-> instance Xor Ind Word8 where
->   xor (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_xor dest 0 (fromIntegral imm)
->
-> instance Xor Addr Reg32 where
->   xor (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_xor dest source
->
-> instance Xor (Disp, Reg32) Reg32 where
->   xor (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_xor dest disp source
->
-> instance Xor Ind Reg32 where
->   xor (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_xor dest 0 source
->
-> instance Xor Reg32 Reg32 where
->   xor (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_xor dest source
->
-> instance Xor Reg8 Reg8 where
->   xor (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_xor dest source False False
->
-> instance Xor Reg32 Addr where
->   xor (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_xor dest source
->
-> instance Xor Reg32 (Disp, Reg32) where
->   xor (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_xor dest source disp
->
-> instance Xor Reg32 Ind where
->   xor (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_xor dest source 0
-
-
-> class Cmp a b where
->   cmp :: a -> b -> CodeGen e s ()
-
-> instance Cmp Reg32 Word32 where
->   cmp (Reg32 dest) imm = x86_alu_reg_imm x86_cmp dest (fromIntegral imm)
->
-> instance Cmp Reg32 Label where
->   cmp (Reg32 dest) lab = do
->       x86_alu_reg_imm x86_cmp dest 0xf0f0f0f0
->       emitFixup lab (-4) Fixup32Absolute
->
-> instance Cmp Addr Word32 where
->   cmp (Addr dest) imm = x86_alu_mem_imm x86_cmp dest (fromIntegral imm)
->
-> instance Cmp Addr Label where
->   cmp (Addr dest) lab = do
->       x86_alu_mem_imm x86_cmp dest 0xf0f0f0f0
->       emitFixup lab (-4) Fixup32Absolute
->
-> instance Cmp (Disp, Reg32) Word32 where
->   cmp (Disp disp, Reg32 dest) imm = x86_alu_membase_imm x86_cmp dest disp (fromIntegral imm)
->
-> instance Cmp (Disp, Reg32) Label where
->   cmp (Disp disp, Reg32 dest) lab = do
->                                    x86_alu_membase_imm x86_cmp dest disp 0xf0f0f0f0
->                                    emitFixup lab (-4) Fixup32Absolute
->
-> instance Cmp Ind Word32 where
->   cmp (Ind (Reg32 dest)) imm = x86_alu_membase_imm x86_cmp dest 0 (fromIntegral imm)
->
-> instance Cmp Ind Label where
->   cmp (Ind (Reg32 dest)) lab = do
->                          x86_alu_membase_imm x86_cmp dest 0 0xf0f0f0f0
->                          emitFixup lab (-4) Fixup32Absolute
->
-> instance Cmp (Disp, Reg32) Word8 where
->   cmp (Disp disp, Reg32 dest) imm = x86_alu_membase8_imm x86_cmp dest disp imm
->
-> instance Cmp Ind Word8 where
->   cmp (Ind (Reg32 dest)) imm = x86_alu_membase8_imm x86_cmp dest 0 imm
->
-> instance Cmp Addr Reg32 where
->   cmp (Addr dest) (Reg32 source) = x86_alu_mem_reg x86_cmp dest source
->
-> instance Cmp (Disp, Reg32) Reg32 where
->   cmp (Disp disp, Reg32 dest) (Reg32 source) = x86_alu_membase_reg x86_cmp dest disp source
->
-> instance Cmp Ind Reg32 where
->   cmp (Ind (Reg32 dest)) (Reg32 source) = x86_alu_membase_reg x86_cmp dest 0 source
->
-> instance Cmp Reg32 Reg32 where
->   cmp (Reg32 dest) (Reg32 source) = x86_alu_reg_reg x86_cmp dest source
->
-> instance Cmp Reg8 Reg8 where
->   cmp (Reg8 dest) (Reg8 source) = x86_alu_reg8_reg8 x86_cmp dest source False False
->
-> instance Cmp Reg32 Addr where
->   cmp (Reg32 dest) (Addr source) = x86_alu_reg_mem x86_cmp dest source
->
-> instance Cmp Reg32 (Disp, Reg32) where
->   cmp (Reg32 dest) (Disp disp, Reg32 source) = x86_alu_reg_membase x86_cmp dest source disp
->
-> instance Cmp Reg32 Ind where
->   cmp (Reg32 dest) (Ind (Reg32 source)) = x86_alu_reg_membase x86_cmp dest source 0
-
-
-logical compare
-
-> class Test a b where
->   test :: a -> b -> CodeGen e s ()
-
-> instance Test Reg32 Word32 where
->   test (Reg32 dest) imm = x86_test_reg_imm dest imm 
->
-> instance Test Addr Word32 where
->   test (Addr dest) imm = x86_test_mem_imm dest imm 
->
-> instance Test (Disp, Reg32) Word32 where
->   test (Disp disp, Reg32 dest) imm = x86_test_membase_imm dest disp imm 
->
-> instance Test Ind Word32 where
->   test (Ind (Reg32 dest)) imm = x86_test_membase_imm dest 0 imm 
->
-> instance Test Reg32 Reg32 where
->   test (Reg32 dest) (Reg32 source) = x86_test_reg_reg dest source 
->
-> instance Test Addr Reg32 where
->   test (Addr dest) (Reg32 source) = x86_test_mem_reg dest source 
->
-> instance Test (Disp, Reg32) Reg32 where
->   test (Disp disp, Reg32 dest) (Reg32 source) = x86_test_membase_reg dest disp source 
->
-> instance Test Ind Reg32 where
->   test (Ind (Reg32 dest)) (Reg32 source) = x86_test_membase_reg dest 0 source 
-
-
-shift and rotate
-
-> class Rol a b where
->   rol :: a -> b -> CodeGen e s ()
->
-> instance Rol Reg32 Word8 where
->   rol (Reg32 dest) imm = x86_shift_reg_imm x86_rol dest imm 
->
-> instance Rol Addr Word8 where
->   rol (Addr dest) imm = x86_shift_mem_imm x86_rol dest imm 
->
-> instance Rol (Disp, Reg32) Word8 where
->   rol (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_rol dest disp imm 
->
-> instance Rol Ind Word8 where
->   rol (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_rol dest 0 imm 
->
-> instance Rol Reg32 Reg8 where
->   rol (Reg32 dest) (Reg8 1) = x86_shift_reg x86_rol dest
->   rol _ _ = onlyCl
->
-> instance Rol Addr Reg8 where
->   rol (Addr dest) (Reg8 1) = x86_shift_mem x86_rol dest
->   rol _ _ = onlyCl
->
-> instance Rol (Disp, Reg32) Reg8 where
->   rol (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_rol dest disp
->
-> instance Rol Ind Reg8 where
->   rol (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_rol dest 0
->   rol _ _ = onlyCl
-
-> class Ror a b where
->   ror :: a -> b -> CodeGen e s ()
->
-> instance Ror Reg32 Word8 where
->   ror (Reg32 dest) imm = x86_shift_reg_imm x86_ror dest imm 
->
-> instance Ror Addr Word8 where
->   ror (Addr dest) imm = x86_shift_mem_imm x86_ror dest imm 
->
-> instance Ror (Disp, Reg32) Word8 where
->   ror (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_ror dest disp imm 
->
-> instance Ror Ind Word8 where
->   ror (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_ror dest 0 imm 
->
-> instance Ror Reg32 Reg8 where
->   ror (Reg32 dest) (Reg8 1) = x86_shift_reg x86_ror dest
->   ror _ _ = onlyCl
->
-> instance Ror Addr Reg8 where
->   ror (Addr dest) (Reg8 1) = x86_shift_mem x86_ror dest
->   ror _ _ = onlyCl
->
-> instance Ror (Disp, Reg32) Reg8 where
->   ror (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_ror dest disp
->
-> instance Ror Ind Reg8 where
->   ror (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_ror dest 0
->   ror _ _ = onlyCl
-
-> class Rcl a b where
->   rcl :: a -> b -> CodeGen e s ()
->
-> instance Rcl Reg32 Word8 where
->   rcl (Reg32 dest) imm = x86_shift_reg_imm x86_rcl dest imm 
->
-> instance Rcl Addr Word8 where
->   rcl (Addr dest) imm = x86_shift_mem_imm x86_rcl dest imm 
->
-> instance Rcl (Disp, Reg32) Word8 where
->   rcl (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_rcl dest disp imm 
->
-> instance Rcl Ind Word8 where
->   rcl (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_rcl dest 0 imm 
->
-> instance Rcl Reg32 Reg8 where
->   rcl (Reg32 dest) (Reg8 1) = x86_shift_reg x86_rcl dest
->   rcl _ _ = onlyCl
->
-> instance Rcl Addr Reg8 where
->   rcl (Addr dest) (Reg8 1) = x86_shift_mem x86_rcl dest
->   rcl _ _ = onlyCl
->
-> instance Rcl (Disp, Reg32) Reg8 where
->   rcl (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_rcl dest disp
->
-> instance Rcl Ind Reg8 where
->   rcl (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_rcl dest 0
->   rcl _ _ = onlyCl
-
-> class Rcr a b where
->   rcr :: a -> b -> CodeGen e s ()
->
-> instance Rcr Reg32 Word8 where
->   rcr (Reg32 dest) imm = x86_shift_reg_imm x86_rcr dest imm 
->
-> instance Rcr Addr Word8 where
->   rcr (Addr dest) imm = x86_shift_mem_imm x86_rcr dest imm 
->
-> instance Rcr (Disp, Reg32) Word8 where
->   rcr (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_rcr dest disp imm 
->
-> instance Rcr Ind Word8 where
->   rcr (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_rcr dest 0 imm 
->
-> instance Rcr Reg32 Reg8 where
->   rcr (Reg32 dest) (Reg8 1) = x86_shift_reg x86_rcr dest
->   rcr _ _ = onlyCl
->
-> instance Rcr Addr Reg8 where
->   rcr (Addr dest) (Reg8 1) = x86_shift_mem x86_rcr dest
->   rcr _ _ = onlyCl
->
-> instance Rcr (Disp, Reg32) Reg8 where
->   rcr (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_rcr dest disp
->
-> instance Rcr Ind Reg8 where
->   rcr (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_rcr dest 0
->   rcr _ _ = onlyCl
-
-> class Shl a b where
->   shl :: a -> b -> CodeGen e s ()
->
-> instance Shl Reg32 Word8 where
->   shl (Reg32 dest) imm = x86_shift_reg_imm x86_shl dest imm 
->
-> instance Shl Addr Word8 where
->   shl (Addr dest) imm = x86_shift_mem_imm x86_shl dest imm 
->
-> instance Shl (Disp, Reg32) Word8 where
->   shl (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_shl dest disp imm 
->
-> instance Shl Ind Word8 where
->   shl (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_shl dest 0 imm 
->
-> instance Shl Reg32 Reg8 where
->   shl (Reg32 dest) (Reg8 1) = x86_shift_reg x86_shl dest
->   shl _ _ = onlyCl
->
-> instance Shl Addr Reg8 where
->   shl (Addr dest) (Reg8 1) = x86_shift_mem x86_shl dest
->   shl _ _ = onlyCl
->
-> instance Shl (Disp, Reg32) Reg8 where
->   shl (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_shl dest disp
->
-> instance Shl Ind Reg8 where
->   shl (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_shl dest 0
->   shl _ _ = onlyCl
-
-> class Shr a b where
->   shr :: a -> b -> CodeGen e s ()
->
-> instance Shr Reg32 Word8 where
->   shr (Reg32 dest) imm = x86_shift_reg_imm x86_shr dest imm 
->
-> instance Shr Addr Word8 where
->   shr (Addr dest) imm = x86_shift_mem_imm x86_shr dest imm 
->
-> instance Shr (Disp, Reg32) Word8 where
->   shr (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_shr dest disp imm 
->
-> instance Shr Ind Word8 where
->   shr (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_shr dest 0 imm 
->
-> instance Shr Reg32 Reg8 where
->   shr (Reg32 dest) (Reg8 1) = x86_shift_reg x86_shr dest
->   shr _ _ = onlyCl
->
-> instance Shr Addr Reg8 where
->   shr (Addr dest) (Reg8 1) = x86_shift_mem x86_shr dest
->   shr _ _ = onlyCl
->
-> instance Shr (Disp, Reg32) Reg8 where
->   shr (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_shr dest disp
->
-> instance Shr Ind Reg8 where
->   shr (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_shr dest 0
->   shr _ _ = onlyCl
-
-> class Sar a b where
->   sar :: a -> b -> CodeGen e s ()
->
-> instance Sar Reg32 Word8 where
->   sar (Reg32 dest) imm = x86_shift_reg_imm x86_sar dest imm 
->
-> instance Sar Addr Word8 where
->   sar (Addr dest) imm = x86_shift_mem_imm x86_sar dest imm 
->
-> instance Sar (Disp, Reg32) Word8 where
->   sar (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_sar dest disp imm 
->
-> instance Sar Ind Word8 where
->   sar (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_sar dest 0 imm 
->
-> instance Sar Reg32 Reg8 where
->   sar (Reg32 dest) (Reg8 1) = x86_shift_reg x86_sar dest
->   sar _ _ = onlyCl
->
-> instance Sar Addr Reg8 where
->   sar (Addr dest) (Reg8 1) = x86_shift_mem x86_sar dest
->   sar _ _ = onlyCl
->
-> instance Sar (Disp, Reg32) Reg8 where
->   sar (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_sar dest disp
->
-> instance Sar Ind Reg8 where
->   sar (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_sar dest 0
->   sar _ _ = onlyCl
-
-> class Sal a b where
->   sal :: a -> b -> CodeGen e s ()
->
-> instance Sal Reg32 Word8 where
->   sal (Reg32 dest) imm = x86_shift_reg_imm x86_shl dest imm 
->
-> instance Sal Addr Word8 where
->   sal (Addr dest) imm = x86_shift_mem_imm x86_shl dest imm 
->
-> instance Sal (Disp, Reg32) Word8 where
->   sal (Disp disp, Reg32 dest) imm = x86_shift_membase_imm x86_shl dest disp imm 
->
-> instance Sal Ind Word8 where
->   sal (Ind (Reg32 dest)) imm = x86_shift_membase_imm x86_shl dest 0 imm 
->
-> instance Sal Reg32 Reg8 where
->   sal (Reg32 dest) (Reg8 1) = x86_shift_reg x86_shl dest
->   sal _ _ = onlyCl
->
-> instance Sal Addr Reg8 where
->   sal (Addr dest) (Reg8 1) = x86_shift_mem x86_shl dest
->   sal _ _ = onlyCl
->
-> instance Sal (Disp, Reg32) Reg8 where
->   sal (Disp disp, Reg32 dest) (Reg8 1) = x86_shift_membase x86_shl dest disp
->
-> instance Sal Ind Reg8 where
->   sal (Ind (Reg32 dest)) (Reg8 1) = x86_shift_membase x86_shl dest 0
->   sal _ _ = onlyCl
-
-
-double precision shift right
-
-> class Shrd a b c where
->   shrd :: a -> b -> c -> CodeGen e s ()
-
-> instance Shrd Reg32 Reg32 Reg8 where
->   shrd (Reg32 dest) (Reg32 source) (Reg8 1) = x86_shrd_reg dest source
->   shrd _ _ _ = onlyCl
->
-> instance Shrd Reg32 Reg32 Word8 where
->   shrd (Reg32 dest) (Reg32 source) imm = x86_shrd_reg_imm dest source imm 
-
-
-double precision shift left
-
-> class Shld a b c where
->   shld :: a -> b -> c -> CodeGen e s ()
-
-> instance Shld Reg32 Reg32 Reg8 where
->   shld (Reg32 dest) (Reg32 source) (Reg8 1) = x86_shld_reg dest source
->   shld _ _ _ = onlyCl
->
-> instance Shld Reg32 Reg32 Word8 where
->   shld (Reg32 dest) (Reg32 source) imm = x86_shld_reg_imm dest source imm 
-
-
-unsigned multiply
-
-> class Mul a where
->   mul :: a -> CodeGen e s ()
-
-> instance Mul Reg32 where
->   mul (Reg32 arg) = x86_mul_reg arg False
->
-> instance Mul Addr where
->   mul (Addr arg) = x86_mul_mem arg False
->
-> instance Mul (Disp, Reg32) where
->   mul (Disp disp, Reg32 arg) = x86_mul_membase arg disp False
->
-> instance Mul Ind where
->   mul (Ind (Reg32 arg)) = x86_mul_membase arg 0 False
-
-
-signed multiply
-
-> data InPlace = InPlace
-
-if a == InPlace then
-  b = b * c
-else
-  a = b * c
-
-> class Imul a b c where
->   imul :: a -> b -> c -> CodeGen e s ()
-
-> instance Imul InPlace Reg32 Reg32 where
->   imul _ (Reg32 dest) (Reg32 source) = x86_imul_reg_reg dest source
->
-> instance Imul InPlace Reg32 Addr where
->   imul _ (Reg32 dest) (Addr source) = x86_imul_reg_mem dest source
->
-> instance Imul InPlace Reg32 (Disp, Reg32) where
->   imul _ (Reg32 dest) (Disp disp, Reg32 source) = x86_imul_reg_membase dest source disp
->
-> instance Imul InPlace Reg32 Ind where
->   imul _ (Reg32 dest) (Ind (Reg32 source)) = x86_imul_reg_membase dest source 0
->
-> instance Imul Reg32 Reg32 Word32 where
->   imul (Reg32 dest) (Reg32 source) imm = x86_imul_reg_reg_imm dest source imm 
->
-> instance Imul Reg32 Addr Word32 where
->   imul (Reg32 dest) (Addr source) imm = x86_imul_reg_mem_imm dest source imm 
->
-> instance Imul Reg32 (Disp, Reg32) Word32 where
->   imul (Reg32 dest) (Disp disp, Reg32 source) imm = x86_imul_reg_membase_imm dest source disp imm 
->
-> instance Imul Reg32 Ind Word32 where
->   imul (Reg32 dest) (Ind (Reg32 source)) imm = x86_imul_reg_membase_imm dest source 0 imm 
-
-
-divide EDX:EAX by rm;
-eax = quotient, edx = remainder
-
-unsigned divide
-
-> class Div a where
->   div :: a -> CodeGen e s ()
-
-> instance Div Reg32 where
->   div (Reg32 arg) = x86_div_reg arg False
->
-> instance Div Addr where
->   div (Addr arg) = x86_div_mem arg False
->
-> instance Div (Disp, Reg32) where
->   div (Disp disp, Reg32 arg) = x86_div_membase arg disp False
->
-> instance Div Ind where
->   div (Ind (Reg32 arg)) = x86_div_membase arg 0 False
-
-
-signed divide
-
-> class Idiv a where
->   idiv :: a -> CodeGen e s ()
-
-> instance Idiv Reg32 where
->   idiv (Reg32 arg) = x86_div_reg arg True
->
-> instance Idiv Addr where
->   idiv (Addr arg) = x86_div_mem arg True
->
-> instance Idiv (Disp, Reg32) where
->   idiv (Disp disp, Reg32 arg) = x86_div_membase arg disp True
->
-> instance Idiv Ind where
->   idiv (Ind (Reg32 arg)) = x86_div_membase arg 0 True
-
-
-"mov" instruction for different sources and destinations
-
-> class Mov a b where
->   mov :: a -> b -> CodeGen e s ()
-
-
-> instance Mov Reg8 Reg8 where
->   mov (Reg8 dest) (Reg8 source) = x86_mov_reg_reg dest source 1
->
-> instance Mov Reg16 Reg16 where
->   mov (Reg16 dest) (Reg16 source) = x86_mov_reg_reg dest source 2
->
-> instance Mov Reg32 Reg32 where
->   mov (Reg32 dest) (Reg32 source) = x86_mov_reg_reg dest source 4
-
-
-> instance Mov Reg32 Word32 where
->   mov (Reg32 dest) imm = x86_mov_reg_imm dest (fromIntegral imm)
-
-> instance Mov Reg32 Label where
->   mov (Reg32 dest) lab = do x86_mov_reg_imm dest 0
->                             emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov Addr Word8 where
->   mov (Addr dest) imm = x86_mov_mem_imm dest (fromIntegral imm) 1
->
-> instance Mov Addr Word16 where
->   mov (Addr dest) imm = x86_mov_mem_imm dest (fromIntegral imm) 2
->
-> instance Mov Addr Word32 where
->   mov (Addr dest) imm = x86_mov_mem_imm dest imm 4
-
-> instance Mov Addr Label where
->   mov (Addr dest) lab = do x86_mov_mem_imm dest 0 4
->                            emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov (Disp, Reg32) Word8 where
->   mov (Disp disp, Reg32 dest) imm = x86_mov_membase_imm dest disp (fromIntegral imm) 1
->
-> instance Mov Ind Word8 where
->   mov (Ind (Reg32 dest)) imm = x86_mov_membase_imm dest 0 (fromIntegral imm) 1
->
-> instance Mov (Disp, Reg32) Word16 where
->   mov (Disp disp, Reg32 dest) imm = x86_mov_membase_imm dest disp (fromIntegral imm) 2
->
-> instance Mov Ind Word16 where
->   mov (Ind (Reg32 dest)) imm = x86_mov_membase_imm dest 0 (fromIntegral imm) 2
->
-> instance Mov (Disp, Reg32) Word32 where
->   mov (Disp disp, Reg32 dest) imm = x86_mov_membase_imm dest disp imm 4
->
-> instance Mov (Disp, Reg32) Label where
->   mov (Disp disp, Reg32 dest) lab = do x86_mov_membase_imm dest disp 0 4
->                                        emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov Ind Word32 where
->   mov (Ind (Reg32 dest)) imm = x86_mov_membase_imm dest 0 imm 4
-
-> instance Mov Ind Label where
->   mov (Ind (Reg32 dest)) lab = do x86_mov_membase_imm dest 0 0 4
->                                   emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov (Reg32, Reg32, Scale) Word8 where
->   mov (Reg32 base, Reg32 index, scale) imm = x86_mov_memindex_imm base 0 index (scaleToShift scale) (fromIntegral imm) 1
->
-> instance Mov (Reg32, Reg32, Scale) Word16 where
->   mov (Reg32 base, Reg32 index, scale) imm = x86_mov_memindex_imm base 0 index (scaleToShift scale) (fromIntegral imm) 2
->
-> instance Mov (Reg32, Reg32, Scale) Word32 where
->   mov (Reg32 base, Reg32 index, scale) imm = x86_mov_memindex_imm base 0 index (scaleToShift scale) imm 4
-
-> instance Mov (Reg32, Reg32, Scale) Label where
->   mov (Reg32 base, Reg32 index, scale) lab = do x86_mov_memindex_imm base 0 index (scaleToShift scale) 0 4
->                                                 emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov (Disp, Reg32, Scale) Word8 where
->   mov (Disp disp, Reg32 index, scale) imm = x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (fromIntegral imm) 1
->
-> instance Mov (Disp, Reg32, Scale) Word16 where
->   mov (Disp disp, Reg32 index, scale) imm = x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (fromIntegral imm) 2
->
-> instance Mov (Disp, Reg32, Scale) Word32 where
->   mov (Disp disp, Reg32 index, scale) imm = x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) imm 4
-
-> instance Mov (Disp, Reg32, Scale) Label where
->   mov (Disp disp, Reg32 index, scale) lab = do x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) 0 4
->                                                emitFixup lab (-4) Fixup32Absolute
-
-> instance Mov (Disp, Reg32, Reg32, Scale) Word8 where
->   mov (Disp disp, Reg32 5, Reg32 index, scale) imm = x86_mov_memindex_imm 5 disp index (scaleToShift scale) (fromIntegral imm) 1
->   mov _ _ = onlyEbp
->
-> instance Mov (Disp, Reg32, Reg32, Scale) Word16 where
->   mov (Disp disp, Reg32 5, Reg32 index, scale) imm = x86_mov_memindex_imm 5 disp index (scaleToShift scale) (fromIntegral imm) 2
->   mov _ _ = onlyEbp
->
-> instance Mov (Disp, Reg32, Reg32, Scale) Word32 where
->   mov (Disp disp, Reg32 5, Reg32 index, scale) imm = x86_mov_memindex_imm 5 disp index (scaleToShift scale) imm 4
->   mov _ _ = onlyEbp
-
-> instance Mov (Disp, Reg32, Reg32, Scale) Label where
->   mov (Disp disp, Reg32 5, Reg32 index, scale) lab = do x86_mov_memindex_imm 5 disp index (scaleToShift scale) 0 4
->                                                         emitFixup lab (-4) Fixup32Absolute
->   mov _ _ = onlyEbp
-
-> instance Mov Addr Reg8 where
->   mov (Addr a) (Reg8 source) = x86_mov_mem_reg a source 1
->
-> instance Mov Addr Reg16 where
->   mov (Addr a) (Reg16 source) = x86_mov_mem_reg a source 2
->
-> instance Mov Addr Reg32 where
->   mov (Addr a) (Reg32 source) = x86_mov_mem_reg a source 4
->
-> instance Mov Reg8 Addr where
->   mov (Reg8 dest) (Addr a) = x86_mov_reg_mem dest a 1
->
-> instance Mov Reg16 Addr where
->   mov (Reg16 dest) (Addr a) = x86_mov_reg_mem dest a 2
->
-> instance Mov Reg32 Addr where
->   mov (Reg32 dest) (Addr a) = x86_mov_reg_mem dest a 4
-
-
-> instance Mov Ind Reg8 where
->   mov (Ind (Reg32 dest)) (Reg8 source) = x86_mov_regp_reg dest source 1
->
-> instance Mov Ind Reg16 where
->   mov (Ind (Reg32 dest)) (Reg16 source) = x86_mov_regp_reg dest source 2
->
-> instance Mov Ind Reg32 where
->   mov (Ind (Reg32 dest)) (Reg32 source) = x86_mov_regp_reg dest source 4
-
-> instance Mov Reg8 Ind where
->   mov (Reg8 dest) (Ind (Reg32 source)) = x86_mov_reg_regp dest source 1
->
-> instance Mov Reg16 Ind where
->   mov (Reg16 dest) (Ind (Reg32 source)) = x86_mov_reg_regp dest source 2
->
-> instance Mov Reg32 Ind where
->   mov (Reg32 dest) (Ind (Reg32 source)) = x86_mov_reg_regp dest source 4
-
-
-> instance Mov (Disp, Reg32) Reg8 where
->   mov (Disp disp, Reg32 dest) (Reg8 source) = x86_mov_membase_reg dest disp source 1
->
-> instance Mov (Disp, Reg32) Reg16 where
->   mov (Disp disp, Reg32 dest) (Reg16 source) = x86_mov_membase_reg dest disp source 2
->
-> instance Mov (Disp, Reg32) Reg32 where
->   mov (Disp disp, Reg32 dest) (Reg32 source) = x86_mov_membase_reg dest disp source 4
->
-> instance Mov Reg8 (Disp, Reg32) where
->   mov (Reg8 dest) (Disp disp, Reg32 source) = x86_mov_reg_membase dest source disp 1
->
-> instance Mov Reg16 (Disp, Reg32) where
->   mov (Reg16 dest) (Disp disp, Reg32 source) = x86_mov_reg_membase dest source disp 2
->
-> instance Mov Reg32 (Disp, Reg32) where
->   mov (Reg32 dest) (Disp disp, Reg32 source) = x86_mov_reg_membase dest source disp 4
-
-
-> instance Mov (Reg32, Reg32, Scale) Reg8 where
->   mov (Reg32 base, Reg32 index, s) (Reg8 source) = x86_mov_memindex_reg base 0 index (scaleToShift s) source 1
->
-> instance Mov (Reg32, Reg32, Scale) Reg16 where
->   mov (Reg32 base, Reg32 index, s) (Reg16 source) = x86_mov_memindex_reg base 0 index (scaleToShift s) source 2
->
-> instance Mov (Reg32, Reg32, Scale) Reg32 where
->   mov (Reg32 base, Reg32 index, s) (Reg32 source) = x86_mov_memindex_reg base 0 index (scaleToShift s) source 4
->
-> instance Mov Reg8 (Reg32, Reg32, Scale) where
->   mov (Reg8 dest) (Reg32 base, Reg32 index, s) = x86_mov_reg_memindex dest base 0 index (scaleToShift s) 1
->
-> instance Mov Reg16 (Reg32, Reg32, Scale) where
->   mov (Reg16 dest) (Reg32 base, Reg32 index, s) = x86_mov_reg_memindex dest base 0 index (scaleToShift s) 2
->
-> instance Mov Reg32 (Reg32, Reg32, Scale) where
->   mov (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_mov_reg_memindex dest base 0 index (scaleToShift s) 4
-
-
-> instance Mov (Disp, Reg32, Scale) Reg8 where
->   mov (Disp disp, Reg32 index, s) (Reg8 source) = x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 1
->
-> instance Mov (Disp, Reg32, Scale) Reg16 where
->   mov (Disp disp, Reg32 index, s) (Reg16 source) = x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 2
->
-> instance Mov (Disp, Reg32, Scale) Reg32 where
->   mov (Disp disp, Reg32 index, s) (Reg32 source) = x86_mov_memindex_reg x86_nobasereg disp index (scaleToShift s) source 4
->
-> instance Mov Reg8 (Disp, Reg32, Scale) where
->   mov (Reg8 dest) (Disp disp, Reg32 index, s) = x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 1
->
-> instance Mov Reg16 (Disp, Reg32, Scale) where
->   mov (Reg16 dest) (Disp disp, Reg32 index, s) = x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 2
->
-> instance Mov Reg32 (Disp, Reg32, Scale) where
->   mov (Reg32 dest) (Disp disp, Reg32 index, s) = x86_mov_reg_memindex dest x86_nobasereg disp index (scaleToShift s) 4
-
-
-> instance Mov (Disp, Reg32, Reg32, Scale) Reg8 where
->   mov (Disp disp, Reg32 5, Reg32 index, s) (Reg8 source) = x86_mov_memindex_reg 5 disp index (scaleToShift s) source 1
->   mov _ _ = onlyEbp
->
-> instance Mov (Disp, Reg32, Reg32, Scale) Reg16 where
->   mov (Disp disp, Reg32 5, Reg32 index, s) (Reg16 source) = x86_mov_memindex_reg 5 disp index (scaleToShift s) source 2
->   mov _ _ = onlyEbp
->
-> instance Mov (Disp, Reg32, Reg32, Scale) Reg32 where
->   mov (Disp disp, Reg32 5, Reg32 index, s) (Reg32 source) = x86_mov_memindex_reg 5 disp index (scaleToShift s) source 4
->   mov _ _ = onlyEbp
->
-> instance Mov Reg8 (Disp, Reg32, Reg32, Scale) where
->   mov (Reg8 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 1
->   mov _ _ = onlyEbp
->
-> instance Mov Reg16 (Disp, Reg32, Reg32, Scale) where
->   mov (Reg16 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 2
->   mov _ _ = onlyEbp
->
-> instance Mov Reg32 (Disp, Reg32, Reg32, Scale) where
->   mov (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_mov_reg_memindex dest 5 disp index (scaleToShift s) 4
->   mov _ _ = onlyEbp
-
-
-move with sign-extension
-
-> class Movsxb a b where
->   movsxb :: a -> b -> CodeGen e s ()
-
-> instance Movsxb Reg32 Reg8 where
->   movsxb (Reg32 dest) (Reg8 source) = x86_widen_reg dest source True False
->
-> instance Movsxb Reg32 Addr where
->   movsxb (Reg32 dest) (Addr source) = x86_widen_mem dest source True False
->
-> instance Movsxb Reg32 (Disp, Reg32) where
->   movsxb (Reg32 dest) (Disp disp, Reg32 source) = x86_widen_membase dest source disp True False
->
-> instance Movsxb Reg32 Ind where
->   movsxb (Reg32 dest) (Ind (Reg32 source)) = x86_widen_membase dest source 0 True False
->
-> instance Movsxb Reg32 (Disp, Reg32, Reg32, Scale) where
->   movsxb (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_widen_memindex dest 5 disp index (scaleToShift s) True False
->   movsxb _ _ = onlyEbp
->
-> instance Movsxb Reg32 (Disp, Reg32, Scale) where
->   movsxb (Reg32 dest) (Disp disp, Reg32 index, s) = x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) True False
->
-> instance Movsxb Reg32 (Reg32, Reg32, Scale) where
->   movsxb (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_widen_memindex dest base 0 index (scaleToShift s) True False
-
-> class Movsxw a b where
->   movsxw :: a -> b -> CodeGen e s ()
-
-> instance Movsxw Reg32 Reg16 where
->   movsxw (Reg32 dest) (Reg16 source) = x86_widen_reg dest source True True
->
-> instance Movsxw Reg32 Addr where
->   movsxw (Reg32 dest) (Addr source) = x86_widen_mem dest source True True
->
-> instance Movsxw Reg32 (Disp, Reg32) where
->   movsxw (Reg32 dest) (Disp disp, Reg32 source) = x86_widen_membase dest source disp True True
->
-> instance Movsxw Reg32 Ind where
->   movsxw (Reg32 dest) (Ind (Reg32 source)) = x86_widen_membase dest source 0 True True
->
-> instance Movsxw Reg32 (Disp, Reg32, Reg32, Scale) where
->   movsxw (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_widen_memindex dest 5 disp index (scaleToShift s) True True
->   movsxw _ _ = onlyEbp
->
-> instance Movsxw Reg32 (Disp, Reg32, Scale) where
->   movsxw (Reg32 dest) (Disp disp, Reg32 index, s) = x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) True True
->
-> instance Movsxw Reg32 (Reg32, Reg32, Scale) where
->   movsxw (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_widen_memindex dest base 0 index (scaleToShift s) True True
-
-
-move with zero-extension
-
-> class Movzxb a b where
->   movzxb :: a -> b -> CodeGen e s ()
-
-> instance Movzxb Reg32 Reg8 where
->   movzxb (Reg32 dest) (Reg8 source) = x86_widen_reg dest source False False
->
-> instance Movzxb Reg32 Addr where
->   movzxb (Reg32 dest) (Addr source) = x86_widen_mem dest source False False
->
-> instance Movzxb Reg32 (Disp, Reg32) where
->   movzxb (Reg32 dest) (Disp disp, Reg32 source) = x86_widen_membase dest source disp False False
->
-> instance Movzxb Reg32 Ind where
->   movzxb (Reg32 dest) (Ind (Reg32 source)) = x86_widen_membase dest source 0 False False
->
-> instance Movzxb Reg32 (Disp, Reg32, Reg32, Scale) where
->   movzxb (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_widen_memindex dest 5 disp index (scaleToShift s) False False
->   movzxb _ _ = onlyEbp
->
-> instance Movzxb Reg32 (Disp, Reg32, Scale) where
->   movzxb (Reg32 dest) (Disp disp, Reg32 index, s) = x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) False False
->
-> instance Movzxb Reg32 (Reg32, Reg32, Scale) where
->   movzxb (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_widen_memindex dest base 0 index (scaleToShift s) False False
-
-> class Movzxw a b where
->   movzxw :: a -> b -> CodeGen e s ()
-
-> instance Movzxw Reg32 Reg16 where
->   movzxw (Reg32 dest) (Reg16 source) = x86_widen_reg dest source False True
->
-> instance Movzxw Reg32 Addr where
->   movzxw (Reg32 dest) (Addr source) = x86_widen_mem dest source False True
->
-> instance Movzxw Reg32 (Disp, Reg32) where
->   movzxw (Reg32 dest) (Disp disp, Reg32 source) = x86_widen_membase dest source disp False True
->
-> instance Movzxw Reg32 Ind where
->   movzxw (Reg32 dest) (Ind (Reg32 source)) = x86_widen_membase dest source 0 False True
->
-> instance Movzxw Reg32 (Disp, Reg32, Reg32, Scale) where
->   movzxw (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_widen_memindex dest 5 disp index (scaleToShift s) False True
->   movzxw _ _ = onlyEbp
->
-> instance Movzxw Reg32 (Disp, Reg32, Scale) where
->   movzxw (Reg32 dest) (Disp disp, Reg32 index, s) = x86_widen_memindex dest x86_nobasereg disp index (scaleToShift s) False True
->
-> instance Movzxw Reg32 (Reg32, Reg32, Scale) where
->   movzxw (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_widen_memindex dest base 0 index (scaleToShift s) False True
-
-
-load effective address
-
-> class Lea a b where
->   lea :: a -> b -> CodeGen e s ()
-
-> instance Lea Reg32 Addr where
->   lea (Reg32 dest) (Addr source) = x86_lea_mem dest source 
->
-> instance Lea Reg32 (Disp, Reg32) where
->   lea (Reg32 dest) (Disp disp, Reg32 source) = x86_lea_membase dest source disp 
->
-> instance Lea Reg32 Ind where
->   lea (Reg32 dest) (Ind (Reg32 source)) = x86_lea_membase dest source 0 
->
-> instance Lea Reg32 (Disp, Reg32, Reg32, Scale) where
->   lea (Reg32 dest) (Disp disp, Reg32 5, Reg32 index, s) = x86_lea_memindex dest 5 disp index (scaleToShift s)
->   lea _ _ = onlyEbp
->
-> instance Lea Reg32 (Disp, Reg32, Scale) where
->   lea (Reg32 dest) (Disp disp, Reg32 index, s) = x86_lea_memindex dest x86_nobasereg disp index (scaleToShift s)
->
-> instance Lea Reg32 (Reg32, Reg32, Scale) where
->   lea (Reg32 dest) (Reg32 base, Reg32 index, s) = x86_lea_memindex dest base 0 index (scaleToShift s)
-
-
-convert word to doubleword
-
-> cdq = x86_cdq
-
-
-wait for FPU
-
-> wait = x86_wait
-
-
-push to stack
-
-> class Push a where
->   push :: a -> CodeGen e s ()
-
-> instance Push Reg32 where
->   push (Reg32 source) = x86_push_reg source 
->
-> instance Push Ind where
->   push (Ind (Reg32 source)) = x86_push_regp source
->
-> instance Push Addr where
->   push (Addr source) = x86_push_mem source 
->
-> instance Push (Disp, Reg32) where
->   push (Disp disp, Reg32 source) = x86_push_membase source disp 
->
-> instance Push Word32 where
->   push imm = x86_push_imm imm 
->
-> instance Push Label where
->   push l = do x86_push_imm_template
->               emitFixup l (-4) Fixup32Absolute
->
-> instance Push (Disp, Reg32, Reg32, Scale) where
->   push (Disp disp, Reg32 5, Reg32 index, s) = x86_push_memindex 5 disp index (scaleToShift s)
->   push _ = onlyEbp
->
-> instance Push (Disp, Reg32, Scale) where
->   push (Disp disp, Reg32 index, s) = x86_push_memindex x86_nobasereg disp index (scaleToShift s)
->
-> instance Push (Reg32, Reg32, Scale) where
->   push (Reg32 base, Reg32 index, s) = x86_push_memindex base 0 index (scaleToShift s)
-
-
-pop from stack
-
-> class Pop a where
->   pop :: a -> CodeGen e s ()
-
-> instance Pop Reg32 where
->   pop (Reg32 dest) = x86_pop_reg dest 
->
-> instance Pop Addr where
->   pop (Addr dest) = x86_pop_mem dest 
->
-> instance Pop (Disp, Reg32) where
->   pop (Disp disp, Reg32 dest) = x86_pop_membase dest disp 
->
-> instance Pop Ind where
->   pop (Ind (Reg32 dest)) = x86_pop_membase dest 0 
-
-
-push/pop general purpose registers
-
-> pushad = x86_pushad
-> popad  = x86_popad
-
-
-push/pop EFLAGS
-
-> pushfd = x86_pushfd
-> popfd  = x86_popfd
-
-
-loop according to ECX couter
-
-> loop   :: Word8 -> CodeGen e s ()
-> loop   = x86_loop
-
-> loope  :: Word8 -> CodeGen e s ()
-> loope  = x86_loope
-
-> loopne :: Word8 -> CodeGen e s ()
-> loopne = x86_loopne
-
-
-jump
-
-> class Jmp a where
->   jmp :: a -> CodeGen e s ()
-
-> instance Jmp Word8 where
->   jmp imm = x86_jump8 imm 
->
-> instance Jmp Word32 where
->   jmp imm = x86_jump32 imm 
->
-> instance Jmp Reg32 where
->   jmp (Reg32 dest) = x86_jump_reg dest 
->
-> instance Jmp Addr where
->   jmp (Addr dest) = x86_jump_mem dest 
->
-> instance Jmp (Disp, Reg32) where
->   jmp (Disp disp, Reg32 dest) = x86_jump_membase dest disp 
->
-> instance Jmp Ind where
->   jmp (Ind (Reg32 dest)) = x86_jump_membase dest 0 
->
-> instance Jmp Label where
->   jmp l = do x86_jump32 0
->              emitFixup l (-4) Fixup32
-              
-jump on condition code (branch)
-
-> class Ja a where
->   ja :: a -> CodeGen e s ()
-
-> instance Ja Word8 where
->   ja imm = x86_branch8 x86_cc_a imm False
->
-> instance Ja Word32 where
->   ja imm = x86_branch32 x86_cc_a imm False
-
-> class Jae a where
->   jae :: a -> CodeGen e s ()
-
-> instance Jae Word8 where
->   jae imm = x86_branch8 x86_cc_ae imm False
->
-> instance Jae Word32 where
->   jae imm = x86_branch32 x86_cc_ae imm False
-> 
-> instance Jae Label where
->   jae l = do x86_branch32 x86_cc_ae 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jb a where
->   jb :: a -> CodeGen e s ()
-
-> instance Jb Word8 where
->   jb imm = x86_branch8 x86_cc_b imm False
->
-> instance Jb Word32 where
->   jb imm = x86_branch32 x86_cc_b imm False
-> 
-> instance Jb Label where
->   jb l = do x86_branch32 x86_cc_b 0 False
->             emitFixup l (-4) Fixup32
-
-> class Jbe a where
->   jbe :: a -> CodeGen e s ()
-
-> instance Jbe Word8 where
->   jbe imm = x86_branch8 x86_cc_be imm False
->
-> instance Jbe Word32 where
->   jbe imm = x86_branch32 x86_cc_be imm False
-> 
-> instance Jbe Label where
->   jbe l = do x86_branch32 x86_cc_be 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jc a where
->   jc :: a -> CodeGen e s ()
-
-> instance Jc Word8 where
->   jc imm = x86_branch8 x86_cc_c imm False
->
-> instance Jc Word32 where
->   jc imm = x86_branch32 x86_cc_c imm False
-> 
-> instance Jc Label where
->   jc l = do x86_branch32 x86_cc_c 0 False
->             emitFixup l (-4) Fixup32
-
-> class Je a where
->   je :: a -> CodeGen e s ()
-
-> instance Je Word8 where
->   je imm = x86_branch8 x86_cc_e imm False
->
-> instance Je Word32 where
->   je imm = x86_branch32 x86_cc_e imm False
-> 
-> instance Je Label where
->   je l = do x86_branch32 x86_cc_e 0 False
->             emitFixup l (-4) Fixup32
-
-> class Jna a where
->   jna :: a -> CodeGen e s ()
-
-> instance Jna Word8 where
->   jna imm = x86_branch8 x86_cc_na imm False
->
-> instance Jna Word32 where
->   jna imm = x86_branch32 x86_cc_na imm False
-> 
-> instance Jna Label where
->   jna l = do x86_branch32 x86_cc_na 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jnae a where
->   jnae :: a -> CodeGen e s ()
-
-> instance Jnae Word8 where
->   jnae imm = x86_branch8 x86_cc_nae imm False
->
-> instance Jnae Word32 where
->   jnae imm = x86_branch32 x86_cc_nae imm False
-> 
-> instance Jnae Label where
->   jnae l = do x86_branch32 x86_cc_nae 0 False
->               emitFixup l (-4) Fixup32
-
-> class Jnb a where
->   jnb :: a -> CodeGen e s ()
-
-> instance Jnb Word8 where
->   jnb imm = x86_branch8 x86_cc_nb imm False
->
-> instance Jnb Word32 where
->   jnb imm = x86_branch32 x86_cc_nb imm False
-> 
-> instance Jnb Label where
->   jnb l = do x86_branch32 x86_cc_nb 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jnbe a where
->   jnbe :: a -> CodeGen e s ()
-
-> instance Jnbe Word8 where
->   jnbe imm = x86_branch8 x86_cc_nbe imm False
->
-> instance Jnbe Word32 where
->   jnbe imm = x86_branch32 x86_cc_nbe imm False
-> 
-> instance Jnbe Label where
->   jnbe l = do x86_branch32 x86_cc_nbe 0 False
->               emitFixup l (-4) Fixup32
-
-> class Jnc a where
->   jnc :: a -> CodeGen e s ()
-
-> instance Jnc Word8 where
->   jnc imm = x86_branch8 x86_cc_nc imm False
->
-> instance Jnc Word32 where
->   jnc imm = x86_branch32 x86_cc_nc imm False
-> 
-> instance Jnc Label where
->   jnc l = do x86_branch32 x86_cc_nc 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jne a where
->   jne :: a -> CodeGen e s ()
-
-> instance Jne Word8 where
->   jne imm = x86_branch8 x86_cc_ne imm False
->
-> instance Jne Word32 where
->   jne imm = x86_branch32 x86_cc_ne imm False
-> 
-> instance Jne Label where
->   jne l = do x86_branch32 x86_cc_ne 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jnp a where
->   jnp :: a -> CodeGen e s ()
-
-> instance Jnp Word8 where
->   jnp imm = x86_branch8 x86_cc_np imm False
->
-> instance Jnp Word32 where
->   jnp imm = x86_branch32 x86_cc_np imm False
-> 
-> instance Jnp Label where
->   jnp l = do x86_branch32 x86_cc_np 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jnz a where
->   jnz :: a -> CodeGen e s ()
-
-> instance Jnz Word8 where
->   jnz imm = x86_branch8 x86_cc_nz imm False
->
-> instance Jnz Word32 where
->   jnz imm = x86_branch32 x86_cc_nz imm False
-> 
-> instance Jnz Label where
->   jnz l = do x86_branch32 x86_cc_nz 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jp a where
->   jp :: a -> CodeGen e s ()
-
-> instance Jp Word8 where
->   jp imm = x86_branch8 x86_cc_p imm False
->
-> instance Jp Word32 where
->   jp imm = x86_branch32 x86_cc_p imm False
-> 
-> instance Jp Label where
->   jp l = do x86_branch32 x86_cc_p 0 False
->             emitFixup l (-4) Fixup32
-
-> class Jpe a where
->   jpe :: a -> CodeGen e s ()
-
-> instance Jpe Word8 where
->   jpe imm = x86_branch8 x86_cc_pe imm False
->
-> instance Jpe Word32 where
->   jpe imm = x86_branch32 x86_cc_pe imm False
-> 
-> instance Jpe Label where
->   jpe l = do x86_branch32 x86_cc_pe 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jpo a where
->   jpo :: a -> CodeGen e s ()
-
-> instance Jpo Word8 where
->   jpo imm = x86_branch8 x86_cc_po imm False
->
-> instance Jpo Word32 where
->   jpo imm = x86_branch32 x86_cc_po imm False
-> 
-> instance Jpo Label where
->   jpo l = do x86_branch32 x86_cc_po 0 False
->              emitFixup l (-4) Fixup32
-
-> class Jz a where
->   jz :: a -> CodeGen e s ()
-
-> instance Jz Word8 where
->   jz imm = x86_branch8 x86_cc_z imm False
->
-> instance Jz Word32 where
->   jz imm = x86_branch32 x86_cc_z imm False
-> 
-> instance Jz Label where
->   jz l = do x86_branch32 x86_cc_z 0 False
->             emitFixup l (-4) Fixup32
-
-> class Jg a where
->   jg :: a -> CodeGen e s ()
-
-> instance Jg Word8 where
->   jg imm = x86_branch8 x86_cc_gt imm True
->
-> instance Jg Word32 where
->   jg imm = x86_branch32 x86_cc_gt imm True
-> 
-> instance Jg Label where
->   jg l = do x86_branch32 x86_cc_gt 0 True
->             emitFixup l (-4) Fixup32
-
-> class Jge a where
->   jge :: a -> CodeGen e s ()
-
-> instance Jge Word8 where
->   jge imm = x86_branch8 x86_cc_ge imm True
->
-> instance Jge Word32 where
->   jge imm = x86_branch32 x86_cc_ge imm True
-> 
-> instance Jge Label where
->   jge l = do x86_branch32 x86_cc_ge 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jl a where
->   jl :: a -> CodeGen e s ()
-
-> instance Jl Word8 where
->   jl imm = x86_branch8 x86_cc_lt imm True
->
-> instance Jl Word32 where
->   jl imm = x86_branch32 x86_cc_lt imm True
-> 
-> instance Jl Label where
->   jl l = do x86_branch32 x86_cc_lt 0 True
->             emitFixup l (-4) Fixup32
-
-> class Jle a where
->   jle :: a -> CodeGen e s ()
-
-> instance Jle Word8 where
->   jle imm = x86_branch8 x86_cc_le imm True
->
-> instance Jle Word32 where
->   jle imm = x86_branch32 x86_cc_le imm True
-> 
-> instance Jle Label where
->   jle l = do x86_branch32 x86_cc_le 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jng a where
->   jng :: a -> CodeGen e s ()
-
-> instance Jng Word8 where
->   jng imm = x86_branch8 x86_cc_le imm True
->
-> instance Jng Word32 where
->   jng imm = x86_branch32 x86_cc_le imm True
-> 
-> instance Jng Label where
->   jng l = do x86_branch32 x86_cc_le 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jnge a where
->   jnge :: a -> CodeGen e s ()
-
-> instance Jnge Word8 where
->   jnge imm = x86_branch8 x86_cc_lt imm True
->
-> instance Jnge Word32 where
->   jnge imm = x86_branch32 x86_cc_lt imm True
-> 
-> instance Jnge Label where
->   jnge l = do x86_branch32 x86_cc_lt 0 True
->               emitFixup l (-4) Fixup32
-
-> class Jnl a where
->   jnl :: a -> CodeGen e s ()
-
-> instance Jnl Word8 where
->   jnl imm = x86_branch8 x86_cc_ge imm True
->
-> instance Jnl Word32 where
->   jnl imm = x86_branch32 x86_cc_ge imm True
-> 
-> instance Jnl Label where
->   jnl l = do x86_branch32 x86_cc_ge 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jnle a where
->   jnle :: a -> CodeGen e s ()
-
-> instance Jnle Word8 where
->   jnle imm = x86_branch8 x86_cc_gt imm True
->
-> instance Jnle Word32 where
->   jnle imm = x86_branch32 x86_cc_gt imm True
-> 
-> instance Jnle Label where
->   jnle l = do x86_branch32 x86_cc_gt 0 True
->               emitFixup l (-4) Fixup32
-
-> class Jno a where
->   jno :: a -> CodeGen e s ()
-
-> instance Jno Word8 where
->   jno imm = x86_branch8 x86_cc_no imm True
->
-> instance Jno Word32 where
->   jno imm = x86_branch32 x86_cc_no imm True
-> 
-> instance Jno Label where
->   jno l = do x86_branch32 x86_cc_no 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jns a where
->   jns :: a -> CodeGen e s ()
-
-> instance Jns Word8 where
->   jns imm = x86_branch8 x86_cc_ns imm True
->
-> instance Jns Word32 where
->   jns imm = x86_branch32 x86_cc_ns imm True
-> 
-> instance Jns Label where
->   jns l = do x86_branch32 x86_cc_ns 0 True
->              emitFixup l (-4) Fixup32
-
-> class Jo a where
->   jo :: a -> CodeGen e s ()
-
-> instance Jo Word8 where
->   jo imm = x86_branch8 x86_cc_o imm True
->
-> instance Jo Word32 where
->   jo imm = x86_branch32 x86_cc_o imm True
-> 
-> instance Jo Label where
->   jo l = do x86_branch32 x86_cc_o 0 True
->             emitFixup l (-4) Fixup32
-
-> class Js a where
->   js :: a -> CodeGen e s ()
-
-> instance Js Word8 where
->   js imm = x86_branch8 x86_cc_s imm True
->
-> instance Js Word32 where
->   js imm = x86_branch32 x86_cc_s imm True
-> 
-> instance Js Label where
->   js l = do x86_branch32 x86_cc_s 0 True
->             emitFixup l (-4) Fixup32
-
-jump if ecx register is 0
-
-> jecxz :: Word8 -> CodeGen e s ()
-> jecxz = x86_jecxz
-
-
-set byte on condition code
-
-> class Seta a where
->   seta :: a -> CodeGen e s ()
-
-> instance Seta Reg8 where
->   seta (Reg8 dest) = x86_set_reg x86_cc_a dest False
->
-> instance Seta Addr where
->   seta (Addr dest) = x86_set_mem x86_cc_a dest False
->
-> instance Seta (Disp, Reg32) where
->   seta (Disp disp, Reg32 dest) = x86_set_membase x86_cc_a dest disp False
->
-> instance Seta Ind where
->   seta (Ind (Reg32 dest)) = x86_set_membase x86_cc_a dest 0 False
-
-> class Setae a where
->   setae :: a -> CodeGen e s ()
-
-> instance Setae Reg8 where
->   setae (Reg8 dest) = x86_set_reg x86_cc_ae dest False
->
-> instance Setae Addr where
->   setae (Addr dest) = x86_set_mem x86_cc_ae dest False
->
-> instance Setae (Disp, Reg32) where
->   setae (Disp disp, Reg32 dest) = x86_set_membase x86_cc_ae dest disp False
->
-> instance Setae Ind where
->   setae (Ind (Reg32 dest)) = x86_set_membase x86_cc_ae dest 0 False
-
-> class Setb a where
->   setb :: a -> CodeGen e s ()
-
-> instance Setb Reg8 where
->   setb (Reg8 dest) = x86_set_reg x86_cc_b dest False
->
-> instance Setb Addr where
->   setb (Addr dest) = x86_set_mem x86_cc_b dest False
->
-> instance Setb (Disp, Reg32) where
->   setb (Disp disp, Reg32 dest) = x86_set_membase x86_cc_b dest disp False
->
-> instance Setb Ind where
->   setb (Ind (Reg32 dest)) = x86_set_membase x86_cc_b dest 0 False
-
-> class Setbe a where
->   setbe :: a -> CodeGen e s ()
-
-> instance Setbe Reg8 where
->   setbe (Reg8 dest) = x86_set_reg x86_cc_be dest False
->
-> instance Setbe Addr where
->   setbe (Addr dest) = x86_set_mem x86_cc_be dest False
->
-> instance Setbe (Disp, Reg32) where
->   setbe (Disp disp, Reg32 dest) = x86_set_membase x86_cc_be dest disp False
->
-> instance Setbe Ind where
->   setbe (Ind (Reg32 dest)) = x86_set_membase x86_cc_be dest 0 False
-
-> class Setc a where
->   setc :: a -> CodeGen e s ()
-
-> instance Setc Reg8 where
->   setc (Reg8 dest) = x86_set_reg x86_cc_c dest False
->
-> instance Setc Addr where
->   setc (Addr dest) = x86_set_mem x86_cc_c dest False
->
-> instance Setc (Disp, Reg32) where
->   setc (Disp disp, Reg32 dest) = x86_set_membase x86_cc_c dest disp False
->
-> instance Setc Ind where
->   setc (Ind (Reg32 dest)) = x86_set_membase x86_cc_c dest 0 False
-
-> class Sete a where
->   sete :: a -> CodeGen e s ()
-
-> instance Sete Reg8 where
->   sete (Reg8 dest) = x86_set_reg x86_cc_e dest False
->
-> instance Sete Addr where
->   sete (Addr dest) = x86_set_mem x86_cc_e dest False
->
-> instance Sete (Disp, Reg32) where
->   sete (Disp disp, Reg32 dest) = x86_set_membase x86_cc_e dest disp False
->
-> instance Sete Ind where
->   sete (Ind (Reg32 dest)) = x86_set_membase x86_cc_e dest 0 False
-
-> class Setna a where
->   setna :: a -> CodeGen e s ()
-
-> instance Setna Reg8 where
->   setna (Reg8 dest) = x86_set_reg x86_cc_na dest False
->
-> instance Setna Addr where
->   setna (Addr dest) = x86_set_mem x86_cc_na dest False
->
-> instance Setna (Disp, Reg32) where
->   setna (Disp disp, Reg32 dest) = x86_set_membase x86_cc_na dest disp False
->
-> instance Setna Ind where
->   setna (Ind (Reg32 dest)) = x86_set_membase x86_cc_na dest 0 False
-
-> class Setnae a where
->   setnae :: a -> CodeGen e s ()
-
-> instance Setnae Reg8 where
->   setnae (Reg8 dest) = x86_set_reg x86_cc_nae dest False
->
-> instance Setnae Addr where
->   setnae (Addr dest) = x86_set_mem x86_cc_nae dest False
->
-> instance Setnae (Disp, Reg32) where
->   setnae (Disp disp, Reg32 dest) = x86_set_membase x86_cc_nae dest disp False
->
-> instance Setnae Ind where
->   setnae (Ind (Reg32 dest)) = x86_set_membase x86_cc_nae dest 0 False
-
-> class Setnb a where
->   setnb :: a -> CodeGen e s ()
-
-> instance Setnb Reg8 where
->   setnb (Reg8 dest) = x86_set_reg x86_cc_nb dest False
->
-> instance Setnb Addr where
->   setnb (Addr dest) = x86_set_mem x86_cc_nb dest False
->
-> instance Setnb (Disp, Reg32) where
->   setnb (Disp disp, Reg32 dest) = x86_set_membase x86_cc_nb dest disp False
->
-> instance Setnb Ind where
->   setnb (Ind (Reg32 dest)) = x86_set_membase x86_cc_nb dest 0 False
-
-> class Setnbe a where
->   setnbe :: a -> CodeGen e s ()
-
-> instance Setnbe Reg8 where
->   setnbe (Reg8 dest) = x86_set_reg x86_cc_nbe dest False
->
-> instance Setnbe Addr where
->   setnbe (Addr dest) = x86_set_mem x86_cc_nbe dest False
->
-> instance Setnbe (Disp, Reg32) where
->   setnbe (Disp disp, Reg32 dest) = x86_set_membase x86_cc_nbe dest disp False
->
-> instance Setnbe Ind where
->   setnbe (Ind (Reg32 dest)) = x86_set_membase x86_cc_nbe dest 0 False
-
-> class Setnc a where
->   setnc :: a -> CodeGen e s ()
-
-> instance Setnc Reg8 where
->   setnc (Reg8 dest) = x86_set_reg x86_cc_nc dest False
->
-> instance Setnc Addr where
->   setnc (Addr dest) = x86_set_mem x86_cc_nc dest False
->
-> instance Setnc (Disp, Reg32) where
->   setnc (Disp disp, Reg32 dest) = x86_set_membase x86_cc_nc dest disp False
->
-> instance Setnc Ind where
->   setnc (Ind (Reg32 dest)) = x86_set_membase x86_cc_nc dest 0 False
-
-> class Setne a where
->   setne :: a -> CodeGen e s ()
-
-> instance Setne Reg8 where
->   setne (Reg8 dest) = x86_set_reg x86_cc_ne dest False
->
-> instance Setne Addr where
->   setne (Addr dest) = x86_set_mem x86_cc_ne dest False
->
-> instance Setne (Disp, Reg32) where
->   setne (Disp disp, Reg32 dest) = x86_set_membase x86_cc_ne dest disp False
->
-> instance Setne Ind where
->   setne (Ind (Reg32 dest)) = x86_set_membase x86_cc_ne dest 0 False
-
-> class Setnp a where
->   setnp :: a -> CodeGen e s ()
-
-> instance Setnp Reg8 where
->   setnp (Reg8 dest) = x86_set_reg x86_cc_np dest False
->
-> instance Setnp Addr where
->   setnp (Addr dest) = x86_set_mem x86_cc_np dest False
->
-> instance Setnp (Disp, Reg32) where
->   setnp (Disp disp, Reg32 dest) = x86_set_membase x86_cc_np dest disp False
->
-> instance Setnp Ind where
->   setnp (Ind (Reg32 dest)) = x86_set_membase x86_cc_np dest 0 False
-
-> class Setnz a where
->   setnz :: a -> CodeGen e s ()
-
-> instance Setnz Reg8 where
->   setnz (Reg8 dest) = x86_set_reg x86_cc_nz dest False
->
-> instance Setnz Addr where
->   setnz (Addr dest) = x86_set_mem x86_cc_nz dest False
->
-> instance Setnz (Disp, Reg32) where
->   setnz (Disp disp, Reg32 dest) = x86_set_membase x86_cc_nz dest disp False
->
-> instance Setnz Ind where
->   setnz (Ind (Reg32 dest)) = x86_set_membase x86_cc_nz dest 0 False
-
-> class Setp a where
->   setp :: a -> CodeGen e s ()
-
-> instance Setp Reg8 where
->   setp (Reg8 dest) = x86_set_reg x86_cc_p dest False
->
-> instance Setp Addr where
->   setp (Addr dest) = x86_set_mem x86_cc_p dest False
->
-> instance Setp (Disp, Reg32) where
->   setp (Disp disp, Reg32 dest) = x86_set_membase x86_cc_p dest disp False
->
-> instance Setp Ind where
->   setp (Ind (Reg32 dest)) = x86_set_membase x86_cc_p dest 0 False
-
-> class Setpe a where
->   setpe :: a -> CodeGen e s ()
-
-> instance Setpe Reg8 where
->   setpe (Reg8 dest) = x86_set_reg x86_cc_pe dest False
->
-> instance Setpe Addr where
->   setpe (Addr dest) = x86_set_mem x86_cc_pe dest False
->
-> instance Setpe (Disp, Reg32) where
->   setpe (Disp disp, Reg32 dest) = x86_set_membase x86_cc_pe dest disp False
->
-> instance Setpe Ind where
->   setpe (Ind (Reg32 dest)) = x86_set_membase x86_cc_pe dest 0 False
-
-> class Setpo a where
->   setpo :: a -> CodeGen e s ()
-
-> instance Setpo Reg8 where
->   setpo (Reg8 dest) = x86_set_reg x86_cc_po dest False
->
-> instance Setpo Addr where
->   setpo (Addr dest) = x86_set_mem x86_cc_po dest False
->
-> instance Setpo (Disp, Reg32) where
->   setpo (Disp disp, Reg32 dest) = x86_set_membase x86_cc_po dest disp False
->
-> instance Setpo Ind where
->   setpo (Ind (Reg32 dest)) = x86_set_membase x86_cc_po dest 0 False
-
-> class Setg a where
->   setg :: a -> CodeGen e s ()
-
-> instance Setg Reg8 where
->   setg (Reg8 dest) = x86_set_reg x86_cc_gt dest True
->
-> instance Setg Addr where
->   setg (Addr dest) = x86_set_mem x86_cc_gt dest True
->
-> instance Setg (Disp, Reg32) where
->   setg (Disp disp, Reg32 dest) = x86_set_membase x86_cc_gt dest disp True
->
-> instance Setg Ind where
->   setg (Ind (Reg32 dest)) = x86_set_membase x86_cc_gt dest 0 True
-
-> class Setge a where
->   setge :: a -> CodeGen e s ()
-
-> instance Setge Reg8 where
->   setge (Reg8 dest) = x86_set_reg x86_cc_ge dest True
->
-> instance Setge Addr where
->   setge (Addr dest) = x86_set_mem x86_cc_ge dest True
->
-> instance Setge (Disp, Reg32) where
->   setge (Disp disp, Reg32 dest) = x86_set_membase x86_cc_ge dest disp True
->
-> instance Setge Ind where
->   setge (Ind (Reg32 dest)) = x86_set_membase x86_cc_ge dest 0 True
-
-> class Setl a where
->   setl :: a -> CodeGen e s ()
-
-> instance Setl Reg8 where
->   setl (Reg8 dest) = x86_set_reg x86_cc_lt dest True
->
-> instance Setl Addr where
->   setl (Addr dest) = x86_set_mem x86_cc_lt dest True
->
-> instance Setl (Disp, Reg32) where
->   setl (Disp disp, Reg32 dest) = x86_set_membase x86_cc_lt dest disp True
->
-> instance Setl Ind where
->   setl (Ind (Reg32 dest)) = x86_set_membase x86_cc_lt dest 0 True
-
-> class Setle a where
->   setle :: a -> CodeGen e s ()
-
-> instance Setle Reg8 where
->   setle (Reg8 dest) = x86_set_reg x86_cc_le dest True
->
-> instance Setle Addr where
->   setle (Addr dest) = x86_set_mem x86_cc_le dest True
->
-> instance Setle (Disp, Reg32) where
->   setle (Disp disp, Reg32 dest) = x86_set_membase x86_cc_le dest disp True
->
-> instance Setle Ind where
->   setle (Ind (Reg32 dest)) = x86_set_membase x86_cc_le dest 0 True
-
-> class Setng a where
->   setng :: a -> CodeGen e s ()
-
-> instance Setng Reg8 where
->   setng (Reg8 dest) = x86_set_reg x86_cc_le dest True
->
-> instance Setng Addr where
->   setng (Addr dest) = x86_set_mem x86_cc_le dest True
->
-> instance Setng (Disp, Reg32) where
->   setng (Disp disp, Reg32 dest) = x86_set_membase x86_cc_le dest disp True
->
-> instance Setng Ind where
->   setng (Ind (Reg32 dest)) = x86_set_membase x86_cc_le dest 0 True
-
-> class Setnge a where
->   setnge :: a -> CodeGen e s ()
-
-> instance Setnge Reg8 where
->   setnge (Reg8 dest) = x86_set_reg x86_cc_lt dest True
->
-> instance Setnge Addr where
->   setnge (Addr dest) = x86_set_mem x86_cc_lt dest True
->
-> instance Setnge (Disp, Reg32) where
->   setnge (Disp disp, Reg32 dest) = x86_set_membase x86_cc_lt dest disp True
->
-> instance Setnge Ind where
->   setnge (Ind (Reg32 dest)) = x86_set_membase x86_cc_lt dest 0 True
-
-> class Setnl a where
->   setnl :: a -> CodeGen e s ()
-
-> instance Setnl Reg8 where
->   setnl (Reg8 dest) = x86_set_reg x86_cc_ge dest True
->
-> instance Setnl Addr where
->   setnl (Addr dest) = x86_set_mem x86_cc_ge dest True
->
-> instance Setnl (Disp, Reg32) where
->   setnl (Disp disp, Reg32 dest) = x86_set_membase x86_cc_ge dest disp True
->
-> instance Setnl Ind where
->   setnl (Ind (Reg32 dest)) = x86_set_membase x86_cc_ge dest 0 True
-
-> class Setnle a where
->   setnle :: a -> CodeGen e s ()
-
-> instance Setnle Reg8 where
->   setnle (Reg8 dest) = x86_set_reg x86_cc_gt dest True
->
-> instance Setnle Addr where
->   setnle (Addr dest) = x86_set_mem x86_cc_gt dest True
->
-> instance Setnle (Disp, Reg32) where
->   setnle (Disp disp, Reg32 dest) = x86_set_membase x86_cc_gt dest disp True
->
-> instance Setnle Ind where
->   setnle (Ind (Reg32 dest)) = x86_set_membase x86_cc_gt dest 0 True
-
-> class Setno a where
->   setno :: a -> CodeGen e s ()
-
-> instance Setno Reg8 where
->   setno (Reg8 dest) = x86_set_reg x86_cc_no dest True
->
-> instance Setno Addr where
->   setno (Addr dest) = x86_set_mem x86_cc_no dest True
->
-> instance Setno (Disp, Reg32) where
->   setno (Disp disp, Reg32 dest) = x86_set_membase x86_cc_no dest disp True
->
-> instance Setno Ind where
->   setno (Ind (Reg32 dest)) = x86_set_membase x86_cc_no dest 0 True
-
-> class Setns a where
->   setns :: a -> CodeGen e s ()
-
-> instance Setns Reg8 where
->   setns (Reg8 dest) = x86_set_reg x86_cc_ns dest True
->
-> instance Setns Addr where
->   setns (Addr dest) = x86_set_mem x86_cc_ns dest True
->
-> instance Setns (Disp, Reg32) where
->   setns (Disp disp, Reg32 dest) = x86_set_membase x86_cc_ns dest disp True
->
-> instance Setns Ind where
->   setns (Ind (Reg32 dest)) = x86_set_membase x86_cc_ns dest 0 True
-
-> class Seto a where
->   seto :: a -> CodeGen e s ()
-
-> instance Seto Reg8 where
->   seto (Reg8 dest) = x86_set_reg x86_cc_o dest True
->
-> instance Seto Addr where
->   seto (Addr dest) = x86_set_mem x86_cc_o dest True
->
-> instance Seto (Disp, Reg32) where
->   seto (Disp disp, Reg32 dest) = x86_set_membase x86_cc_o dest disp True
->
-> instance Seto Ind where
->   seto (Ind (Reg32 dest)) = x86_set_membase x86_cc_o dest 0 True
-
-> class Sets a where
->   sets :: a -> CodeGen e s ()
-
-> instance Sets Reg8 where
->   sets (Reg8 dest) = x86_set_reg x86_cc_s dest True
->
-> instance Sets Addr where
->   sets (Addr dest) = x86_set_mem x86_cc_s dest True
->
-> instance Sets (Disp, Reg32) where
->   sets (Disp disp, Reg32 dest) = x86_set_membase x86_cc_s dest disp True
->
-> instance Sets Ind where
->   sets (Ind (Reg32 dest)) = x86_set_membase x86_cc_s dest 0 True
-
-> class Setz a where
->   setz :: a -> CodeGen e s ()
-
-> instance Setz Reg8 where
->   setz (Reg8 dest) = x86_set_reg x86_cc_z dest False
->
-> instance Setz Addr where
->   setz (Addr dest) = x86_set_mem x86_cc_z dest False
->
-> instance Setz (Disp, Reg32) where
->   setz (Disp disp, Reg32 dest) = x86_set_membase x86_cc_z dest disp False
->
-> instance Setz Ind where
->   setz (Ind (Reg32 dest)) = x86_set_membase x86_cc_z dest 0 False
-
-
-call procedure
-
-> class Call a where
->   call :: a -> CodeGen e s ()
-
-> instance Call Word32 where
->   call imm = x86_call_imm imm 
->
-> instance Call Label where
->   call l = do x86_call_imm 0
->               emitFixup l (-4) Fixup32
->
-> instance Call Reg32 where
->   call (Reg32 dest) = x86_call_reg dest 
->
-> instance Call Addr where
->   call (Addr dest) = x86_call_mem dest 
->
-> instance Call (Disp, Reg32) where
->   call (Disp disp, Reg32 dest) = x86_call_membase dest disp 
->
-> instance Call Ind where
->   call (Ind (Reg32 dest)) = x86_call_membase dest 0 
->
-> instance Call (FunPtr a) where
->   call = x86_call_hs
-
-
-return from procedure
-
-> ret :: CodeGen e s ()
-> ret = x86_ret
->
-> retN :: Word16 -> CodeGen e s ()
-> retN n = x86_ret_imm n
-
-
-make stack frame
-
-> enter :: Word16 -> CodeGen e s ()
-> enter = x86_enter
-
-
-conditional move
-
-> class Cmova a b where
->   cmova :: a -> b -> CodeGen e s ()
-
-> instance Cmova Reg32 Reg32 where
->   cmova (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_a False dest source
->
-> instance Cmova Reg32 Addr where
->   cmova (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_a False dest source
->
-> instance Cmova Reg32 (Disp, Reg32) where
->   cmova (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_a False dest source disp
->
-> instance Cmova Reg32 Ind where
->   cmova (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_a False dest source 0
-
-> class Cmovae a b where
->   cmovae :: a -> b -> CodeGen e s ()
-
-> instance Cmovae Reg32 Reg32 where
->   cmovae (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_ae False dest source
->
-> instance Cmovae Reg32 Addr where
->   cmovae (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_ae False dest source
->
-> instance Cmovae Reg32 (Disp, Reg32) where
->   cmovae (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_ae False dest source disp
->
-> instance Cmovae Reg32 Ind where
->   cmovae (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_ae False dest source 0
-
-> class Cmovb a b where
->   cmovb :: a -> b -> CodeGen e s ()
-
-> instance Cmovb Reg32 Reg32 where
->   cmovb (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_b False dest source
->
-> instance Cmovb Reg32 Addr where
->   cmovb (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_b False dest source
->
-> instance Cmovb Reg32 (Disp, Reg32) where
->   cmovb (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_b False dest source disp
->
-> instance Cmovb Reg32 Ind where
->   cmovb (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_b False dest source 0
-
-> class Cmovbe a b where
->   cmovbe :: a -> b -> CodeGen e s ()
-
-> instance Cmovbe Reg32 Reg32 where
->   cmovbe (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_be False dest source
->
-> instance Cmovbe Reg32 Addr where
->   cmovbe (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_be False dest source
->
-> instance Cmovbe Reg32 (Disp, Reg32) where
->   cmovbe (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_be False dest source disp
->
-> instance Cmovbe Reg32 Ind where
->   cmovbe (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_be False dest source 0
-
-> class Cmovc a b where
->   cmovc :: a -> b -> CodeGen e s ()
-
-> instance Cmovc Reg32 Reg32 where
->   cmovc (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_c False dest source
->
-> instance Cmovc Reg32 Addr where
->   cmovc (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_c False dest source
->
-> instance Cmovc Reg32 (Disp, Reg32) where
->   cmovc (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_c False dest source disp
->
-> instance Cmovc Reg32 Ind where
->   cmovc (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_c False dest source 0
-
-> class Cmove a b where
->   cmove :: a -> b -> CodeGen e s ()
-
-> instance Cmove Reg32 Reg32 where
->   cmove (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_e False dest source
->
-> instance Cmove Reg32 Addr where
->   cmove (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_e False dest source
->
-> instance Cmove Reg32 (Disp, Reg32) where
->   cmove (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_e False dest source disp
->
-> instance Cmove Reg32 Ind where
->   cmove (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_e False dest source 0
-
-> class Cmovna a b where
->   cmovna :: a -> b -> CodeGen e s ()
-
-> instance Cmovna Reg32 Reg32 where
->   cmovna (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_na False dest source
->
-> instance Cmovna Reg32 Addr where
->   cmovna (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_na False dest source
->
-> instance Cmovna Reg32 (Disp, Reg32) where
->   cmovna (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_na False dest source disp
->
-> instance Cmovna Reg32 Ind where
->   cmovna (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_na False dest source 0
-
-> class Cmovnae a b where
->   cmovnae :: a -> b -> CodeGen e s ()
-
-> instance Cmovnae Reg32 Reg32 where
->   cmovnae (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_nae False dest source
->
-> instance Cmovnae Reg32 Addr where
->   cmovnae (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_nae False dest source
->
-> instance Cmovnae Reg32 (Disp, Reg32) where
->   cmovnae (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_nae False dest source disp
->
-> instance Cmovnae Reg32 Ind where
->   cmovnae (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_nae False dest source 0
-
-> class Cmovnb a b where
->   cmovnb :: a -> b -> CodeGen e s ()
-
-> instance Cmovnb Reg32 Reg32 where
->   cmovnb (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_nb False dest source
->
-> instance Cmovnb Reg32 Addr where
->   cmovnb (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_nb False dest source
->
-> instance Cmovnb Reg32 (Disp, Reg32) where
->   cmovnb (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_nb False dest source disp
->
-> instance Cmovnb Reg32 Ind where
->   cmovnb (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_nb False dest source 0
-
-> class Cmovnbe a b where
->   cmovnbe :: a -> b -> CodeGen e s ()
-
-> instance Cmovnbe Reg32 Reg32 where
->   cmovnbe (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_nbe False dest source
->
-> instance Cmovnbe Reg32 Addr where
->   cmovnbe (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_nbe False dest source
->
-> instance Cmovnbe Reg32 (Disp, Reg32) where
->   cmovnbe (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_nbe False dest source disp
->
-> instance Cmovnbe Reg32 Ind where
->   cmovnbe (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_nbe False dest source 0
-
-> class Cmovnc a b where
->   cmovnc :: a -> b -> CodeGen e s ()
-
-> instance Cmovnc Reg32 Reg32 where
->   cmovnc (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_nc False dest source
->
-> instance Cmovnc Reg32 Addr where
->   cmovnc (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_nc False dest source
->
-> instance Cmovnc Reg32 (Disp, Reg32) where
->   cmovnc (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_nc False dest source disp
->
-> instance Cmovnc Reg32 Ind where
->   cmovnc (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_nc False dest source 0
-
-> class Cmovne a b where
->   cmovne :: a -> b -> CodeGen e s ()
-
-> instance Cmovne Reg32 Reg32 where
->   cmovne (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_ne False dest source
->
-> instance Cmovne Reg32 Addr where
->   cmovne (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_ne False dest source
->
-> instance Cmovne Reg32 (Disp, Reg32) where
->   cmovne (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_ne False dest source disp
->
-> instance Cmovne Reg32 Ind where
->   cmovne (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_ne False dest source 0
-
-> class Cmovnp a b where
->   cmovnp :: a -> b -> CodeGen e s ()
-
-> instance Cmovnp Reg32 Reg32 where
->   cmovnp (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_np False dest source
->
-> instance Cmovnp Reg32 Addr where
->   cmovnp (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_np False dest source
->
-> instance Cmovnp Reg32 (Disp, Reg32) where
->   cmovnp (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_np False dest source disp
->
-> instance Cmovnp Reg32 Ind where
->   cmovnp (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_np False dest source 0
-
-> class Cmovnz a b where
->   cmovnz :: a -> b -> CodeGen e s ()
-
-> instance Cmovnz Reg32 Reg32 where
->   cmovnz (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_nz False dest source
->
-> instance Cmovnz Reg32 Addr where
->   cmovnz (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_nz False dest source
->
-> instance Cmovnz Reg32 (Disp, Reg32) where
->   cmovnz (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_nz False dest source disp
->
-> instance Cmovnz Reg32 Ind where
->   cmovnz (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_nz False dest source 0
-
-> class Cmovp a b where
->   cmovp :: a -> b -> CodeGen e s ()
-
-> instance Cmovp Reg32 Reg32 where
->   cmovp (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_p False dest source
->
-> instance Cmovp Reg32 Addr where
->   cmovp (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_p False dest source
->
-> instance Cmovp Reg32 (Disp, Reg32) where
->   cmovp (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_p False dest source disp
->
-> instance Cmovp Reg32 Ind where
->   cmovp (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_p False dest source 0
-
-> class Cmovpe a b where
->   cmovpe :: a -> b -> CodeGen e s ()
-
-> instance Cmovpe Reg32 Reg32 where
->   cmovpe (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_pe False dest source
->
-> instance Cmovpe Reg32 Addr where
->   cmovpe (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_pe False dest source
->
-> instance Cmovpe Reg32 (Disp, Reg32) where
->   cmovpe (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_pe False dest source disp
->
-> instance Cmovpe Reg32 Ind where
->   cmovpe (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_pe False dest source 0
-
-> class Cmovpo a b where
->   cmovpo :: a -> b -> CodeGen e s ()
-
-> instance Cmovpo Reg32 Reg32 where
->   cmovpo (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_po False dest source
->
-> instance Cmovpo Reg32 Addr where
->   cmovpo (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_po False dest source
->
-> instance Cmovpo Reg32 (Disp, Reg32) where
->   cmovpo (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_po False dest source disp
->
-> instance Cmovpo Reg32 Ind where
->   cmovpo (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_po False dest source 0
-
-> class Cmovz a b where
->   cmovz :: a -> b -> CodeGen e s ()
-
-> instance Cmovz Reg32 Reg32 where
->   cmovz (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_z False dest source
->
-> instance Cmovz Reg32 Addr where
->   cmovz (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_z False dest source
->
-> instance Cmovz Reg32 (Disp, Reg32) where
->   cmovz (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_z False dest source disp
->
-> instance Cmovz Reg32 Ind where
->   cmovz (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_z False dest source 0
-
-> class Cmovg a b where
->   cmovg :: a -> b -> CodeGen e s ()
-
-> instance Cmovg Reg32 Reg32 where
->   cmovg (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_gt True dest source
->
-> instance Cmovg Reg32 Addr where
->   cmovg (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_gt True dest source
->
-> instance Cmovg Reg32 (Disp, Reg32) where
->   cmovg (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_gt True dest source disp
->
-> instance Cmovg Reg32 Ind where
->   cmovg (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_gt True dest source 0
-
-> class Cmovge a b where
->   cmovge :: a -> b -> CodeGen e s ()
-
-> instance Cmovge Reg32 Reg32 where
->   cmovge (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_ge True dest source
->
-> instance Cmovge Reg32 Addr where
->   cmovge (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_ge True dest source
->
-> instance Cmovge Reg32 (Disp, Reg32) where
->   cmovge (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_ge True dest source disp
->
-> instance Cmovge Reg32 Ind where
->   cmovge (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_ge True dest source 0
-
-> class Cmovl a b where
->   cmovl :: a -> b -> CodeGen e s ()
-
-> instance Cmovl Reg32 Reg32 where
->   cmovl (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_lt True dest source
->
-> instance Cmovl Reg32 Addr where
->   cmovl (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_lt True dest source
->
-> instance Cmovl Reg32 (Disp, Reg32) where
->   cmovl (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_lt True dest source disp
->
-> instance Cmovl Reg32 Ind where
->   cmovl (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_lt True dest source 0
-
-> class Cmovle a b where
->   cmovle :: a -> b -> CodeGen e s ()
-
-> instance Cmovle Reg32 Reg32 where
->   cmovle (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_le True dest source
->
-> instance Cmovle Reg32 Addr where
->   cmovle (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_le True dest source
->
-> instance Cmovle Reg32 (Disp, Reg32) where
->   cmovle (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_le True dest source disp
->
-> instance Cmovle Reg32 Ind where
->   cmovle (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_le True dest source 0
-
-> class Cmovng a b where
->   cmovng :: a -> b -> CodeGen e s ()
-
-> instance Cmovng Reg32 Reg32 where
->   cmovng (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_le True dest source
->
-> instance Cmovng Reg32 Addr where
->   cmovng (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_le True dest source
->
-> instance Cmovng Reg32 (Disp, Reg32) where
->   cmovng (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_le True dest source disp
->
-> instance Cmovng Reg32 Ind where
->   cmovng (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_le True dest source 0
-
-> class Cmovnge a b where
->   cmovnge :: a -> b -> CodeGen e s ()
-
-> instance Cmovnge Reg32 Reg32 where
->   cmovnge (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_lt True dest source
->
-> instance Cmovnge Reg32 Addr where
->   cmovnge (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_lt True dest source
->
-> instance Cmovnge Reg32 (Disp, Reg32) where
->   cmovnge (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_lt True dest source disp
->
-> instance Cmovnge Reg32 Ind where
->   cmovnge (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_lt True dest source 0
-
-> class Cmovnl a b where
->   cmovnl :: a -> b -> CodeGen e s ()
-
-> instance Cmovnl Reg32 Reg32 where
->   cmovnl (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_ge True dest source
->
-> instance Cmovnl Reg32 Addr where
->   cmovnl (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_ge True dest source
->
-> instance Cmovnl Reg32 (Disp, Reg32) where
->   cmovnl (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_ge True dest source disp
->
-> instance Cmovnl Reg32 Ind where
->   cmovnl (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_ge True dest source 0
-
-> class Cmovnle a b where
->   cmovnle :: a -> b -> CodeGen e s ()
-
-> instance Cmovnle Reg32 Reg32 where
->   cmovnle (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_gt True dest source
->
-> instance Cmovnle Reg32 Addr where
->   cmovnle (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_gt True dest source
->
-> instance Cmovnle Reg32 (Disp, Reg32) where
->   cmovnle (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_gt True dest source disp
->
-> instance Cmovnle Reg32 Ind where
->   cmovnle (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_gt True dest source 0
-
-> class Cmovno a b where
->   cmovno :: a -> b -> CodeGen e s ()
-
-> instance Cmovno Reg32 Reg32 where
->   cmovno (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_no True dest source
->
-> instance Cmovno Reg32 Addr where
->   cmovno (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_no True dest source
->
-> instance Cmovno Reg32 (Disp, Reg32) where
->   cmovno (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_no True dest source disp
->
-> instance Cmovno Reg32 Ind where
->   cmovno (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_no True dest source 0
-
-> class Cmovns a b where
->   cmovns :: a -> b -> CodeGen e s ()
-
-> instance Cmovns Reg32 Reg32 where
->   cmovns (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_ns True dest source
->
-> instance Cmovns Reg32 Addr where
->   cmovns (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_ns True dest source
->
-> instance Cmovns Reg32 (Disp, Reg32) where
->   cmovns (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_ns True dest source disp
->
-> instance Cmovns Reg32 Ind where
->   cmovns (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_ns True dest source 0
-
-> class Cmovo a b where
->   cmovo :: a -> b -> CodeGen e s ()
-
-> instance Cmovo Reg32 Reg32 where
->   cmovo (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_o True dest source
->
-> instance Cmovo Reg32 Addr where
->   cmovo (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_o True dest source
->
-> instance Cmovo Reg32 (Disp, Reg32) where
->   cmovo (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_o True dest source disp
->
-> instance Cmovo Reg32 Ind where
->   cmovo (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_o True dest source 0
-
-> class Cmovs a b where
->   cmovs :: a -> b -> CodeGen e s ()
-
-> instance Cmovs Reg32 Reg32 where
->   cmovs (Reg32 dest) (Reg32 source) = x86_cmov_reg x86_cc_s True dest source
->
-> instance Cmovs Reg32 Addr where
->   cmovs (Reg32 dest) (Addr source) = x86_cmov_mem x86_cc_s True dest source
->
-> instance Cmovs Reg32 (Disp, Reg32) where
->   cmovs (Reg32 dest) (Disp disp, Reg32 source) = x86_cmov_membase x86_cc_s True dest source disp
->
-> instance Cmovs Reg32 Ind where
->   cmovs (Reg32 dest) (Ind (Reg32 source)) = x86_cmov_membase x86_cc_s True dest source 0
-
-
-release stack frame
-
-> leave :: CodeGen e s ()
-> leave = x86_leave
-
-
-store ah into flags
-
-> sahf :: CodeGen e s ()
-> sahf = x86_sahf
diff --git a/Harpy/X86CGCombinators.hs b/Harpy/X86CGCombinators.hs
--- a/Harpy/X86CGCombinators.hs
+++ b/Harpy/X86CGCombinators.hs
@@ -19,6 +19,8 @@
   -- * Types
   UserState(..),
   UserEnv(..),
+  emptyUserEnv,
+  emptyUserState,
   CtrlDest(..),
   DataDest(..),
   -- * Combinators
@@ -26,24 +28,26 @@
   doWhile,
   continue,
   continueBranch,
+  saveRegs,
+  function,
   withDataDest,
   withCtrlDest,
   withDest,
-  function,
-  withRegister
-  ) where
+   ) where
 
 import Text.PrettyPrint.HughesPJ
 
 import Foreign
+import Data.Word
 
 import Harpy.CodeGenMonad
 import Harpy.X86CodeGen
+import Harpy.X86Assembler
 
 -- | Destination for a calculated value.
-data DataDest = RegDest Word8            -- ^ Store into specific register
+data DataDest = RegDest Reg32            -- ^ Store into specific register
               | StackDest                -- ^ Push onto stack
-              | MemBaseDest Word8 Word32 -- ^ Store at memory address
+              | MemBaseDest Reg32 Word32 -- ^ Store at memory address
               | Ignore                   -- ^ Throw result away.
 
 -- | Destination for control transfers
@@ -54,18 +58,19 @@
                                          -- depending on outcome of test
 
 -- | User state is used to maintain bitmask of registers currently in use.
-data UserState = UserState { usedRegs :: Int}
+data UserState = UserState {}
 
                              
 -- | User environment stores code generators for accessing specific
 -- variables as well as the current data and control destinations
-data UserEnv = UserEnv { bindings :: [(String, 
-                                       CodeGen UserEnv UserState ())],
+data UserEnv = UserEnv { bindings :: [(String, CodeGen UserEnv UserState ())],
                          dataDest :: DataDest,
                          ctrlDest :: CtrlDest }
 
-emptyUserState = UserState{usedRegs = 0}
+emptyUserState :: UserState
+emptyUserState = UserState{}
 
+emptyUserEnv :: UserEnv
 emptyUserEnv = UserEnv{bindings = [], dataDest = Ignore,
                        ctrlDest = Return}
 
@@ -77,35 +82,48 @@
     do env <- getEnv 
        elseLabel <- newLabel
        endLabel <- newLabel
-       withDest Ignore (Branch FallThrough (Goto elseLabel)) 
-         (condCg)
+       withDest Ignore (Branch FallThrough (Goto elseLabel)) condCg
        withCtrlDest (case ctrlDest env of 
                        FallThrough -> Goto endLabel
                        _ -> ctrlDest env)
                     (thenCg >> continue)
-       defineLabel elseLabel
-       elseCg >> continue
-       defineLabel endLabel
+       elseLabel @@ (elseCg >> continue)
+       endLabel @@ return ()
 
 doWhile :: CodeGen UserEnv s r -> CodeGen UserEnv s a -> CodeGen UserEnv s ()
 doWhile condCg bodyCg =
     do topLabel <- newLabel
        testLabel <- newLabel
-       emitFixup testLabel 1 Fixup8
-       x86_jump8 0
-       defineLabel topLabel
-       withCtrlDest FallThrough (bodyCg >> continue)
-       defineLabel testLabel
-       withDest Ignore (Branch (Goto topLabel) FallThrough) condCg 
+       jmp testLabel
+       topLabel @@ withCtrlDest FallThrough (bodyCg >> continue)
+       testLabel @@ withDest Ignore (Branch (Goto topLabel) FallThrough) 
+                        condCg 
        continue
 
+doFor :: (Mov a Word32, Add a Word32, Cmp a Word32) => a -> Word32 -> Word32 -> Int32 ->
+         CodeGen UserEnv s r ->
+         CodeGen UserEnv s ()
+doFor loc from to step body =
+    do topLabel <- newLabel
+       testLabel <- newLabel
+       mov loc from
+       jmp testLabel
+       topLabel @@ withCtrlDest FallThrough  (body >> continue)
+       testLabel @@ cmp loc to
+       add loc (fromIntegral step :: Word32)
+       if step < 0
+          then jge topLabel
+          else jle topLabel
+       continue
+       
+
 continue :: CodeGen UserEnv s ()
 continue =
     do env <- getEnv
        cont (ctrlDest env)
   where
   cont FallThrough = return ()
-  cont (Goto l) = emitFixup l 1 Fixup32 >> x86_jump32 0
+  cont (Goto l) = jmp l
   cont (Branch _ _) = error "Branch in continue"
   cont Return = x86_epilog 0
 
@@ -117,23 +135,23 @@
        cont cc isSigned c1 c2
   where
   cont cc isSigned (Goto l1) (Goto l2) =
-    do emitFixup l1 1 Fixup32
-       x86_branch32 cc 0 isSigned
-       emitFixup l2 1 Fixup32
+    do x86_branch32 cc 0 isSigned
+       emitFixup l1 (-4) Fixup32
        x86_branch32 (negateCC cc) 0 isSigned
+       emitFixup l2 (-4) Fixup32
   cont cc isSigned (Goto l1) FallThrough =
-    do emitFixup l1 1 Fixup32
-       x86_branch32 cc 0 isSigned
+    do x86_branch32 cc 0 isSigned
+       emitFixup l1 (-4) Fixup32
   cont cc isSigned FallThrough (Goto l2) =
-    do emitFixup l2 1 Fixup32
-       x86_branch32 (negateCC cc) 0 isSigned
+    do x86_branch32 (negateCC cc) 0 isSigned
+       emitFixup l2 (-4) Fixup32
   cont cc isSigned (Goto l1) Return =
-    do emitFixup l1 1 Fixup32
-       x86_branch32 cc 0 isSigned
+    do x86_branch32 cc 0 isSigned
+       emitFixup l1 (-4) Fixup32
        withCtrlDest Return continue
   cont cc isSigned Return (Goto l2) =
-    do emitFixup l2 1 Fixup32
-       x86_branch32 (negateCC cc) 0 isSigned
+    do x86_branch32 (negateCC cc) 0 isSigned
+       emitFixup l2 (-4) Fixup32
        withCtrlDest Return continue
   cont _ _ _ _ = error "unhandled case in continueBranch"
 
@@ -143,12 +161,12 @@
   where
   reg' sreg (RegDest r) = 
     do if sreg /= r 
-          then x86_mov_reg_reg r sreg x86_dword_size 
+          then mov r sreg
           else return ()
   reg' sreg (StackDest) = 
-    do x86_push_reg sreg
+    do push sreg
   reg' sreg (MemBaseDest r offset) = 
-    do x86_mov_membase_reg r offset sreg x86_dword_size
+    do mov (Disp offset, r) sreg
   reg' sreg Ignore = return () 
 
 membase reg ofs =
@@ -156,12 +174,14 @@
        membase' reg ofs (dataDest env)
   where
   membase' reg ofs (RegDest r) = 
-    do x86_mov_reg_membase r reg ofs x86_dword_size
+    do mov r (Disp ofs, reg)
   membase' reg ofs (StackDest) = 
-    do x86_push_membase reg ofs
+    do push (Disp ofs, reg)
   membase' reg ofs (MemBaseDest r offset) = 
-    do x86_mov_reg_membase x86_edi reg ofs x86_dword_size
-       x86_mov_membase_reg r offset x86_edi x86_dword_size
+    do push edi
+       mov edi (Disp ofs, reg)
+       mov (Disp offset, r) edi
+       pop edi
   membase' reg ofs Ignore = return () 
 
 global ofs =
@@ -169,12 +189,14 @@
        global' ofs (dataDest env)
   where
   global' ofs (RegDest r) = 
-    do x86_mov_reg_mem r ofs x86_dword_size
+    do mov r (Addr ofs)
   global' ofs (StackDest) = 
-    do x86_push_mem ofs
+    do push (Addr ofs)
   global' ofs (MemBaseDest r offset) = 
-    do x86_mov_reg_mem x86_edi ofs x86_dword_size
-       x86_mov_membase_reg r offset x86_edi x86_dword_size
+    do push edi
+       mov edi (Addr ofs)
+       mov (Disp offset, r) edi
+       pop edi
   global' ofs Ignore = return ()
 
 immediate value =
@@ -182,38 +204,30 @@
        immediate' value (dataDest env)
   where
   immediate' value (RegDest r) = 
-    do x86_mov_reg_imm r value
+    do mov r value
   immediate' value (StackDest) = 
     do x86_push_imm value
   immediate' value (MemBaseDest r offset) = 
-    do x86_mov_reg_imm x86_edi value 
-       x86_mov_membase_reg r offset x86_edi x86_dword_size
+    do push edi
+       mov edi value 
+       mov (Disp offset, r) edi
+       pop edi
   immediate' ofs Ignore = return ()
 
 -- | Save a number of registers on the stack, perform the given code
 -- generation, and restore the registers.
-saveRegs :: (Bits a) =>
-	    a -> CodeGen UserEnv s r -> CodeGen UserEnv s ()
-saveRegs reg_mask cg =
-    do gen_push 0 1
+saveRegs :: [Reg32] -> CodeGen UserEnv s r -> CodeGen UserEnv s ()
+saveRegs [] cg = cg >> return ()
+saveRegs regs cg =
+    do gen_push regs
        withCtrlDest FallThrough cg
-       gen_pop x86_edi (1 `shiftL` (fromIntegral x86_edi))
+       gen_pop regs
        continue
   where
-  gen_push i m =
-     if i <= x86_edi
-        then do if (reg_mask .&. m) /= 0
-                   then x86_push_reg i
-                   else return ()
-                gen_push (i + 1) (m `shiftL` 1)
-        else return ()
-  gen_pop i m =
-    if m /= 0
-       then do if (reg_mask .&. m) /= 0
-                  then x86_pop_reg i
-                  else return ()
-               gen_pop (i - 1) (m `shiftR` 1)
-       else return ()
+  gen_push [] = return ()
+  gen_push (r:regs) = push r >> gen_push regs
+  gen_pop [] = return ()
+  gen_pop (r:regs) = gen_pop regs >> pop r
 
 -- | Perform the code generation associated with the variable given.
 loadVar :: String -> CodeGen UserEnv UserState ()
@@ -223,18 +237,6 @@
          Just cg -> cg
          Nothing -> failCodeGen (text ("undefined variable: " ++ name))
 
--- | Find a register not recorded in the given bit mask.
-findReg :: (Bits a) => a -> Word8
-findReg reg_mask = findR 0 1
-  where
-   findR i m =
-     if i <= x86_edi
-        then if (reg_mask .&. m) == 0
-                   then i
-                   else findR (i + 1) (m `shiftL` 1)
-        else error "no register left for allocation"
-    
-
 -- | Set the data destinations to the given values while
 -- running the code generator.
 withDataDest :: DataDest -> CodeGen UserEnv s r -> CodeGen UserEnv s r
@@ -261,16 +263,4 @@
 function :: CodeGen UserEnv s r -> CodeGen UserEnv s r
 function cg =
     do x86_prolog 0 0
-       withDataDest (RegDest x86_eax) $ withCtrlDest Return $ cg
-
--- | Apply the given cg to a register, which is reserved while the
--- generator is running.
-withRegister :: (Word8 -> CodeGen e UserState t) -> CodeGen e UserState ()
-withRegister cg =
-    do state <- getState
-       let used = usedRegs state
-       let reg = findReg used
-       setState (state{usedRegs = used .|. (1 `shiftL` fromIntegral reg)})
-       cg reg
-       state <- getState
-       setState (state{usedRegs = used})
+       withDest (RegDest eax) Return $ cg
diff --git a/Harpy/X86CodeGen.hs b/Harpy/X86CodeGen.hs
--- a/Harpy/X86CodeGen.hs
+++ b/Harpy/X86CodeGen.hs
@@ -45,38 +45,68 @@
 --------------------------------------------------------------------------
 
 module Harpy.X86CodeGen(
+    -- * Types
+    X86_SSE_PFX,
     -- * Constants
     -- ** Machine characteristics
+    -- |  Sizes of various machine data types in bytes.
     x86_dword_size, 
     x86_qword_size, 
+    x86_max_instruction_bytes,
     -- ** Register numbers
     -- | x86 general-purpose register numbers
     x86_eax, x86_ecx, x86_edx, x86_ebx, x86_esp, x86_ebp, x86_esi, x86_edi,
     x86_nobasereg,
     -- ** Register masks and predicates
+    -- | Bitvector masks for general-purpose registers
     x86_eax_mask, x86_ecx_mask, x86_edx_mask, x86_ebx_mask,
-    x86_esi_mask, x86_edi_mask, 
+    x86_esi_mask, x86_edi_mask, x86_ebp_mask,
     x86_callee_regs, x86_caller_regs, x86_byte_regs,
     -- ** ALU operations
+    -- | Opcodes for ALU instructions
     x86_add, x86_or, x86_adc, x86_sbb, x86_and, x86_sub, x86_xor, x86_cmp,
     -- ** Shift operations
+    -- | Opcodes for shift instructions
     x86_rol, x86_ror, x86_rcl, x86_rcr, x86_shl,
-    x86_shr, x86_sar,
+    x86_shr, x86_sar, x86_shld, x86_shlr,
+    -- ** FP operations
+    -- | Opcodes for floating-point instructions
+    x86_fadd, x86_fmul, x86_fcom, x86_fcomp, x86_fsub, x86_fsubr,
+    x86_fdiv, x86_fdivr,
+    -- ** FP conditions and control codes
+    -- | FP status word codes
+    x86_fp_c0, x86_fp_c1, x86_fp_c2, x86_fp_c3, x86_fp_cc_mask,
+    -- | FP control word codes
+    x86_fpcw_invopex_mask, x86_fpcw_denopex_mask, x86_fpcw_zerodiv_mask, 
+    x86_fpcw_ovfex_mask, x86_fpcw_undfex_mask, x86_fpcw_precex_mask, 
+    x86_fpcw_precc_mask, x86_fpcw_roundc_mask,
+    x86_fpcw_prec_single, x86_fpcw_prec_double, 
+    x86_fpcw_prec_extended,
+    x86_fpcw_round_nearest, x86_fpcw_round_down, x86_fpcw_round_up,
+    x86_fpcw_round_tozero,
     -- ** Condition codes
+    -- | Integer conditions codes
     x86_cc_eq, x86_cc_e, x86_cc_z,
     x86_cc_ne, x86_cc_nz,
     x86_cc_lt, x86_cc_b, x86_cc_c, x86_cc_nae, x86_cc_le, x86_cc_be, 
     x86_cc_na, x86_cc_gt, x86_cc_a, x86_cc_nbe, x86_cc_ge, x86_cc_ae, 
     x86_cc_nb, x86_cc_nc, x86_cc_lz, x86_cc_s, x86_cc_gez, x86_cc_ns, 
     x86_cc_p, x86_cc_np, x86_cc_pe, x86_cc_po, x86_cc_o, x86_cc_no,
+    -- ** Instruction prefix codes
+    x86_lock_prefix, x86_repnz_prefix, x86_repz_prefix, x86_rep_prefix,
+    x86_cs_prefix, x86_ss_prefix, x86_ds_prefix, x86_es_prefix,
+    x86_fs_prefix, x86_gs_prefix, x86_unlikely_prefix,
+    x86_likely_prefix, x86_operand_prefix, x86_address_prefix,
     -- * Functions
     -- ** Utility functions
     x86_is_scratch, x86_is_callee,
     -- ** Code emission
-    x86_imm_emit32, x86_imm_emit16, x86_imm_emit8, 
+    -- | These functions are used to emit parts of instructions, such
+    -- as constants or operand descriptions.
+    x86_imm_emit16, x86_imm_emit8, x86_imm_emit32, 
     x86_membase_emit, x86_alu_reg_imm,
     -- ** Call instructions
-    x86_call_hs, x86_call_membase, x86_call_mem, x86_call_reg, 
+    x86_call_hs, x86_call_membase, x86_call_mem, x86_call_reg, x86_call_code,
     x86_call_imm,
     -- ** Function prologue and epilogue
     x86_prolog, x86_epilog, x86_enter, x86_leave,
@@ -130,16 +160,42 @@
     -- ** Conversion 
     x86_cdq,x86_widen_memindex, x86_widen_membase, x86_widen_mem, 
     x86_widen_reg,
+    -- ** Floating point
+    x86_fp_op_mem, x86_fp_op_membase, x86_fp_op, x86_fp_op_reg,
+    x86_fp_int_op_membase, x86_fstp, x86_fcompp, x86_fucompp,
+    x86_fnstsw, x86_fnstcw, x86_fnstcw_membase,
+    x86_fldcw, x86_fldcw_membase, x86_fchs,
+    x86_frem, x86_fxch, x86_fcomi, x86_fcomip, x86_fucomi, x86_fucomip,
+    x86_fld, x86_fld_membase, x86_fld80_mem, x86_fld80_membase,
+    x86_fld_reg, x86_fldz, x86_fld1, x86_fldpi,
+    x86_fst, x86_fst_membase, x86_fst80_mem, x86_fst80_membase,
+    x86_fist_pop, x86_fist_pop_membase, x86_fstsw, 
+    x86_fist_membase, x86_fild, x86_fild_membase,
+    x86_fsin, x86_fcos, x86_fabs, x86_ftst, x86_fxam, x86_fpatan, 
+    x86_fprem, x86_fprem1, x86_frndint, x86_fsqrt, x86_fptan,
+    -- ** SSE instructions
+    x86_sse_ps, x86_sse_pd, x86_sse_ss, x86_sse_sd,
+    x86_add_sse_reg_reg, x86_add_sse_reg_mem, x86_add_sse_reg_membase,
+    x86_sub_sse_reg_reg, x86_sub_sse_reg_mem, x86_sub_sse_reg_membase,
+    x86_mul_sse_reg_reg, x86_mul_sse_reg_mem, x86_mul_sse_reg_membase,
+    x86_div_sse_reg_reg, x86_div_sse_reg_mem, x86_div_sse_reg_membase,
+    x86_max_sse_reg_reg, x86_max_sse_reg_mem, x86_max_sse_reg_membase,
+    x86_min_sse_reg_reg, x86_min_sse_reg_mem, x86_min_sse_reg_membase,
+    x86_sqrt_sse_reg_reg, x86_sqrt_sse_reg_mem, x86_sqrt_sse_reg_membase,
+    x86_mov_sse_reg_reg, x86_mov_sse_reg_mem, x86_mov_sse_reg_membase, x86_mov_sse_mem_reg ,x86_mov_sse_membase_reg,
+    x86_ucomisd_reg_reg, x86_ucomisd_reg_mem, x86_ucomisd_reg_membase,
+    x86_ucomiss_reg_reg, x86_ucomiss_reg_mem, x86_ucomiss_reg_membase,
+    x86_comisd_reg_reg, x86_comisd_reg_mem, x86_comisd_reg_membase,
+    x86_comiss_reg_reg, x86_comiss_reg_mem, x86_comiss_reg_membase,
     -- ** Miscellaneous
     x86_sahf, x86_wait, x86_nop, x86_breakpoint, x86_rdtsc, x86_cld,
+    x86_prefix, x86_padding,
     -- ** Other utilities
     negateCC
                        ) where
 
 import qualified Text.PrettyPrint.HughesPJ as PP
 
-import Debug.Trace
-
 import Data.Word
 import Data.Bits
 
@@ -147,8 +203,10 @@
 
 import Harpy.CodeGenMonad
 
+-- | Maximal length of an x86 instruction in bytes.
+x86_max_instruction_bytes :: Int
+x86_max_instruction_bytes = 16   -- According to Intel manual.
 
--- |  Sizes of various machine data types in bytes.
 x86_dword_size, x86_qword_size :: Int
 
 x86_dword_size = 4                    -- Number of bytes in doubleword
@@ -165,7 +223,6 @@
 x86_esi = 6
 x86_edi = 7
 
--- | Opcodes for ALU instructions
 x86_cmp, x86_or, x86_adc, x86_sbb, x86_and, x86_sub, x86_xor, 
   x86_add :: Word8
 x86_add = 0
@@ -177,7 +234,6 @@
 x86_xor = 6
 x86_cmp = 7
 
--- | Opcodes for shift instructions
 x86_sar, x86_shld, x86_shlr, x86_rol, x86_ror, x86_rcl, x86_rcr,
   x86_shl, x86_shr :: Word8
 
@@ -191,8 +247,6 @@
 x86_shr  = 5
 x86_sar  = 7
 
--- | Opcodes for floating-point instructions
-
 x86_fadd, x86_fmul, x86_fcom, x86_fcomp, x86_fsub, x86_fsubr :: Word8
 x86_fdiv, x86_fdivr :: Word8
 
@@ -205,7 +259,6 @@
 x86_fdiv  = 6
 x86_fdivr = 7
 
--- | Integer conditions codes
 x86_cc_no, x86_cc_eq, x86_cc_e, x86_cc_z, x86_cc_ne, x86_cc_nz, x86_cc_lt :: Int
 x86_cc_b, x86_cc_c, x86_cc_nae, x86_cc_le, x86_cc_be, x86_cc_na :: Int
 x86_cc_gt :: Int
@@ -300,6 +353,7 @@
 x86_address_prefix = 0x67
 
 -- | Mapping from condition code to opcode (unsigned)
+x86_cc_unsigned_map :: [Word8]
 x86_cc_unsigned_map = [
        0x74, -- eq  
        0x75, -- ne  
@@ -316,6 +370,7 @@
  ]
 
 -- | Mapping from condition code to opcode (signed)
+x86_cc_signed_map :: [Word8]
 x86_cc_signed_map = [
       0x74, -- eq  
       0x75, -- ne  
@@ -332,6 +387,7 @@
  ]
 
 -- | Mapping from condition code to negated condition code.
+x86_cc_negate :: [(Int, Int)]
 x86_cc_negate = [
        (x86_cc_eq, x86_cc_ne), -- eq  
        (x86_cc_ne, x86_cc_eq), -- ne  
@@ -359,7 +415,6 @@
 x86_nobasereg :: Word8
 x86_nobasereg = (-1)
 
--- | Bitvector masks for general-purpose registers
 x86_edi_mask, x86_esi_mask, x86_ebx_mask, x86_ebp_mask,
     x86_eax_mask, x86_ecx_mask, x86_edx_mask:: Int
 x86_esi_mask = (1 `shiftL` (fromIntegral x86_esi))
@@ -408,10 +463,12 @@
 -- useful building blocks
 
 
-x86_modrm_mod modrm = ((modrm) `shiftR` 6)
-x86_modrm_reg modrm = (((modrm) `shiftR` 3) .&. 0x7)
-x86_modrm_rm modrm = ((modrm) .&. 0x7)
+--x86_modrm_mod modrm = ((modrm) `shiftR` 6)
+--x86_modrm_reg :: Bits a => a -> a
+--x86_modrm_reg modrm = (((modrm) `shiftR` 3) .&. 0x7)
+--x86_modrm_rm modrm = ((modrm) .&. 0x7)
 
+x86_address_byte :: Word8 -> Word8 -> Word8 -> CodeGen e s ()
 x86_address_byte m o r = emit8 ((((m) .&. 0x03) `shiftL` 6) .|.
                                (((o) .&. 0x07) `shiftL` 3) .|. 
                                 (((r) .&. 0x07)))
@@ -420,8 +477,9 @@
 x86_imm_emit32 :: Word32 -> CodeGen e s ()
 x86_imm_emit32 imm = emit32 imm
 
--- | Emit a 32-bit constant to the instruction stream at the given offset.
-x86_imm_emit32_at pos imm = emit32At pos imm
+-- -- | Emit a 32-bit constant to the instruction stream at the given offset.
+-- x86_imm_emit32_at :: Int -> Word32 -> CodeGen e s ()
+-- x86_imm_emit32_at pos imm = emit32At pos imm
 
 -- | Emit a 16-bit constant to the instruction stream.
 x86_imm_emit16 :: Word16 -> CodeGen e s ()
@@ -436,16 +494,21 @@
 x86_imm_emit8 imm = 
   emit8 (imm .&. 0xff)
 
--- | Emit a 8-bit constant to the instruction stream at the given offset.
-x86_imm_emit8_at pos imm = 
-  emit8At pos (imm .&. 0xff)
+-- -- | Emit a 8-bit constant to the instruction stream at the given offset.
+-- x86_imm_emit8_at :: Int -> Word8 -> CodeGen e s ()
+-- x86_imm_emit8_at pos imm = emit8At pos (imm .&. 0xff)
 
 -- | Return true if the given value is a signed 8-bit constant.
+x86_is_imm8 :: Integral a => a -> Bool
 x86_is_imm8 imm =  (((fromIntegral imm :: Integer) >= -128) && ((fromIntegral imm :: Integer) <= 127))
-x86_is_imm16 imm = (((fromIntegral imm :: Integer) >= -(1 `shiftL` 16)) && 
-                              ((fromIntegral imm :: Integer) <= ((1 `shiftL` 16)-1)))
+-- x86_is_imm16 :: Integral a => a -> Bool
+-- x86_is_imm16 imm = (((fromIntegral imm :: Integer) >= -(1 `shiftL` 16)) && 
+--                               ((fromIntegral imm :: Integer) <= ((1 `shiftL` 16)-1)))
 
+x86_reg_emit :: Word8 -> Word8 -> CodeGen e s ()
 x86_reg_emit r regno = x86_address_byte 3 r regno
+
+x86_reg8_emit :: Word8 -> Word8 -> Bool -> Bool -> CodeGen e s ()
 x86_reg8_emit r regno is_rh is_rnoh = 
   x86_address_byte 3 (if is_rh then (r .|. 4) else r) 
                      (if is_rnoh then regno .|. 4 else regno)
@@ -475,32 +538,34 @@
                                x86_imm_emit32 (fromIntegral disp)
        else do if (disp == 0 && (toInteger basereg) /= (toInteger x86_ebp))
                   then x86_address_byte 0 r basereg
-                  else if x86_is_imm8 (fromIntegral disp)
+                  else if x86_is_imm8 (fromIntegral disp :: Word32)
                           then do x86_address_byte 1 r basereg
                                   x86_imm_emit8 (fromIntegral disp)
                           else do x86_address_byte 2 r basereg
                                   x86_imm_emit32 (fromIntegral disp)
 
-x86_memindex_emit r basereg disp indexreg shift =
+x86_memindex_emit :: Word8 -> Word8 -> Word32 -> Word8 -> Word8 -> CodeGen e s ()
+x86_memindex_emit r basereg disp indexreg shft =
     if (basereg == x86_nobasereg)
        then do x86_address_byte 0 r 4
-               x86_address_byte shift indexreg 5
+               x86_address_byte shft indexreg 5
                x86_imm_emit32 disp
        else if ((disp) == 0 && (basereg) /= x86_ebp)
                then do x86_address_byte 0 r 4
-                       x86_address_byte shift indexreg (fromIntegral basereg)
+                       x86_address_byte shft indexreg (fromIntegral basereg)
                 else if x86_is_imm8 disp
                         then do x86_address_byte 1 r 4
-                                x86_address_byte shift indexreg 
+                                x86_address_byte shft indexreg 
                                              (fromIntegral basereg)
                                 x86_imm_emit8 (fromIntegral disp)
                         else do x86_address_byte 2 r 4
-                                x86_address_byte shift indexreg 5
+                                x86_address_byte shft indexreg 5
                                 x86_imm_emit32 disp
 
+{-
 x86_jmp_ofs_size ins =
   do instr <- peek8At ins
-     case trace (show instr) instr of
+     case instr of
        0xe8 -> return 1
        0xe9 -> return 1
        0x0f ->
@@ -509,6 +574,7 @@
                then failCodeGen (PP.text "Wrong Opcode")
                else return 1
        _ -> return 0
+-}
 
 -- target is the position in the code where to jump to:
 
@@ -527,6 +593,7 @@
 -- the instruction is inspected for validity and the correct displacement
 -- is inserted.
 
+{-
 x86_patch ins target =
     let pos = ins + 1
     in do size <- x86_jmp_ofs_size ins
@@ -537,6 +604,7 @@
              else if (x86_is_imm8 (disp - 1)) 
                      then x86_imm_emit8_at pos (fromIntegral (disp - 1))
                      else failCodeGen (PP.text "Wrong offset")
+-}
 
 x86_breakpoint, x86_cld, x86_stosb, x86_stosl, x86_stosd, x86_movsb, 
  x86_movsl, x86_movsd :: CodeGen s e ()
@@ -555,13 +623,20 @@
 x86_rdtsc :: CodeGen s e ()
 x86_rdtsc = emit8 0x0f >> emit8 0x31
 
+x86_cmpxchg_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
 x86_cmpxchg_reg_reg dreg reg = 
     emit8 0x0f >> emit8 0xb1 >> x86_reg_emit reg dreg
+
+x86_cmpxchg_mem_reg :: Word32 -> Word8 -> CodeGen e s ()
 x86_cmpxchg_mem_reg mem reg = emit8 0x0f >> emit8 0xb1 >> x86_mem_emit reg mem
+
+x86_cmpxchg_membase_reg :: Word8 -> Word32 -> Word8 -> CodeGen e s ()
 x86_cmpxchg_membase_reg basereg disp reg =
     emit8 0x0f >> emit8 0xb1 >> x86_membase_emit reg basereg disp
 
+x86_xchg :: Num a => a -> CodeGen e s ()
 x86_xchg size = if size == 1 then emit8 0x86 else emit8 0x87
+
 x86_xchg_reg_reg dreg reg size =
     do x86_xchg size ; x86_reg_emit reg dreg
 x86_xchg_mem_reg mem reg size =
@@ -569,8 +644,8 @@
 x86_xchg_membase_reg basereg disp reg size =
     do x86_xchg size ; x86_membase_emit reg basereg disp
 
-x86_xadd size = 
-    do emit8 0x0f ; if size == 1 then emit8 0xc0 else emit8 0xc1
+x86_xadd :: Num a => a -> CodeGen e s ()
+x86_xadd size = do emit8 0x0f ; if size == 1 then emit8 0xc0 else emit8 0xc1
 x86_xadd_reg_reg dreg reg size = x86_xadd size >> x86_reg_emit reg dreg
 x86_xadd_mem_reg mem reg size = x86_xadd size >> x86_mem_emit reg mem
 x86_xadd_membase_reg basereg disp reg size =
@@ -760,6 +835,7 @@
     do emit8 0xf7
        x86_membase_emit (6 + (if is_signed then 1 else 0)) basereg disp
 
+x86_mov1 :: Num t => t -> CodeGen e s ()
 x86_mov1 size =
     case size of
          1 -> emit8 0x88
@@ -767,6 +843,7 @@
          4 -> emit8 0x89
          _ -> failCodeGen (PP.text "invalid operand size")
        
+x86_mov2 :: Num t => t -> CodeGen e s ()
 x86_mov2 size =
     case size of
          1 -> emit8 0x8a
@@ -782,8 +859,8 @@
     do x86_mov2 size ; x86_regp_emit reg regp
 x86_mov_membase_reg basereg disp reg size =   
     do x86_mov1 size ; x86_membase_emit reg basereg disp      
-x86_mov_memindex_reg basereg disp indexreg shift reg size =   
-    do x86_mov1 size ; x86_memindex_emit reg basereg disp indexreg shift
+x86_mov_memindex_reg basereg disp indexreg shft reg size =   
+    do x86_mov1 size ; x86_memindex_emit reg basereg disp indexreg shft
 x86_mov_reg_reg dreg reg size =       
     do x86_mov2 size
        x86_reg_emit dreg reg  
@@ -793,15 +870,11 @@
 x86_mov_reg_membase reg basereg disp size =
     do x86_mov2 size
        x86_membase_emit reg basereg disp      
-x86_mov_reg_memindex reg basereg disp 4 shift size =
+x86_mov_reg_memindex _ _ _ 4 _ _ =
     failCodeGen $ PP.text "x86_mov_reg_memindex: cannot use (E)SP as index register"
-x86_mov_reg_memindex reg basereg disp indexreg shift size =   
+x86_mov_reg_memindex reg basereg disp indexreg shft size =   
     do x86_mov2 size
-       x86_memindex_emit reg basereg disp indexreg  shift     
-
--- Note: x86_clear_reg () changes the condition code!
-
-x86_clear_reg reg = x86_alu_reg_reg x86_xor reg reg
+       x86_memindex_emit reg basereg disp indexreg  shft
 
 x86_mov_reg_imm reg imm =     
     emit8 (0xb8 + reg) >> x86_imm_emit32 imm  
@@ -832,28 +905,34 @@
                        x86_membase_emit 0 basereg disp        
                        x86_imm_emit32 imm     
 
-x86_mov_memindex_imm basereg disp indexreg shift imm size =   
+x86_mov_memindex_imm basereg disp indexreg shft imm size =   
     if size == 1
     then do emit8 0xc6        
-            x86_memindex_emit 0 basereg disp indexreg  shift  
+            x86_memindex_emit 0 basereg disp indexreg  shft  
             x86_imm_emit8 (fromIntegral imm)  
     else if size == 2
          then do emit8 0x66   
                  emit8 0xc7   
-                 x86_memindex_emit 0 basereg disp indexreg  shift     
+                 x86_memindex_emit 0 basereg disp indexreg  shft     
                  x86_imm_emit16 (fromIntegral imm)    
          else do emit8 0xc7   
-                 x86_memindex_emit 0 basereg disp indexreg  shift     
+                 x86_memindex_emit 0 basereg disp indexreg  shft     
                  x86_imm_emit32 imm   
 
 -- LEA: Load Effective Address
 
+x86_lea_mem :: Word8 -> Word32 -> CodeGen e s ()
 x86_lea_mem reg mem = emit8 0x8d >> x86_mem_emit reg mem      
+
+x86_lea_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
 x86_lea_membase reg basereg disp =    
     emit8 0x8d >> x86_membase_emit reg basereg disp   
-x86_lea_memindex reg basereg disp indexreg shift =
-    emit8 0x8d >> x86_memindex_emit reg basereg disp indexreg shift   
 
+x86_lea_memindex :: Word8 -> Word8 -> Word32 -> Word8 -> Word8 -> CodeGen e s ()
+x86_lea_memindex reg basereg disp indexreg shft =
+    emit8 0x8d >> x86_memindex_emit reg basereg disp indexreg shft   
+
+x86_widen_reg :: Word8 -> Word8 -> Bool -> Bool -> CodeGen e s () 
 x86_widen_reg dreg reg is_signed is_half =
     if is_half || x86_is_byte_reg reg
     then do let op = 0xb6 + (if is_signed then 0x08 else 0) +
@@ -862,42 +941,52 @@
             emit8 op
             x86_reg_emit dreg reg
     else failCodeGen (PP.text "widen: need byte register or is_half=True")
+
+x86_widen_mem :: Word8 -> Word32 -> Bool -> Bool -> CodeGen e s ()
 x86_widen_mem dreg mem is_signed is_half =
     do let op = 0xb6 + (if is_signed then 0x08 else 0) +
                 (if is_half then 0x1 else 0)
        emit8 0x0f
        emit8 op
        x86_mem_emit dreg mem  
+
+x86_widen_membase :: Word8 -> Word8 -> Word32 -> Bool -> Bool -> CodeGen e s ()
 x86_widen_membase dreg basereg disp is_signed is_half =       
     do let op = 0xb6 + (if is_signed then 0x08 else 0) +
                 (if is_half then 0x1 else 0)
        emit8 0x0f
        emit8 op
        x86_membase_emit dreg basereg disp     
-x86_widen_memindex dreg basereg disp indexreg shift is_signed is_half =
+
+x86_widen_memindex :: Word8 -> Word8 -> Word32 -> Word8 -> Word8 -> Bool -> Bool -> CodeGen e s ()
+x86_widen_memindex dreg basereg disp indexreg shft is_signed is_half =
     do let op = 0xb6 + (if is_signed then 0x08 else 0) +
                 (if is_half then 0x1 else 0)
        emit8 0x0f
        emit8 op
-       x86_memindex_emit dreg basereg disp indexreg shift     
+       x86_memindex_emit dreg basereg disp indexreg shft     
 
 x86_cdq, x86_wait :: CodeGen s e ()
 x86_cdq  = emit8 0x99
 x86_wait = emit8 0x9b
 
+x86_fp_op_mem :: Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fp_op_mem opc mem is_double =     
     do emit8 (if is_double then 0xdc else 0xd8)       
        x86_mem_emit opc mem
+x86_fp_op_membase :: Word8 -> Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fp_op_membase opc basereg disp is_double =        
     do emit8 (if is_double then 0xdc else 0xd8)       
        x86_membase_emit opc basereg disp      
+x86_fp_op ::Word8 -> Word8 -> CodeGen e s ()
 x86_fp_op opc index = 
     do emit8 0xd8
        emit8 (0xc0 + (opc `shiftL` 3) + (index .&. 0x07))
+x86_fp_op_reg :: Int -> Word8 -> Bool -> CodeGen e s ()
 x86_fp_op_reg opc index pop_stack =   
-    do let  map = [ 0, 1, 2, 3, 5, 4, 7, 6, 8]        
+    do let  opcMap = [ 0, 1, 2, 3, 5, 4, 7, 6, 8]        
        emit8 (if pop_stack then 0xde else 0xdc)       
-       emit8 (0xc0 + ((map !! opc) `shiftL` 3) + (index .&. 0x07))
+       emit8 (0xc0 + ((opcMap !! opc) `shiftL` 3) + (index .&. 0x07))
 
 
 -- @x86_fp_int_op_membase
@@ -906,67 +995,100 @@
 -- Operand is addressed by [basereg + disp].
 -- is_int specifies whether operand is int32 (TRUE) or int16 (FALSE).
 
+x86_fp_int_op_membase :: Word8 -> Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fp_int_op_membase opc basereg disp is_int =
     do emit8 (if is_int then 0xda else 0xde)  
        x86_membase_emit opc basereg disp      
+x86_fstp :: Word8 -> CodeGen e s ()
 x86_fstp index =      
     emit8 0xdd >> emit8 (0xd8 + index)        
+x86_fcompp :: CodeGen e s ()
 x86_fcompp = emit8 0xde >> emit8 0xd9 
+x86_fucompp :: CodeGen e s ()
 x86_fucompp = emit8 0xda >> emit8 0xe9        
+x86_fnstsw :: CodeGen e s ()
 x86_fnstsw = emit8 0xdf >> emit8 0xe0 
+x86_fnstcw :: Word32 -> CodeGen e s ()
 x86_fnstcw mem = emit8 0xd9 >> x86_mem_emit 7 mem     
+x86_fnstcw_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_fnstcw_membase basereg disp =     
     emit8 0xd9 >> x86_membase_emit 7 basereg disp     
+x86_fldcw :: Word32 -> CodeGen e s ()
 x86_fldcw mem = emit8 0xd9 >> x86_mem_emit 5 mem      
+x86_fldcw_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_fldcw_membase basereg disp =      
     emit8 0xd9 >> x86_membase_emit 5 basereg disp     
+x86_fchs :: CodeGen e s ()
 x86_fchs = emit8 0xd9 >> emit8 0xe0   
+x86_frem :: CodeGen e s ()
 x86_frem = emit8 0xd9 >> emit8 0xf8
+x86_fxch :: Word8 -> CodeGen e s ()
 x86_fxch index = emit8 0xd9 >> emit8 (0xc8 + (index .&. 0x07))        
+x86_fcomi :: Word8 -> CodeGen e s ()
 x86_fcomi index = emit8 0xdb >> emit8 (0xf0 + (index .&. 0x07))       
+x86_fcomip :: Word8 -> CodeGen e s ()
 x86_fcomip index = emit8 0xdf >> emit8 (0xf0 + (index .&. 0x07))      
+x86_fucomi :: Word8 -> CodeGen e s ()
 x86_fucomi index = emit8 0xdb >> emit8 (0xe8 + (index .&. 0x07))
+x86_fucomip :: Word8 -> CodeGen e s ()
 x86_fucomip index = emit8 0xdf >> emit8 (0xe8 + (index .&. 0x07))
+x86_fld :: Word32 -> Bool -> CodeGen e s ()
 x86_fld mem is_double =       
     do emit8 (if is_double then 0xdd else 0xd9)       
        x86_mem_emit 0 mem     
+x86_fld_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fld_membase basereg disp is_double =      
     do emit8 (if is_double then 0xdd else 0xd9)       
        x86_membase_emit 0 basereg disp        
+x86_fld80_mem :: Word32 -> CodeGen e s ()
 x86_fld80_mem mem = emit8 0xdb >> x86_mem_emit 5 mem  
+x86_fld80_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_fld80_membase basereg disp =      
     emit8 0xdb >> x86_membase_emit 5 basereg disp     
+x86_fild :: Word32 -> Bool -> CodeGen e s ()
 x86_fild mem is_long =        
     if is_long
        then emit8 0xdf >> x86_mem_emit 5 mem  
        else emit8 0xdb >> x86_mem_emit 0 mem  
+x86_fild_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fild_membase basereg disp is_long =       
     if is_long
        then emit8 0xdf >> x86_membase_emit 5 basereg disp     
        else emit8 0xdb >> x86_membase_emit 0 basereg disp     
+x86_fld_reg :: Word8 -> CodeGen e s ()
 x86_fld_reg index =   
     emit8 0xd9 >> emit8 (0xc0 + (index .&. 0x07))
+x86_fldz :: CodeGen e s ()
 x86_fldz = emit8 0xd9 >> emit8 0xee   
+x86_fld1 :: CodeGen e s ()
 x86_fld1 = emit8 0xd9 >> emit8 0xe8
+x86_fldpi :: CodeGen e s ()
 x86_fldpi = emit8 0xd9 >> emit8 0xeb  
 
+x86_fst :: Word32 -> Bool -> Bool -> CodeGen e s ()
 x86_fst mem is_double pop_stack =     
     do emit8 (if is_double then 0xdd else 0xd9)
        x86_mem_emit (2 + (if pop_stack then 1 else 0)) mem    
+x86_fst_membase :: Word8 -> Word32 -> Bool -> Bool -> CodeGen e s ()
 x86_fst_membase basereg disp is_double pop_stack =    
     do emit8 (if is_double then 0xdd else 0xd9)       
        x86_membase_emit (2 + (if pop_stack then 1 else 0)) basereg disp
+x86_fst80_mem :: Word32 -> CodeGen e s ()
 x86_fst80_mem mem = emit8 0xdb >> x86_mem_emit 7 mem  
+x86_fst80_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_fst80_membase basereg disp =      
     emit8 0xdb >> x86_membase_emit 7 basereg disp     
+x86_fist_pop :: Word32 -> Bool -> CodeGen e s ()
 x86_fist_pop mem is_long =    
     if is_long
        then emit8 0xdf >> x86_mem_emit 7 mem  
        else emit8 0xdb >> x86_mem_emit 3 mem  
+x86_fist_pop_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fist_pop_membase basereg disp is_long =   
      if is_long
         then emit8 0xdf >> x86_membase_emit 7 basereg disp    
         else emit8 0xdb >> x86_membase_emit 3 basereg disp    
+x86_fstsw :: CodeGen e s ()
 x86_fstsw = emit8 0x9b >> emit8 0xdf >> emit8 0xe0
 
 -- @x86_fist_membase
@@ -974,6 +1096,7 @@
 -- addressed by [basereg + disp].
 -- is_int specifies whether destination is int32 (TRUE) or int16 (FALSE).
 
+x86_fist_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_fist_membase basereg disp is_int =        
     if is_int
        then emit8 0xdb >> x86_membase_emit 2 basereg disp     
@@ -981,14 +1104,27 @@
 
 -- PUSH instruction.
 
+x86_push_reg :: Word8 -> CodeGen e s ()
 x86_push_reg reg = emit8 (0x50 + reg) 
+
+x86_push_regp :: Word8 -> CodeGen e s ()
 x86_push_regp reg = emit8 0xff >> x86_regp_emit 6 reg 
+
+x86_push_mem :: Word32 -> CodeGen e s ()
 x86_push_mem mem = emit8 0xff >> x86_mem_emit 6 mem   
+
+x86_push_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_push_membase basereg disp = 
     emit8 0xff >> x86_membase_emit 6 basereg disp     
-x86_push_memindex basereg disp indexreg shift =
-    emit8 0xff >> x86_memindex_emit 6 basereg disp indexreg shift     
+
+x86_push_memindex :: Word8 -> Word32 -> Word8 -> Word8 -> CodeGen e s ()
+x86_push_memindex basereg disp indexreg shft =
+    emit8 0xff >> x86_memindex_emit 6 basereg disp indexreg shft
+
+x86_push_imm_template :: CodeGen e s ()
 x86_push_imm_template = x86_push_imm 0xf0f0f0f0
+
+x86_push_imm :: Word32 -> CodeGen e s ()
 x86_push_imm imm =    
     if x86_is_imm8 imm
     then emit8 0x6A >> x86_imm_emit8 (fromIntegral imm)
@@ -996,46 +1132,79 @@
 
 -- POP instruction.
 
+x86_pop_reg :: Word8 -> CodeGen e s ()
 x86_pop_reg reg = emit8 (0x58 + reg)
+
+x86_pop_mem :: Word32 -> CodeGen e s ()
 x86_pop_mem mem = emit8 0x87 >> x86_mem_emit 0 mem    
+
+x86_pop_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_pop_membase basereg disp =        
     emit8 0x87 >> x86_membase_emit 0 basereg disp     
 
+x86_pushad :: CodeGen e s ()
 x86_pushad = emit8 0x60
+
+x86_pushfd :: CodeGen e s ()
 x86_pushfd = emit8 0x9c
+
+x86_popad :: CodeGen e s ()
 x86_popad  = emit8 0x61
+
+x86_popfd :: CodeGen e s ()
 x86_popfd  = emit8 0x9d
 
+x86_loop ::  Word8 -> CodeGen e s ()
 x86_loop imm = emit8 0xe2 >> x86_imm_emit8 imm        
+
+x86_loope :: Word8 -> CodeGen e s ()
 x86_loope imm = emit8 0xe1 >> x86_imm_emit8 imm       
+
+x86_loopne :: Word8 -> CodeGen e s ()
 x86_loopne imm = emit8 0xe0 >> x86_imm_emit8 imm      
 
+x86_jump32 :: Word32 -> CodeGen e s ()
 x86_jump32 imm = emit8 0xe9 >> x86_imm_emit32 imm     
+
+x86_jump8 :: Word8 -> CodeGen e s ()
 x86_jump8 imm = emit8 0xeb >> x86_imm_emit8 imm       
+
+x86_jump_reg :: Word8 -> CodeGen e s ()
 x86_jump_reg reg = emit8 0xff >> x86_reg_emit 4 reg   
+
+x86_jump_mem :: Word32 -> CodeGen e s ()
 x86_jump_mem mem = emit8 0xff >> x86_mem_emit 4 mem   
+
+x86_jump_membase :: Word8 -> Word32 -> CodeGen e s ()
 x86_jump_membase basereg disp =       
     emit8 0xff >> x86_membase_emit 4 basereg disp     
 
 -- target is a pointer in our buffer.
 
+{-
 x86_jump_code target =
     do inst <- getCodeOffset
        let t = target - inst - 2      
        if x86_is_imm8 t
           then x86_jump8 (fromIntegral t)
           else x86_jump32 (fromIntegral (t - 3))
+-}
+{-
 x86_jump_disp disp =  
     do let t = disp - 2
        if x86_is_imm8 t
           then x86_jump8 (fromIntegral t)
           else x86_jump32 (t - 3)
+-}
 
+x86_branch8 :: Int -> Word8 -> Bool -> CodeGen e s ()
 x86_branch8 cond imm is_signed =      
     do if is_signed   
           then emit8 (x86_cc_signed_map !! cond)
           else emit8 (x86_cc_unsigned_map !! cond)    
        x86_imm_emit8 imm      
+
+x86_branch32 :: Int -> Word32 -> Bool -> CodeGen e s ()
 x86_branch32 cond imm is_signed =     
     do emit8 0x0f     
        if is_signed   
@@ -1043,21 +1212,25 @@
           else emit8 ((x86_cc_unsigned_map !! cond) + 0x10)   
        x86_imm_emit32 imm     
 
+x86_branch :: Int -> Int -> Bool -> CodeGen e s ()
 x86_branch cond target is_signed =    
     do inst <- getCodeOffset
        let offset = target - inst - 2;        
        if x86_is_imm8 offset
           then x86_branch8 cond (fromIntegral offset) is_signed
           else x86_branch32 cond (fromIntegral (offset - 4)) is_signed
-
+{-
 x86_branch_disp cond disp is_signed = 
     do let offset = disp - 2
        if x86_is_imm8 offset
           then x86_branch8 cond (fromIntegral offset) is_signed
           else x86_branch32 cond (offset - 4) is_signed
+-}
 
+x86_jecxz :: Word8 -> CodeGen e s ()
 x86_jecxz imm = emit8 0xe3 >> emit8 imm
 
+x86_set_reg :: Int -> Word8 -> Bool -> CodeGen e s ()
 x86_set_reg cond reg is_signed =      
     do emit8 0x0f     
        if is_signed
@@ -1065,12 +1238,14 @@
           else emit8 ((x86_cc_unsigned_map !! cond) + 0x20)   
        x86_reg_emit 0 reg     
 
+x86_set_mem :: Int -> Word32 -> Bool -> CodeGen e s ()
 x86_set_mem cond mem is_signed =      
     do emit8 0x0f     
        if is_signed
           then emit8 ((x86_cc_signed_map !! cond) + 0x20)     
           else emit8 ((x86_cc_unsigned_map !! cond) + 0x20)   
        x86_mem_emit 0 mem     
+x86_set_membase :: Int -> Word8 -> Word32 -> Bool -> CodeGen e s ()
 x86_set_membase cond basereg disp is_signed = 
     do emit8 0x0f     
        if is_signed
@@ -1117,18 +1292,21 @@
     if imm == 0 then x86_ret else emit8 0xc2 >> x86_imm_emit16 imm    
 
 -- Conditional move instructions.
-
+x86_cmov ::Int -> Bool -> CodeGen e s ()
 x86_cmov cond is_signed =
     do emit8 0x0f     
        if is_signed
           then emit8 ((x86_cc_signed_map !! cond) - 0x30)
           else emit8 ((x86_cc_unsigned_map !! cond) - 0x30)
+x86_cmov_reg :: Int -> Bool -> Word8 -> Word8 -> CodeGen e s ()
 x86_cmov_reg cond is_signed dreg reg =        
     do x86_cmov cond is_signed
        x86_reg_emit dreg reg  
+x86_cmov_mem :: Int -> Bool -> Word8 -> Word32 -> CodeGen e s ()
 x86_cmov_mem cond is_signed reg mem = 
     do x86_cmov cond is_signed
        x86_mem_emit reg mem   
+x86_cmov_membase :: Int -> Bool -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
 x86_cmov_membase cond is_signed reg basereg disp =    
     do x86_cmov cond is_signed
        x86_membase_emit reg basereg disp      
@@ -1163,6 +1341,7 @@
 
 -- Fast instruction sequences for 1 to 7-byte noops.
 
+x86_padding ::(Num t) => t -> CodeGen e s ()
 x86_padding size =    
     case size of
       1 -> x86_nop
@@ -1221,341 +1400,273 @@
        else return ()
 
 -- TODO: Move signatures to definition, delete duplicates.
-x86_cmpxchg_reg_reg ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_cmpxchg_mem_reg ::
-  forall e s.
-  Word32
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_cmpxchg_membase_reg ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
 x86_xchg_reg_reg ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_xchg_mem_reg ::
-  forall a e s.
   (Num a) =>
   Word32
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_xchg_membase_reg ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word32
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_xadd_reg_reg ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_xadd_mem_reg ::
-  forall a e s.
   (Num a) =>
   Word32
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_xadd_membase_reg ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word32
   -> Word8
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_inc_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> CodeGen e s ()
 x86_inc_membase ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_inc_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> CodeGen e s ()
 x86_dec_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> CodeGen e s ()
 x86_dec_membase ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_dec_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> CodeGen e s ()
 x86_not_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> CodeGen e s ()
 x86_not_membase ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_not_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> CodeGen e s ()
 x86_neg_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> CodeGen e s ()
 x86_neg_membase ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_neg_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> CodeGen e s ()
 x86_alu_mem_imm ::
-  forall e s.
   Word8
   -> Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_membase_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_membase8_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_mem_reg ::
-  forall e s.
   Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_membase_reg ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_reg_reg ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_reg8_reg8 ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
   -> Bool
   -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_reg_mem ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_alu_reg_membase ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_reg_imm ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_mem_imm ::
-  forall e s.
   Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_membase_imm ::
-  forall e s.
   Word8
   -> Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_reg_reg ::
-  forall e s.
   Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_mem_reg ::
-  forall e s.
   Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_test_membase_reg ::
-  forall e s.
   Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_reg_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_mem_imm ::
-  forall e s.
   Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_membase_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_reg ::
-  forall e s.
   Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_mem ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shift_membase ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shrd_reg ::
-  forall e s.
   Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shrd_reg_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shld_reg ::
-  forall e s.
   Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_shld_reg_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mul_reg ::
-  forall e s.
-  Word8 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> Bool -> CodeGen e s ()
 x86_mul_mem ::
-  forall e s.
-  Word32 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> Bool -> CodeGen e s ()
 x86_mul_membase ::
-  forall e s.
   Word8
   -> Word32
   -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_reg ::
-  forall e s.
   Word8
   -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_mem ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_membase ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_reg_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_mem_imm ::
-  forall e s.
   Word8
   -> Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_imul_reg_membase_imm ::
-  forall e s.
   Word8
   -> Word8
   -> Word32
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_div_reg ::
-  forall e s.
-  Word8 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word8 -> Bool -> CodeGen e s ()
 x86_div_mem ::
-  forall e s.
-  Word32 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
+  Word32 -> Bool -> CodeGen e s ()
 x86_div_membase ::
-  forall e s.
   Word8
   -> Word32
   -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_mem_reg ::
-  forall t e s.
   (Num t) =>
   Word32
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_regp_reg ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_regp ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_membase_reg ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word32
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_memindex_reg ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word32
@@ -1563,31 +1674,27 @@
   -> Word8
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_reg ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_mem ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word32
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_membase ::
-  forall t e s.
   (Num t) =>
   Word8
   -> Word8
   -> Word32
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_memindex ::
-  forall e s t.
   (Num t) =>
   Word8
   -> Word8
@@ -1595,29 +1702,25 @@
   -> Word8
   -> Word8
   -> t
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_reg_imm ::
-  forall e s.
   Word8
   -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_mem_imm ::
-  forall a e s.
   (Num a) =>
   Word32
   -> Word32
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_membase_imm ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word32
   -> Word32
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 x86_mov_memindex_imm ::
-  forall a e s.
   (Num a) =>
   Word8
   -> Word32
@@ -1625,156 +1728,285 @@
   -> Word8
   -> Word32
   -> a
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_lea_mem ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_lea_membase ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_lea_memindex ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_widen_reg ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Bool
-  -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_widen_mem ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Bool
-  -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_widen_membase ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Word32
-  -> Bool
-  -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_widen_memindex ::
-  forall e s.
-  Word8
-  -> Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> Bool
-  -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_regp ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_membase ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_memindex ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_imm_template ::
-  forall e s. Harpy.CodeGenMonad.CodeGen e s ()
-x86_push_imm ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_pop_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_pop_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_pop_membase ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_pushad :: forall e s. Harpy.CodeGenMonad.CodeGen e s ()
-x86_pushfd :: forall e s. Harpy.CodeGenMonad.CodeGen e s ()
-x86_popad :: forall e s. Harpy.CodeGenMonad.CodeGen e s ()
-x86_popfd :: forall e s. Harpy.CodeGenMonad.CodeGen e s ()
-x86_loop ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_loope ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_loopne ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jump32 ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jump8 ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jump_reg ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jump_mem ::
-  forall e s. Word32 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jump_membase ::
-  forall e s.
-  Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_branch8 ::
-  forall e s.
-  Int -> Word8 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_branch32 ::
-  forall e s.
-  Int -> Word32 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_branch ::
-  forall e s. Int -> Int -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_jecxz ::
-  forall e s. Word8 -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_set_reg ::
-  forall e s.
-  Int -> Word8 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_set_mem ::
-  forall e s.
-  Int -> Word32 -> Bool -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_set_membase ::
-  forall e s.
-  Int
-  -> Word8
-  -> Word32
-  -> Bool
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_cmov_reg ::
-  forall e s.
-  Int
-  -> Bool
-  -> Word8
-  -> Word8
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_cmov_mem ::
-  forall e s.
-  Int
-  -> Bool
-  -> Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
-x86_cmov_membase ::
-  forall e s.
-  Int
-  -> Bool
-  -> Word8
-  -> Word8
-  -> Word32
-  -> Harpy.CodeGenMonad.CodeGen e s ()
+  -> CodeGen e s ()
 
+-- SSE instructions.
+
+data X86_SSE_PFX = X86_SSE_SD
+                 | X86_SSE_SS
+                 | X86_SSE_PD
+                 | X86_SSE_PS
+--newtype X86_SSE_PFX = X86_SSE_PFX (forall e s. CodeGen e s ())
+
+x86_sse_sd, x86_sse_ss, x86_sse_pd, x86_sse_ps :: X86_SSE_PFX
+x86_sse_sd = X86_SSE_SD
+x86_sse_ss = X86_SSE_SS
+x86_sse_pd = X86_SSE_PD
+x86_sse_ps = X86_SSE_PS
+
+emit_sse :: X86_SSE_PFX -> CodeGen e s ()
+emit_sse X86_SSE_SD = emit8 0xf2
+emit_sse X86_SSE_SS = emit8 0xf3
+emit_sse X86_SSE_PD = emit8 0x66
+emit_sse X86_SSE_PS = return ()
+
+x86_sqrt_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_sqrt_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x51
+       x86_reg_emit dreg reg
+
+x86_sqrt_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_sqrt_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x51
+       x86_mem_emit dreg mem
+
+x86_sqrt_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_sqrt_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x51
+       x86_membase_emit dreg basereg disp
+
+x86_add_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_add_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x58
+       x86_reg_emit dreg reg
+
+x86_add_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_add_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x58
+       x86_mem_emit dreg mem
+
+x86_add_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_add_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x58
+       x86_membase_emit dreg basereg disp
+
+x86_mul_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_mul_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x59
+       x86_reg_emit dreg reg
+
+x86_mul_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_mul_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x59
+       x86_mem_emit dreg mem
+
+x86_mul_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_mul_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x59
+       x86_membase_emit dreg basereg disp
+
+x86_sub_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_sub_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5c
+       x86_reg_emit dreg reg
+
+x86_sub_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_sub_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5c
+       x86_mem_emit dreg mem
+
+x86_sub_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_sub_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5c
+       x86_membase_emit dreg basereg disp
+
+x86_min_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_min_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5d
+       x86_reg_emit dreg reg
+
+x86_min_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_min_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5d
+       x86_mem_emit dreg mem
+
+x86_min_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_min_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5d
+       x86_membase_emit dreg basereg disp
+
+x86_div_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_div_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5e
+       x86_reg_emit dreg reg
+
+x86_div_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_div_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5e
+       x86_mem_emit dreg mem
+
+x86_div_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_div_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5e
+       x86_membase_emit dreg basereg disp
+
+x86_max_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_max_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5f
+       x86_reg_emit dreg reg
+
+x86_max_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_max_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5f
+       x86_mem_emit dreg mem
+
+x86_max_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_max_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x5f
+       x86_membase_emit dreg basereg disp
+
+x86_mov_sse_reg_reg :: X86_SSE_PFX -> Word8 -> Word8 -> CodeGen e s ()
+x86_mov_sse_reg_reg pfx dreg reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x10
+       x86_reg_emit dreg reg
+
+x86_mov_sse_reg_mem :: X86_SSE_PFX -> Word8 -> Word32 -> CodeGen e s ()
+x86_mov_sse_reg_mem pfx dreg mem =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x10
+       x86_mem_emit dreg mem
+
+x86_mov_sse_reg_membase :: X86_SSE_PFX -> Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_mov_sse_reg_membase pfx dreg basereg disp =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x10
+       x86_membase_emit dreg basereg disp
+
+x86_mov_sse_mem_reg :: X86_SSE_PFX -> Word32 -> Word8 -> CodeGen e s ()
+x86_mov_sse_mem_reg pfx mem reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x11
+       x86_mem_emit reg mem
+
+x86_mov_sse_membase_reg :: X86_SSE_PFX -> Word8 -> Word32 -> Word8 -> CodeGen e s ()
+x86_mov_sse_membase_reg pfx basereg disp reg =
+    do emit_sse pfx
+       emit8 0x0f
+       emit8 0x11
+       x86_membase_emit reg basereg disp
+
+x86_ucomisd_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
+x86_ucomisd_reg_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2e
+       x86_reg_emit dreg reg
+
+x86_ucomisd_reg_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_ucomisd_reg_mem dreg mem =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2e
+       x86_mem_emit dreg mem
+
+x86_ucomisd_reg_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_ucomisd_reg_membase dreg basereg disp =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2e
+       x86_membase_emit dreg basereg disp
+
+x86_ucomiss_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
+x86_ucomiss_reg_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x2e
+       x86_reg_emit dreg reg
+
+x86_ucomiss_reg_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_ucomiss_reg_mem dreg mem =
+    do emit8 0x0f
+       emit8 0x2e
+       x86_mem_emit dreg mem
+
+x86_ucomiss_reg_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_ucomiss_reg_membase dreg basereg disp =
+    do emit8 0x0f
+       emit8 0x2e
+       x86_membase_emit dreg basereg disp
+
+x86_comisd_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
+x86_comisd_reg_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2f
+       x86_reg_emit dreg reg
+
+x86_comisd_reg_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_comisd_reg_mem dreg mem =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2f
+       x86_mem_emit dreg mem
+
+x86_comisd_reg_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_comisd_reg_membase dreg basereg disp =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x2e
+       x86_membase_emit dreg basereg disp
+
+x86_comiss_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
+x86_comiss_reg_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x2f
+       x86_reg_emit dreg reg
+
+x86_comiss_reg_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_comiss_reg_mem dreg mem =
+    do emit8 0x0f
+       emit8 0x2f
+       x86_mem_emit dreg mem
+
+x86_comiss_reg_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_comiss_reg_membase dreg basereg disp =
+    do emit8 0x0f
+       emit8 0x2e
+       x86_membase_emit dreg basereg disp
 
diff --git a/Harpy/X86Disassembler.hs b/Harpy/X86Disassembler.hs
--- a/Harpy/X86Disassembler.hs
+++ b/Harpy/X86Disassembler.hs
@@ -1,6 +1,6 @@
 --------------------------------------------------------------------------
 -- |
--- Module      :  X86Disassembler
+-- Module      :  Harpy.X86Disassembler
 -- Copyright   :  (c) Martin Grabmueller and Dirk Kleeblatt
 -- License     :  GPL
 -- 
@@ -10,9 +10,9 @@
 --
 -- Disassembler for x86 machine code.
 --
--- This is a disassembler for object code for the x86 architecture.  It
--- provides functions for disassembling byte arrays, byte lists and files
--- containing raw binary code.
+-- This is a disassembler for object code for the x86 architecture.
+-- It provides functions for disassembling byte arrays, byte lists and
+-- memory blocks containing raw binary code.
 -- 
 -- Features:
 --
@@ -67,8 +67,7 @@
   disassembleList,
   disassembleArray,
   showIntel,
-  showAtt,
-  testFile
+  showAtt
   ) where
 
 import Text.ParserCombinators.Parsec
@@ -501,15 +500,21 @@
 -- | All operands are in one of the following locations:
 --
 -- - Constants in the instruction stream
+--
 -- - Memory locations
+--
 -- - Registers
 --
 -- Memory locations are referred to by on of several addressing modes:
 --
 -- - Absolute (address in instruction stream)
+--
 -- - Register-indirect (address in register)
+--
 -- - Register-indirect with displacement
+--
 -- - Base-Index with scale
+--
 -- - Base-Index with scale and displacement 
 --
 -- Displacements can be encoded as 8 or 32-bit immediates in the
@@ -583,15 +588,15 @@
 -- | Some opcodes can operate on data of several widths.  This information
 -- is encoded in instructions using the following enumeration type..
 
-data InstrOperandSize = OPNONE 	-- ^ No operand size specified
-       	        | OP8 		-- ^ 8-bit integer operand
-       	        | OP16 		-- ^ 16-bit integer operand
-       	        | OP32		-- ^ 32-bit integer operand
-       	        | OP64		-- ^ 64-bit integer operand
-       	        | OP128		-- ^ 128-bit integer operand
-       	        | OPF32	    -- ^ 32-bit floating point operand
-       	        | OPF64	    -- ^ 64-bit floating point operand
-       	        | OPF80	    -- ^ 80-bit floating point operand
+data InstrOperandSize = OPNONE -- ^ No operand size specified
+       	        | OP8 	       -- ^ 8-bit integer operand
+       	        | OP16 	       -- ^ 16-bit integer operand
+       	        | OP32	       -- ^ 32-bit integer operand
+       	        | OP64	       -- ^ 64-bit integer operand
+       	        | OP128	       -- ^ 128-bit integer operand
+       	        | OPF32	       -- ^ 32-bit floating point operand
+       	        | OPF64	       -- ^ 64-bit floating point operand
+       	        | OPF80	       -- ^ 80-bit floating point operand
   deriving (Show)
 
 
@@ -602,13 +607,14 @@
 -- the instruction.
 
 data Instruction = 
-    BadInstruction Word8 String Int [Word8] -- ^ Invalid instruction
-  | Instruction { opcode :: Opcode, 	-- ^ Opcode of the instruction
+    BadInstruction Word8 String Int [Word8]   -- ^ Invalid instruction
+  | PseudoInstruction Int String                  -- ^ Pseudo instruction, e.g. label
+  | Instruction { opcode :: Opcode, 	      -- ^ Opcode of the instruction
        		  opsize :: InstrOperandSize, -- ^ Operand size, if any
-       		  operands :: [Operand], -- ^ Instruction operands
-                  address :: Int,    -- ^ Start address of instruction
-       		  bytes ::[Word8]	-- ^ Instruction bytes
-                 }			-- ^ Valid instruction
+       		  operands :: [Operand],      -- ^ Instruction operands
+                  address :: Int,             -- ^ Start address of instruction
+       		  bytes ::[Word8]	      -- ^ Instruction bytes
+                 }			      -- ^ Valid instruction
 
 instance Show Instruction where
     show = showIntel
@@ -620,7 +626,9 @@
 
 hex32 :: Int -> String
 hex32 i =
-    let s = showHex i ""
+    let w :: Word32
+        w = fromIntegral i
+        s = showHex w ""
     in take (8 - length s) (repeat '0') ++ s
 
 -- Show a byte as an 2-digit hexadecimal number with leading zeroes.
@@ -637,17 +645,24 @@
 -- Intel style:
 --
 -- - Destination operand comes first, source second.
+--
 -- - No register or immediate prefixes.
+--
 -- - Memory operands are annotated with operand size.
--- - Hexadecimal numbers are suffixed with H and prefixed with 0 if
+--
+-- - Hexadecimal numbers are suffixed with @H@ and prefixed with @0@ if
 --   necessary.
 --
 -- AT&T style:
 --
 -- - Source operand comes first, destination second.
--- - Register names are prefixes with %.
--- - Immediates are prefixed with $.
--- - Hexadecimal numbers are prefixes with 0x
+--
+-- - Register names are prefixes with @%@.
+--
+-- - Immediates are prefixed with @$@.
+--
+-- - Hexadecimal numbers are prefixes with @0x@
+--
 -- - Opcodes are suffixed with operand size, when ambiguous otherwise.
 data ShowStyle = IntelStyle		-- ^ Show in Intel style
                 | AttStyle		-- ^ Show in AT&T style
@@ -658,6 +673,8 @@
 showIntel (BadInstruction b desc pos bytes) =
     showPosBytes pos bytes ++
     "(" ++ desc ++ ", byte=" ++ show b ++ ")"
+showIntel (PseudoInstruction pos s) =
+    hex32 pos ++ "                          " ++ s
 showIntel (Instruction op opsize [] pos bytes) = 
     showPosBytes pos bytes ++
        showOp op
@@ -672,6 +689,8 @@
 showAtt (BadInstruction b desc pos bytes) = 
     showPosBytes pos bytes ++
        "(" ++ desc ++ ", byte=" ++ show b ++ ")"
+showAtt (PseudoInstruction pos s) =
+    hex32 pos ++ "                          " ++ s
 showAtt (Instruction op opsize [] pos bytes) = 
     showPosBytes pos bytes ++
        showOp op ++ showInstrSuffix [] opsize
@@ -731,13 +750,15 @@
 
 -- Show an immediate value in hexadecimal.
 
+showImm :: Word32 -> String
 showImm i =
   "$0x" ++ showHex i ""
 
+showIntelImm :: Word32 -> String
 showIntelImm i =
   let h = showHex i "H"
       (f:_) = h
-  in (if isDigit f then "" else "0") ++ showHex i "H"
+  in (if isDigit f then "" else "0") ++ h
 
 -- Show an address in hexadecimal.
 
@@ -750,7 +771,7 @@
       w = fromIntegral i
       h = showHex w "H"
       (f:_) = h
-  in (if isDigit f then "" else "0") ++ showHex w "H"
+  in (if isDigit f then "" else "0") ++ h
 
 -- | Disassemble a block of memory.  Starting at the location
 -- pointed to by the given pointer, the given number of bytes are
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
diff --git a/NEWS b/NEWS
new file mode 100644
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,46 @@
+							-*-outline-*-
+* Harpy NEWS
+
+** New in version 0.4
+
+- New convenience top-level module "Harpy", which re-exports
+  Harpy.CodeGenMonad, Harpy.Call and Harpy.X86Assembler
+
+- It is now possible to override Harpy's automatic code buffer
+  management.  The new field 'customCodeBuffer' in the type
+  'CodeGenConfig' can be set to 'Just (buf, size)', where 'buf' is a
+  pointer to a memory region of 'size' bytes.  Harpy will then use the
+  supplied code buffer and will not perform any automatic code buffer
+  allocation on overflow.  Overflow checking is still performed and
+  will result in an exception in the CodeGen monad.
+
+- When using the high-level assembler in X86Assembler, the code buffer
+  is automatically protected from overflow.
+
+- Floating point operations added to X86Assembler (only for double
+  operands yet).
+
+- Preliminary support for SSE instructions.  Currently, only the
+  packed and scalar floating-point arithmetic operations are supported
+  (both in the low-level module Harpy.X86CodeGen and as methods in
+  Harpy.X86Assembler)
+
+- Code buffer default size has been increased from 128 to 4096 bytes.
+
+- The CodeGenMonad fails when a label is defined twice.
+
+- It is now possible to associate names with labels, using the new
+  operation newNamedLabel.  The given names will show up in the
+  disassembly, which makes debugging of generated code much easier.
+
+- The doc directory contains a second, slightly larger tutorial now.
+
+- The examples/evaluator directory contains a small example
+  interpreter for arithmetic expressions, which translates expressions
+  entered at the keayboard to machine code on the fly.  This is the
+  demo program we presented at the Haskell Workshop 2007.
+
+** New in version 0.2
+
+- Everything is new!  This is the first released version.
+
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,18 @@
+all: larger-tutorial.pdf
+
+larger-tutorial.pdf: larger-tutorial.tex 
+
+larger-tutorial.tex: larger-tutorial.lhs
+	lhs2TeX $< > $@
+
+%.pdf: %.tex
+	pdflatex $<
+	pdflatex $<
+
+clean:
+	rm -f larger-tutorial.aux larger-tutorial.toc\
+ larger-tutorial.tex larger-tutorial.log larger-tutorial.out\
+ larger-tutorial.ptb
+
+really-clean: clean
+	rm -f larger-tutorial.pdf
diff --git a/doc/larger-tutorial.lhs b/doc/larger-tutorial.lhs
new file mode 100644
--- /dev/null
+++ b/doc/larger-tutorial.lhs
@@ -0,0 +1,312 @@
+\documentclass[a4paper,11pt]{article}
+
+\usepackage[margin=2.5cm]{geometry}
+\usepackage{hyperref}
+
+%include polycode.fmt
+%format alpha = "\alpha"
+
+
+\title{\textbf{Slightly Larger Harpy Tutorial}}
+\author{Martin Grabmüller \and Dirk Kleeblatt}
+
+\begin{document}
+\maketitle
+\begin{abstract}\noindent
+This tutorial is an introduction to some of the more advanced features
+of Harpy.  In the course of the tutorial, we will build a small
+run-time compiler for a call-by-value lambda-calculus.
+This document is written as a litarate Haskell program, so you can
+compile and run it without any modifications.  
+\end{abstract}
+
+\section{Introduction}
+
+In this tutorial, we develop a small run-time compiler for a simple
+call-by-value lambda calculus extended with natural number constants.
+
+Before reading, you should have read the Harpy tutorial, which
+introduces the most basic concepts.  We also recommend to have a
+running \verb|ghci| session running for loading the literate Haskell
+script of this tutorial and to try it out.  Maybe you want to have the
+Harpy API documentation available, too.
+
+\section{The Code}
+
+To make use of Harpy and (a subset of) the x86 assembler instructions, we need
+to import some modules.
+
+\begin{code}
+import Harpy.CodeGenMonad
+import Harpy.X86Assembler
+import Harpy.X86Disassembler
+import Foreign
+import Control.Monad
+import Control.Monad.Trans
+import Data.List 
+\end{code}
+
+The following module system hackery is necessary, because the
+|Harpy.X86Assembler| module exports a method called
+|div|, which clashes with the |div| function
+exported by the Haskell Prelude.  The prelude |div| will be
+hidden, but is still available as a qualified name.
+
+\begin{code}
+import Prelude hiding (div)
+import qualified Prelude
+\end{code}
+
+\subsection{Data Types}
+
+In the following, we define several data types for representing lambda
+calculus terms
+
+A |Name| represents a variable name.  In a real
+implementation, it would probably be more complicated data type for
+handling qualified or compiler-generated names.  For now, a string
+will suffice.
+
+\begin{code}
+type Name = String
+\end{code}
+
+In our implementation, a variable may refer to (a) a global variable,
+which is represented by its address, (b) a parameter, which is
+represented by the number of enclosing lambda expression, or (c) a
+free variable, which is represented by its index into the current code
+closure.
+
+\begin{code}
+data VarLoc  =  Global Word32
+	     |  Param Int
+             |  Free Int
+             deriving (Show)
+\end{code}
+
+A compile-time environment represents a mapping from variable names to
+variable locations.
+
+\begin{code}
+data Env = Env [(Name, VarLoc)]
+\end{code}
+
+An expression is represented by the following data type and may be a
+variable, an immediate value (integer constant), a lambda abstraction
+or an application expression.
+
+\begin{code}
+data Exp  =  Var Name
+	  |  Imm Int
+          |  Abs Name Exp
+          |  App Exp Exp
+\end{code}
+
+The |State| type represents the state of a running program.
+It consists of a pointer to the next available word of heap memory,
+and a pointer to the end of the heap.  These two values are necessary
+for dynamically allocating memory and for performing heap-overflow
+checks.
+
+\begin{code}
+data State = State {  heap     :: Ptr Word32,
+		      heapEnd  :: Ptr Word32}
+\end{code}
+
+The following test expressions are constructed using the constructors of
+type |Exp| and are to be evaluated by the main program.
+
+\begin{code}
+testExp0 = App (Abs "x" (Var "x")) (Imm 12)
+testExp1 = App (App (Abs "x" (Abs "y" (Var "x"))) (Imm 12)) (Imm 23)
+\end{code}
+
+\subsection{Main Program}
+
+Before presenting the compiler, we will have a look at how it is used.
+The entry point to the dynamic compiler is the function
+|interpret|, which takes an expression and returns the value
+calculated by the expression.  The main program simply prints the
+result.
+
+\begin{code}
+$(callDecl "callFunc" [t|Word32|])
+\end{code}
+
+\begin{code}
+main :: IO ()
+main = do  res <- interpret testExp1
+           putStrLn $ "Result: " ++ show res
+\end{code}
+
+The |interpret| function allocates 16 kbytes of heap and
+compiles the expression.  The |State| of the compiler is
+passed to the |runCodeGen| function as a user state.
+
+\begin{code}
+interpret :: Exp -> IO Word32
+interpret exp =
+    do  let heapSize = 1024 * 16
+        heap <- mallocBytes heapSize
+        (_, Right res) <- runCodeGen (compileTop exp) (Env []) 
+	 		  (State heap (heap `plusPtr` 
+				       (heapSize `Prelude.div` 4)))
+        return res
+\end{code}
+
+\subsection{Compilation}
+
+The compilation starts in the function |compileTop|, which emits code
+for creating a stack frame, saving all general-purpose registers
+(except \verb|eax|, which will contain the result of the execution),
+and finally compiles the expression.  Afterwards, all registers are
+restored and the function is called.  In addition we call the
+disassembler on the generated code and print it out.  This is a useful
+debuggin aid when generating assembler code.
+
+\begin{code}
+compileTop :: Exp -> CodeGen Env State Word32
+compileTop exp =
+    do  st <- getState
+        push ebp
+        mov ebp esp
+        push ebx
+        push ecx
+        push edi
+        push esi
+        mov ecx ((fromIntegral (ptrToWordPtr (heap st))) :: Word32)
+        compile exp
+        pop esi
+        pop edi
+        pop ecx
+        pop ebx
+        mov esp ebp
+        pop ebp
+        ret
+        y <- callFunc
+        dis <- disassemble
+        liftIO $ mapM_ (putStrLn . showIntel) dis
+        return y
+
+\end{code}
+
+\subsubsection{Handling Variables}
+
+The |findVar| function looks up a variable in the
+environment and returns its binding.
+
+\begin{code}
+findVar s = 
+    do  Env e <- getEnv
+        case lookup s e of
+          Just vl -> return vl
+	  Nothing -> error ("unbound variable: " ++ s)
+\end{code}
+
+For the implementation of closures, we need to calculate free
+variables of expressions, so that we know what to store into closures
+and how to access free variables from the body of a lambda expression.
+
+\begin{code}
+freeVariables (Var s) = return [s]
+freeVariables (Imm _) = return []
+freeVariables (Abs x b) = liftM (delete x) (freeVariables b)
+freeVariables (App e1 e2) = liftM2 union (freeVariables e1) (freeVariables e2)
+\end{code}
+
+\subsubsection{Heap Allocation}
+
+Closures are the only dynamically allocated structures in our little
+compiler.  They are allocated from a contiguous block of malloc'ed
+memory, which is passed in the code generator monad's state.  The
+following function generates code for allocating $w$ words of memory
+in the heap, and returning a pointer to the memory in register
+\verb|eax|.  On heap overflow, a breakpoint instruction is executed.
+
+\begin{code}
+emitAlloc w =
+    do  mov eax ecx
+        st <- getState
+        cmp ecx (fromIntegral (ptrToWordPtr (heapEnd st)) :: Word32)
+        next <- newLabel
+        jl next
+        breakpoint
+        defineLabel next
+        add ecx ((4 * w) :: Word32)
+\end{code}
+
+\subsubsection{The Compilation Proper}
+
+Finally, the |compile| function compiles an expression.
+Constants are simply loaded into the result register, values of
+variables are retrieved from their respective addresses (global
+variables from absolute addresses, parameters relative to the stack
+base pointer, and free variables relative to the closure pointer.
+
+\begin{code}
+compile :: Exp -> CodeGen Env State ()
+compile (Imm i) = 
+    do  mov eax (fromIntegral i :: Word32)
+compile (Var s) =
+    do  c <- findVar s
+        case c of
+          Global addr -> mov eax (Addr addr)
+	  Param ofs -> mov eax (Disp (fromIntegral ofs), ebp)
+	  Free ofs -> mov eax (Disp (fromIntegral ofs), esi)
+\end{code}
+
+Lambda expressions are more complicated.  We first need to calculate
+the set of free variables of the body expression.  Then the body of
+the expression is compiled (with a jump around its code, so that it is
+not actually executed at this point).  Then a closure record is
+allocated on the heap, a code pointer to the body is stored in the
+first word, and the values of all free variables of the body are
+calculated and moved into the remaining fields of the closure.
+
+The result is a pointer to the new closure, returned in \verb|eax|, as
+usual.
+
+\begin{code}
+compile exp@(Abs x body) =
+    do  fv <- freeVariables exp
+        let frees = zip fv (map Free [4,8..])
+        next <- newLabel
+        jmp next
+        f <- setLabel
+        push ebp
+        mov ebp esp
+        mov esi (Disp 8, ebp)
+        withEnv (Env ((x, Param 12) : frees)) (compile body)
+        mov esp ebp
+        pop ebp
+        ret
+        defineLabel next
+        emitAlloc (fromIntegral (length frees + 1))
+        mov edi eax
+        mov (Disp 0, edi) f
+        if length frees > 0
+           then do  push eax
+                    mapM_ (\ (x, Free ofs) -> 
+                           do  compile (Var x)
+                               mov (Disp (fromIntegral ofs), edi) eax)
+                      frees
+                    pop eax
+           else return ()
+compile (App e1 e2) = 
+    do  compile e2
+        push eax
+        compile e1
+        push eax
+        call (Disp 0, eax)
+        add esp (8 :: Word32)
+\end{code}
+
+\section{Conclusion}
+
+This completes our little just-in-time compiled lambda calculus
+evaluator.  We hope that this tutorial makes clear many of the fine
+points in using the libray.
+
+Happy Harpy Hacking in Haskell!
+
+\end{document}
diff --git a/examples/evaluator/ArithParser.hs b/examples/evaluator/ArithParser.hs
new file mode 100644
--- /dev/null
+++ b/examples/evaluator/ArithParser.hs
@@ -0,0 +1,73 @@
+module ArithParser where
+
+import Control.Monad
+
+import ArithTypes
+
+import Foreign
+
+import Text.ParserCombinators.Parsec
+import qualified Text.ParserCombinators.Parsec.Token as P
+import Text.ParserCombinators.Parsec.Language
+import Text.ParserCombinators.Parsec.Expr
+
+lexer :: P.TokenParser ()
+lexer  = P.makeTokenParser 
+         (haskellStyle
+         { reservedOpNames = ["*","/","+","-"]
+         })
+
+statement :: Parser Stmt
+statement = do s <- statement'
+               eof
+               return s
+
+statement' :: Parser Stmt
+statement' = try((do [i] <- identifier
+                     if i < 'a' || i > 'z'
+                       then fail "character a-z expected"
+                       else return ()
+                     symbol ":="
+                     e <- expr
+                     return $ Assign i e) <?> "assignment")
+            <|> liftM Cmd cmd
+            <|> liftM Print expr
+
+cmd :: Parser Cmd
+cmd = try (do symbol ":help"
+              return Help)
+      <|> try (do symbol ":verbose"
+                  return Verbose)
+      <|> (do symbol ":quit"
+              return Quit)
+
+expr    :: Parser Exp
+expr    = buildExpressionParser table factor
+        <?> "expression"
+
+table   = [[op "*" Mul AssocLeft, op "/" Div AssocLeft]
+          ,[op "+" Add AssocLeft, op "-" Sub AssocLeft]
+          ]
+        where
+          op s f assoc
+             = Infix (do{ reservedOp s; return f} <?> "operator") assoc
+
+factor  =   parens expr
+        <|> liftM (Lit . fromInteger) natural
+        <|> (do [i] <- identifier
+                if i < 'a' || i > 'z'
+                   then fail "character a-z expected"
+                   else return ()
+                return $ Var i)
+        <?> "simple expression"
+
+whiteSpace= P.whiteSpace lexer
+lexeme    = P.lexeme lexer
+symbol    = P.symbol lexer
+natural   = P.natural lexer
+parens    = P.parens lexer
+semi      = P.semi lexer
+identifier= P.identifier lexer
+reserved  = P.reserved lexer
+reservedOp= P.reservedOp lexer
+
diff --git a/examples/evaluator/ArithTypes.hs b/examples/evaluator/ArithTypes.hs
new file mode 100644
--- /dev/null
+++ b/examples/evaluator/ArithTypes.hs
@@ -0,0 +1,22 @@
+module ArithTypes where
+
+import Foreign
+
+data Stmt = Assign Char Exp
+          | Print Exp
+          | Cmd Cmd
+          deriving (Show)
+
+data Cmd = Help
+         | Quit
+         | Verbose
+         deriving (Show)
+
+data Exp = Add Exp Exp
+         | Sub Exp Exp
+         | Mul Exp Exp
+         | Div Exp Exp
+         | Lit Int32
+         | Var Char
+         deriving (Show)
+
diff --git a/examples/evaluator/Evaluator.hs b/examples/evaluator/Evaluator.hs
new file mode 100644
--- /dev/null
+++ b/examples/evaluator/Evaluator.hs
@@ -0,0 +1,118 @@
+module Main(main) where
+
+import ArithTypes
+import ArithParser
+
+import Harpy
+import Harpy.X86Disassembler
+
+import Foreign
+
+import Control.Monad
+
+import System.Console.Readline
+
+import Text.ParserCombinators.Parsec
+
+$(callDecl "callAsWord32" [t|Word32|])
+
+main :: IO ()
+main = do putStrLn "\n\n\n\nHarpy Interpreter"
+          putStrLn "(type :help to see a help message)"
+          allocaArray 26 (\ p -> mapM_ (\ i -> poke (advancePtr p i) 0) [0..25] >> repl p False)
+
+repl :: Ptr Int32 -> Bool -> IO ()
+repl env verbose =
+    do s <- readline "@ "
+       case s of
+         Nothing -> return ()
+         Just s' -> do addHistory s'
+                       interpret env verbose s'
+
+interpret :: Ptr Int32 -> Bool -> String -> IO ()
+interpret env verbose s = 
+    do let e = parse statement "<standard input>" s
+       case e of
+         Left err -> do putStrLn (show err)
+                        repl env verbose
+         Right stmt -> run env verbose stmt
+
+run :: Ptr Int32 -> Bool -> Stmt -> IO ()
+run env verbose (Cmd Help) = 
+    do putStrLn "Enter an arithmetic expression to evaluate it"
+       putStrLn "  e.g. 5 / 2"
+       putStrLn "Enter an assignment to set a variable"
+       putStrLn "  e.g. a := 4 * 2 - (6 + 1)"
+       putStrLn "Enter :help to see this message again"
+       putStrLn "Enter :quit to exit"
+       putStrLn "Enter :verbose to toggle disassembly output"
+       repl env verbose
+
+run env _ (Cmd Quit) = return ()
+
+run env verbose (Cmd Verbose) = repl env (Prelude.not verbose)
+
+run env verbose stmt@(Assign var exp) =
+    do (i, ins) <- eval' env stmt
+       when verbose (mapM_ (putStrLn . showIntel) ins)
+       repl env verbose
+
+run env verbose stmt@(Print exp) =
+    do (i, ins) <- eval' env stmt
+       putStrLn (show i)
+       when verbose (mapM_ (putStrLn . showIntel) ins)
+       repl env verbose
+
+-- Function for compiling and executing statements.
+eval' :: Ptr Int32 -> Stmt -> IO (Int32, [Instruction])
+eval' env e = do (_, Right v) <- runCodeGen (compileAndRun e) env ()
+                 return v
+
+compileAndRun :: Stmt -> CodeGen (Ptr Int32) s (Int32, [Instruction])
+compileAndRun (Assign c exp) = 
+    do entryCode
+       compileExp exp
+       env <- getEnv
+       mov (variableAddress env c) eax
+       exitCode
+       d <- disassemble
+       callAsVoid
+       return (0, d)
+compileAndRun (Print exp) =
+    do entryCode
+       compileExp exp
+       exitCode
+       d <- disassemble
+       r <- callAsWord32
+       return (fromIntegral r, d)
+
+compileExp :: Exp -> CodeGen (Ptr Int32) s ()
+compileExp (Add e1 e2) = compileBinOp e1 e2 (add eax (Ind esp))
+compileExp (Sub e1 e2) = compileBinOp e1 e2 (sub eax (Ind esp))
+compileExp (Mul e1 e2) = compileBinOp e1 e2 (imul InPlace eax (Ind esp))
+compileExp (Div e1 e2) = compileBinOp e1 e2 (cdq >> idiv (Ind esp))
+compileExp (Lit i) = mov eax ((fromIntegral i) :: Word32)
+compileExp (Var c) = do env <- getEnv
+                        mov eax (variableAddress env c)
+
+compileBinOp :: Exp -> Exp -> CodeGen (Ptr Int32) s a -> CodeGen (Ptr Int32) s ()
+compileBinOp e1 e2 op = do compileExp e2
+                           push eax
+                           compileExp e1
+                           op
+                           add esp (4 :: Word32) 
+
+entryCode :: CodeGen e s ()
+entryCode = do push ebp
+               mov ebp esp
+
+exitCode :: CodeGen e s ()
+exitCode = do mov esp ebp
+              pop ebp
+              ret
+
+variableAddress :: Ptr Int32 -> Char -> Addr
+variableAddress env c =
+    let ofs = fromEnum c - fromEnum 'a'
+        env' = advancePtr env ofs
+    in Addr (fromIntegral (ptrToWordPtr env'))
diff --git a/harpy.cabal b/harpy.cabal
--- a/harpy.cabal
+++ b/harpy.cabal
@@ -1,12 +1,13 @@
+Cabal-version:  >=1.2
 Name:           harpy
-Version:        0.2
+Version:        0.4
 License:        GPL
 License-file:   COPYING
 Author:         Dirk Kleeblatt <klee@cs.tu-berlin.de>
                 Martin Grabmueller <magr@cs.tu-berlin.de>
 Maintainer:     klee@cs.tu-berlin.de, magr@cs.tu-berlin.de
 Homepage:       http://uebb.cs.tu-berlin.de/harpy/
-Category:       Code generation
+Category:       Code Generation
 Synopsis:       Runtime code generation for x86 machine code
 Description:	The package contains the following components:
 	.
@@ -27,15 +28,35 @@
 	.
 	* All the above modules use the code generation monad defined in module
 	  "Harpy.CodeGenMonad".
+        .
+        * The Darcs repo and two tutorials on using Harpy can be found at
+          Harpy's homepage: <http://uebb.cs.tu-berlin.de/harpy/>
 Stability:      Experimental
-Build-depends:  base, parsec, mtl, template-haskell
-Exposed-Modules:
+
+Extra-source-files: 
+    NEWS README Makefile
+    doc/Makefile doc/tutorial.lhs doc/larger-tutorial.lhs
+    examples/evaluator/ArithTypes.hs examples/evaluator/ArithParser.hs
+    examples/evaluator/Evaluator.hs
+
+Flag small_base
+  Description: Choose the new smaller, split-up base package.
+
+Library
+  if flag(small_base)
+    Build-depends:  base >= 3,parsec,mtl,template-haskell,pretty,containers,array
+  else
+    Build-Depends: base < 3,parsec,mtl,template-haskell
+  Exposed-Modules:
+    Harpy,
     Harpy.X86CodeGen,
     Harpy.X86Assembler,
     Harpy.CodeGenMonad,
     Harpy.Call,
     Harpy.X86Disassembler,
     Harpy.X86CGCombinators
-Extensions:     ForeignFunctionInterface, MultiParamTypeClasses, 
-	TemplateHaskell, CPP
-ghc-options:	-O
+  Extensions: 
+    ForeignFunctionInterface, MultiParamTypeClasses, 
+    TemplateHaskell, CPP, FlexibleContexts, FlexibleInstances,
+    RankNTypes
+  Ghc-options: -O2 
