Initial commit: 0.4.3.0 from hackage
authorBernhard Urban <lewurm@gmail.com>
Sun, 22 Apr 2012 18:03:52 +0000 (20:03 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sun, 22 Apr 2012 18:03:52 +0000 (20:03 +0200)
19 files changed:
COPYING [new file with mode: 0644]
Harpy.hs [new file with mode: 0644]
Harpy/Call.hs [new file with mode: 0644]
Harpy/CodeGenMonad.hs [new file with mode: 0644]
Harpy/X86Assembler.hs [new file with mode: 0644]
Harpy/X86CGCombinators.hs [new file with mode: 0644]
Harpy/X86CodeGen.hs [new file with mode: 0644]
Harpy/X86Disassembler.hs [new file with mode: 0644]
Makefile [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
Setup.hs [new file with mode: 0644]
doc/Makefile [new file with mode: 0644]
doc/larger-tutorial.lhs [new file with mode: 0644]
doc/tutorial.lhs [new file with mode: 0644]
examples/evaluator/ArithParser.hs [new file with mode: 0644]
examples/evaluator/ArithTypes.hs [new file with mode: 0644]
examples/evaluator/Evaluator.hs [new file with mode: 0644]
harpy.cabal [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..623b625
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Harpy.hs b/Harpy.hs
new file mode 100644 (file)
index 0000000..89e58cd
--- /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
new file mode 100644 (file)
index 0000000..76d4af5
--- /dev/null
@@ -0,0 +1,35 @@
+{-# OPTIONS -cpp #-}
+
+--------------------------------------------------------------------------
+-- |
+-- Module      :  Harpy.Call
+-- Copyright   :  (c) 2006-2007 Martin Grabmueller and Dirk Kleeblatt
+-- License     :  GPL
+-- 
+-- Maintainer  :  {magr,klee}@cs.tu-berlin.de
+-- Stability   :  provisional
+-- Portability :  non-portable
+--
+-- Predefined call stubs for run-time generated code.
+--------------------------------------------------------------------------
+
+module Harpy.Call where
+
+import Harpy.CodeGenMonad
+
+import Data.Word
+import Foreign.Ptr
+
+#ifndef __HADDOCK__
+
+$(callDecl "callAsVoid" [t|()|])
+$(callDecl "callAsWord32ToWord32" [t|Word32 -> Word32|])
+$(callDecl "callAs7PtrToVoid" [t|forall a b c d e f g . Ptr a -> Ptr b -> Ptr c -> Ptr d -> Ptr e -> Ptr f -> Ptr g -> () |])
+
+#else
+
+callAsVoid :: CodeGen e s ()
+callAsWord32ToWord32 :: Word32 -> CodeGen e s Word32
+callAs7PtrToVoid :: forall a b c d e f g e' s'. Ptr a -> Ptr b -> Ptr c -> Ptr d -> Ptr e -> Ptr f -> Ptr g -> CodeGen e' s' ()
+
+#endif
diff --git a/Harpy/CodeGenMonad.hs b/Harpy/CodeGenMonad.hs
new file mode 100644 (file)
index 0000000..20e81dd
--- /dev/null
@@ -0,0 +1,588 @@
+{-# OPTIONS -cpp #-}
+
+--------------------------------------------------------------------------
+-- |
+-- 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)
+--
+-- Monad for generating x86 machine code at runtime.
+--
+-- This is a combined reader-state-exception monad which handles all
+-- 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 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,
+          ErrMsg,
+          RelocKind(..),
+          Reloc,
+          Label,
+          FixupKind(..),
+          CodeGenConfig(..),
+          defaultCodeGenConfig,
+    -- * Functions
+    -- ** General code generator monad operations
+          failCodeGen,
+    -- ** Accessing code generation internals
+          getEntryPoint,
+          getCodeOffset,
+          getBasePtr,
+          getCodeBufferList,
+    -- ** Access to user state and environment
+          setState,
+          getState,
+          getEnv,
+          withEnv,
+    -- ** Label management
+          newLabel,
+          newNamedLabel,
+          setLabel,
+          defineLabel,
+          (@@),
+          emitFixup,
+          labelAddress,
+          emitRelocInfo,
+    -- ** Code emission
+          emit8,
+          emit8At,
+          peek8At,
+          emit32,
+          emit32At,
+          checkBufferSize,
+          ensureBufferSize,
+    -- ** Executing code generation
+          runCodeGen,
+          runCodeGenWithConfig,
+    -- ** Calling generated functions
+          callDecl,
+    -- ** Interface to disassembler
+          disassemble
+    ) where
+
+import qualified Harpy.X86Disassembler as Dis
+
+import Control.Monad
+
+import Text.PrettyPrint.HughesPJ
+
+import Numeric
+
+import Data.List
+import qualified Data.Map as Map
+import Foreign
+import System.IO
+
+import Control.Monad.Trans
+
+import Language.Haskell.TH.Syntax
+
+
+-- | An error message produced by a code generation operation.
+type ErrMsg = Doc
+
+-- | The code generation monad, a combined reader-state-exception
+-- monad.
+newtype CodeGen e s a = CodeGen ((e, CodeGenEnv) -> (s, CodeGenState) -> IO ((s, CodeGenState), Either ErrMsg a))
+
+-- | 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,                    -- ^ 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 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
+               | RelocAbsolute -- ^ Absolute address
+   deriving (Show)
+
+-- | Relocation entry
+data Reloc = Reloc { offset :: Int, 
+             -- ^ offset in code block which needs relocation
+                     kind :: RelocKind,
+             -- ^ kind of relocation
+                     address :: FunPtr () 
+             -- ^ target address
+           }
+   deriving (Show)
+
+-- | Label
+data Label = Label Int String
+           deriving (Eq, Ord)
+
+unCg :: CodeGen e s a -> ((e, CodeGenEnv) -> (s, CodeGenState) -> IO ((s, CodeGenState), Either ErrMsg a))
+unCg (CodeGen a) = a
+
+instance Monad (CodeGen e s) where
+    return x = cgReturn x
+    fail err = cgFail err
+    m >>= k = cgBind m k
+
+cgReturn :: a -> CodeGen e s a
+cgReturn x = CodeGen (\_env state -> return (state, Right x))
+
+cgFail :: String -> CodeGen e s a
+cgFail err = CodeGen (\_env state -> return (state, Left (text err)))
+
+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
+                    (state', Left err) -> return (state', Left err)
+                    (state', Right v) -> unCg (k v) env state')
+
+-- | Abort code generation with the given error message.
+failCodeGen :: Doc -> CodeGen e s a
+failCodeGen d = CodeGen (\_env state -> return (state, Left d))
+
+instance MonadIO (CodeGen e s) where
+  liftIO st = CodeGen (\_env state -> do { r <- st; return (state, Right r) })
+
+emptyCodeGenState :: CodeGenState
+emptyCodeGenState = CodeGenState { buffer = undefined,
+                                   bufferList = [],
+                                   firstBuffer = undefined,
+                                   bufferOfs = 0,
+                                   bufferSize = 0,
+                                   relocEntries = [], 
+                                   nextLabel = 0,
+                                   definedLabels = Map.empty,
+                                   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,
+                                       customCodeBuffer = Nothing }
+
+defaultCodeBufferSize :: Int
+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.  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 (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 = buf,
+                                     bufferList = [],
+                                     firstBuffer = buf,
+                                     bufferSize = sze,
+                                     config = conf}
+       ((ustate', _), res) <- cg (uenv, env) (ustate, state)
+       return (ustate', res)
+
+-- | Check whether 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.  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
+       unless (bufferOfs state + needed <= bufferSize state)
+              (failCodeGen (text "code generation buffer overflow: needed additional" <+> 
+                            int needed <+> text "bytes (offset =" <+> 
+                            int (bufferOfs state) <> 
+                            text ", buffer size =" <+> 
+                            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.  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
+       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 (\ _ (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 (\ _ (ustate, state) -> 
+      return $ ((ustate, state), Right (bufferOfs state)))
+
+-- | Set the user state to the given value. 
+setState :: s -> CodeGen e s ()
+setState st =
+    CodeGen (\ _ (_, state) -> 
+      return $ ((st, state), Right ()))
+
+-- | Return the current user state.
+getState :: CodeGen e s s
+getState =
+    CodeGen (\ _ (ustate, state) -> 
+      return $ ((ustate, state), Right (ustate)))
+
+-- | Return the current user environment.
+getEnv :: CodeGen e s e
+getEnv =
+    CodeGen (\ (uenv, _) state -> 
+      return $ (state, Right uenv))
+
+-- | Set the environment to the given value and execute the given
+-- code generation in this environment.
+withEnv :: e -> CodeGen e s r -> CodeGen e s r
+withEnv e (CodeGen cg) =
+    CodeGen (\ (_, env) state ->
+      cg (e, env) state)
+
+-- | Set the user state to the given value. 
+setInternalState :: CodeGenState -> CodeGen e s ()
+setInternalState st =
+    CodeGen (\ _ (ustate, _) -> 
+      return $ ((ustate, st), Right ()))
+
+-- | Return the current user state.
+getInternalState :: CodeGen e s CodeGenState
+getInternalState =
+    CodeGen (\ _ (ustate, state) -> 
+      return $ ((ustate, state), Right (state)))
+
+-- | Return the pointer to the start of the code buffer.
+getBasePtr :: CodeGen e s (Ptr Word8)
+getBasePtr =
+    CodeGen (\ _ (ustate, state) -> 
+      return $ ((ustate, state), Right (buffer state)))
+
+-- | Return a list of all code buffers and their respective size 
+-- (i.e., actually used space for code, not allocated size).
+getCodeBufferList :: CodeGen e s [(Ptr Word8, Int)]
+getCodeBufferList = do st <- getInternalState
+                       return $ bufferList st ++ [(buffer st, bufferOfs st)]
+
+-- | Generate a new label to be used with the label operations
+-- 'emitFixup' and 'defineLabel'.
+newLabel :: CodeGen e s Label
+newLabel =
+    do state <- getInternalState
+       let lab = nextLabel state
+       setInternalState state{nextLabel = lab + 1}
+       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 =
+    do l <- newLabel
+       defineLabel l
+       return l
+
+-- | Emit a relocation entry for the given offset, relocation kind 
+-- and target address.
+emitRelocInfo :: Int -> RelocKind -> FunPtr a -> CodeGen e s ()
+emitRelocInfo ofs knd addr = 
+    do state <- getInternalState
+       setInternalState state{relocEntries =
+                              Reloc{offset = ofs, 
+                                    kind = knd,
+                                    address = castFunPtr addr} : 
+                              (relocEntries state)}
+
+-- | Emit a byte value to the code buffer. 
+emit8 :: Word8 -> CodeGen e s ()
+emit8 op = 
+    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.
+emit8At :: Int -> Word8 -> CodeGen e s ()
+emit8At pos op = 
+    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.
+peek8At :: Int -> CodeGen e s Word8
+peek8At pos =
+    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.
+emit32 :: Word32 -> CodeGen e s ()
+emit32 op = 
+    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.
+emit32At :: Int -> Word32 -> CodeGen e s ()
+emit32At pos op = 
+    CodeGen (\ _ (ustate, state) -> 
+      do let buf = buffer state
+         pokeByteOff buf pos op
+         return $ ((ustate, state), Right ()))
+
+-- | 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 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 ()
+       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 = knd}) =
+    do let diff = (labBuf `plusPtr` labOfs) `minusPtr` (buf `plusPtr` ofs)
+       liftIO $ case knd of
+                  Fixup8  -> pokeByteOff buf ofs (fromIntegral diff - 1 :: Word8)
+                  Fixup16 -> pokeByteOff buf ofs (fromIntegral diff - 2 :: Word16)
+                  Fixup32 -> pokeByteOff buf ofs (fromIntegral diff - 4 :: Word32)
+                  Fixup32Absolute -> pokeByteOff buf ofs (fromIntegral (ptrToWordPtr (labBuf `plusPtr` labOfs)) :: Word32)
+       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
+
+-- | Emit a fixup entry for the given label at the current offset in
+-- the code buffer (unless the label is already defined).
+-- The instruction at this offset will
+-- 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 knd = 
+    do state <- getInternalState 
+       let base = buffer state
+           ptr = bufferOfs state
+           fue = FixupEntry{fueBuffer = base,
+                            fueOfs = ptr + ofs,
+                            fueKind = knd}
+       case Map.lookup lab (definedLabels state) of
+         Just (labBuf, labOfs, _) -> performFixup labBuf labOfs fue
+         Nothing -> setInternalState state{pendingFixups = Map.insertWith (++) lab [fue] (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 name) = do
+  state <- getInternalState
+  case Map.lookup lab (definedLabels state) of
+    Just (labBuf, labOfs, _) -> return $ plusPtr labBuf labOfs
+    Nothing -> fail $ "Label " ++ show lab ++ "(" ++ name ++ ") not yet defined"
+
+
+-- | 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 (\ (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)]
+  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 allLabs = Map.toList (definedLabels state)
+                  labs = filter (\ (_, (buf, ofs, _)) -> fromIntegral (ptrToWordPtr (buf `plusPtr` ofs)) == addr) allLabs
+                  createLabel (l, (buf, ofs, name)) = Dis.PseudoInstruction addr
+                                                        (case name of
+                                                           "" ->
+                                                               "label " ++ show l ++ 
+                                                                " [" ++ 
+                                                                hex32 (fromIntegral (ptrToWordPtr (buf `plusPtr` ofs))) ++ 
+                                                                "]"
+                                                           _ -> name ++ ": [" ++ 
+                                                                  hex32 (fromIntegral (ptrToWordPtr (buf `plusPtr` ofs))) ++ 
+                                                                  "]")
+              return $ fmap createLabel labs ++ [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__
+
+callDecl :: String -> Q Type -> Q [Dec]
+callDecl ns qt =  do
+    t0 <- qt
+    let (tvars, cxt, t) = case t0 of
+                         ForallT vs c t' -> (vs, c, t')
+                         _ -> ([], [], t0)
+    let name = mkName ns
+    let funptr = AppT (ConT $ mkName "FunPtr") t
+    let ioresult = addIO t
+    let ty = AppT (AppT ArrowT funptr) ioresult
+    dynName <- newName "conv"
+    let dyn = ForeignD $ ImportF CCall Safe "dynamic" dynName $ ForallT tvars cxt ty
+    vs <- mkArgs t
+    cbody <- [| CodeGen (\env (ustate, state) ->
+                        do let code = firstBuffer state
+                           res <- liftIO $ $(do
+                                             c <- newName "c"
+                                             cast <- [|castPtrToFunPtr|]
+                                             let f = AppE (VarE dynName)
+                                                          (AppE cast
+                                                                (VarE c))
+                                             return $ LamE [VarP c] $ foldl AppE f $ map VarE vs
+                                            ) code
+                           return $ ((ustate, state), Right res))|]
+    let call = ValD (VarP name) (NormalB $ LamE (map VarP vs) cbody) []
+    return [ dyn, call ]
+
+mkArgs (AppT (AppT ArrowT _from) to) = do
+  v  <- newName "v"
+  vs <- mkArgs to
+  return $ v : vs
+mkArgs _ = return []
+
+addIO (AppT t@(AppT ArrowT _from) to) = AppT t $ addIO to
+addIO t = AppT (ConT $ mkName "IO") t
+
+#else
+
+-- | Declare a stub function to call the code buffer. Arguments are the name
+-- of the generated function, and the type the code buffer is supposed to have.
+-- The type argument can be given using the [t| ... |] notation of Template Haskell.
+-- Allowed types are the legal types for FFI functions.
+callDecl :: String -> Q Type -> Q [Dec]
+
+#endif
diff --git a/Harpy/X86Assembler.hs b/Harpy/X86Assembler.hs
new file mode 100644 (file)
index 0000000..1933ad5
--- /dev/null
@@ -0,0 +1,4168 @@
+{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances,FunctionalDependencies #-}
+--------------------------------------------------------------------------
+-- |
+-- 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 (
+   module Harpy.X86Assembler,
+   XMMReg(..),
+   ) 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, Ord)
+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
+    deriving (Eq, Ord)
+-}
+
+xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 :: XMMReg
+xmm0 = XMMReg 0
+xmm1 = XMMReg 1
+xmm2 = XMMReg 2
+xmm3 = XMMReg 3
+xmm4 = XMMReg 4
+xmm5 = XMMReg 5
+xmm6 = XMMReg 6
+xmm7 = XMMReg 7
+
+instance Show XMMReg where
+    show (XMMReg i) = "xmm" ++ show i
+
+-- 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 (Ptr a) where
+  cmp (Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_cmp dest (ptrToInt ptr)
+
+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 (Ptr a) where
+  cmp (Addr dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest (ptrToWord32 ptr)
+
+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) (Ptr a) where
+  cmp (Disp disp, Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp (ptrToWord32 ptr)
+
+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 (Ptr a) where
+  cmp (Ind (Reg32 dest)) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 (ptrToWord32 ptr)
+
+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 (Ptr a) where
+  mov (Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest (ptrToWord32 ptr)
+
+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 (Ptr a) where
+  mov (Addr dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest (ptrToWord32 ptr) 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) (Ptr a) where
+  mov (Disp disp, Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp (ptrToWord32 ptr) 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 (Ptr a) where
+  mov (Ind (Reg32 dest)) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 (ptrToWord32 ptr) 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) (Ptr a) where
+  mov (Reg32 base, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) (ptrToWord32 ptr) 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) (Ptr a) where
+  mov (Disp disp, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (ptrToWord32 ptr) 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) (Ptr a) where
+  mov (Disp disp, Reg32 5, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) (ptrToWord32 ptr) 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 counter
+
+class Loop a where
+  loop   :: a -> CodeGen e s ()
+  loope  :: a -> CodeGen e s ()
+  loopne :: a -> CodeGen e s ()
+
+instance Loop Word8 where
+    loop w   = ensureBufferSize x86_max_instruction_bytes >> x86_loop w
+    loope w  = ensureBufferSize x86_max_instruction_bytes >> x86_loope w
+    loopne w = ensureBufferSize x86_max_instruction_bytes >> x86_loopne w
+
+instance Loop Label where
+    loop l   = do ensureBufferSize x86_max_instruction_bytes >> x86_loop 0
+                  emitFixup l (-1) Fixup8
+    loope l  = do ensureBufferSize x86_max_instruction_bytes >> x86_loope 0
+                  emitFixup l (-1) Fixup8
+    loopne l = do ensureBufferSize x86_max_instruction_bytes >> x86_loopne 0
+                  emitFixup l (-1) Fixup8
+
+-- 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
+            
+instance Jmp (Ptr a) where
+  jmp ptr = ensureBufferSize x86_max_instruction_bytes >> x86_jump_pointer ptr 
+
+-- 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 (Ptr a) where
+  ja ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_a ptr 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 (Ptr a) where
+  jae ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ae ptr 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 (Ptr a) where
+  jb ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_b ptr 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 (Ptr a) where
+  jbe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_be ptr 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 (Ptr a) where
+  jc ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_c ptr 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 (Ptr a) where
+  je ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_e ptr 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 (Ptr a) where
+  jna ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_na ptr 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 (Ptr a) where
+  jnae ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nae ptr 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 (Ptr a) where
+  jnb ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nb ptr 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 (Ptr a) where
+  jnbe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nbe ptr 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 (Ptr a) where
+  jnc ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nc ptr 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 (Ptr a) where
+  jne ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ne ptr 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 (Ptr a) where
+  jnp ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_np ptr 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 (Ptr a) where
+  jnz ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nz ptr 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 (Ptr a) where
+  jp ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_p ptr 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 (Ptr a) where
+  jpe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_pe ptr 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 (Ptr a) where
+  jpo ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_po ptr 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 (Ptr a) where
+  jz ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_z ptr 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 (Ptr a) where
+  jg ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_gt ptr 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 (Ptr a) where
+  jge ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ge ptr 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 (Ptr a) where
+  jl ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_lt ptr 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 (Ptr a) where
+  jle ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_le ptr 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 (Ptr a) where
+  jng ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_le ptr 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 (Ptr a) where
+  jnge ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_lt ptr 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 (Ptr a) where
+  jnl ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ge ptr 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 (Ptr a) where
+  jnle ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_gt ptr 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 (Ptr a) where
+  jno ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_no ptr 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 (Ptr a) where
+  jns ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ns ptr 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 (Ptr a) where
+  jo ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_o ptr 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 (Ptr a) where
+  js ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_s ptr 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
+
+fsin = ensureBufferSize x86_max_instruction_bytes >> x86_fsin
+fcos = ensureBufferSize x86_max_instruction_bytes >> x86_fcos
+fptan = ensureBufferSize x86_max_instruction_bytes >> x86_fptan
+fpatan = ensureBufferSize x86_max_instruction_bytes >> x86_fpatan
+fabs = ensureBufferSize x86_max_instruction_bytes >> x86_fabs
+ftst = ensureBufferSize x86_max_instruction_bytes >> x86_ftst
+fxam = ensureBufferSize x86_max_instruction_bytes >> x86_fxam
+fprem = ensureBufferSize x86_max_instruction_bytes >> x86_fprem
+fprem1 = ensureBufferSize x86_max_instruction_bytes >> x86_fprem1
+frndint = ensureBufferSize x86_max_instruction_bytes >> x86_frndint
+fsqrt = ensureBufferSize x86_max_instruction_bytes >> x86_fsqrt
+
+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
+
+instance Fadd FPReg FPTopReg where
+    fadd (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fadd idx False
+
+
+class Faddp a b where
+    faddp :: a -> b -> CodeGen e s ()
+
+instance Faddp FPReg FPTopReg where
+    faddp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fadd idx True
+
+
+class Fiadd a b where
+    fiadd32 :: a -> b -> CodeGen e s ()
+    fiadd16 :: a -> b -> CodeGen e s ()
+
+instance Fiadd FPTopReg (Disp, Reg32) where
+    fiadd32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r d True
+    fiadd16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r d False
+
+instance Fiadd FPTopReg Ind where
+    fiadd32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r 0 True
+    fiadd16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r 0 False
+
+
+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
+
+instance Fsub FPReg FPTopReg where
+    fsub (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fsub idx False
+
+
+class Fsubp a b where
+    fsubp :: a -> b -> CodeGen e s ()
+
+instance Fsubp FPReg FPTopReg where
+    fsubp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fsub idx True
+
+
+class Fisub a b where
+    fisub32 :: a -> b -> CodeGen e s ()
+    fisub16 :: a -> b -> CodeGen e s ()
+
+instance Fisub FPTopReg (Disp, Reg32) where
+    fisub32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r d True
+    fisub16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r d False
+
+instance Fisub FPTopReg Ind where
+    fisub32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r 0 True
+    fisub16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r 0 False
+
+
+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
+
+instance Fmul FPReg FPTopReg where
+    fmul (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fmul idx False
+
+
+class Fmulp a b where
+    fmulp :: a -> b -> CodeGen e s ()
+
+instance Fmulp FPReg FPTopReg where
+    fmulp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fmul idx True
+
+
+class Fimul a b where
+    fimul32 :: a -> b -> CodeGen e s ()
+    fimul16 :: a -> b -> CodeGen e s ()
+
+instance Fimul FPTopReg (Disp, Reg32) where
+    fimul32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r d True
+    fimul16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r d False
+
+instance Fimul FPTopReg Ind where
+    fimul32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r 0 True
+    fimul16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r 0 False
+
+
+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
+
+instance Fdiv FPReg FPTopReg where
+    fdiv (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fdiv idx False
+
+
+class Fdivp a b where
+    fdivp :: a -> b -> CodeGen e s ()
+
+instance Fdivp FPReg FPTopReg where
+    fdivp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fdiv idx True
+
+
+class Fidiv a b where
+    fidiv32 :: a -> b -> CodeGen e s ()
+    fidiv16 :: a -> b -> CodeGen e s ()
+
+instance Fidiv FPTopReg (Disp, Reg32) where
+    fidiv32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r d True
+    fidiv16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r d False
+
+instance Fidiv FPTopReg Ind where
+    fidiv32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r 0 True
+    fidiv16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r 0 False
+
+
+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 FInt32
+
+instance Fild (Disp, Reg32) where 
+    fild (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r d FInt32
+
+instance Fild Ind where 
+    fild (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r 0 FInt32
+
+
+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 FInt32
+
+instance Fist Ind where 
+    fist (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r 0 FInt32
+
+
+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 FInt32
+
+instance Fistp (Disp, Reg32) where 
+    fistp (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r d FInt32
+
+instance Fistp Ind where 
+    fistp (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r 0 FInt32
+
+
+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 Movss a b where
+    movss :: a -> b -> CodeGen e s ()
+
+instance Movss XMMReg XMMReg where
+    movss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_reg x86_sse_ss xd xs
+
+instance Movss XMMReg Addr where
+    movss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_mem x86_sse_ss xd a
+
+instance Movss Addr XMMReg where
+    movss (Addr a) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_mem_reg x86_sse_ss a xd
+
+instance Movss XMMReg Ind where
+    movss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_ss xd r 0
+
+instance Movss Ind XMMReg where
+    movss (Ind (Reg32 r)) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_ss r 0 xd
+
+instance Movss XMMReg (Disp, Reg32) where
+    movss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_ss xd r d
+
+instance Movss (Disp, Reg32) XMMReg where
+    movss (Disp d, Reg32 r) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_ss r d xd
+
+
+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 Movups a b where
+    movups :: a -> b -> CodeGen e s ()
+
+instance Movups XMMReg XMMReg where
+    movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)
+
+instance Movups XMMReg Addr where
+    movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)
+
+instance Movups Addr XMMReg where
+    movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)
+
+instance Movups XMMReg Ind where
+    movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)
+
+instance Movups Ind XMMReg where
+    movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)
+
+instance Movups XMMReg (Disp, Reg32) where
+    movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)
+
+instance Movups (Disp, Reg32) XMMReg where
+    movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)
+
+
+class Movlps a b where
+    movlps :: a -> b -> CodeGen e s ()
+
+instance Movlps XMMReg XMMReg where
+    movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)
+
+instance Movlps XMMReg Addr where
+    movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)
+
+instance Movlps Addr XMMReg where
+    movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel xd)
+
+instance Movlps XMMReg Ind where
+    movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)
+
+instance Movlps Ind XMMReg where
+    movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel xd)
+
+instance Movlps XMMReg (Disp, Reg32) where
+    movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)
+
+instance Movlps (Disp, Reg32) XMMReg where
+    movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel 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
+
+
+class XMMLocation b => XMMLoc a b | a -> b where
+    xmmLocLowLevel :: a -> b
+
+instance XMMLoc XMMReg XMMReg where
+    xmmLocLowLevel = id
+
+instance XMMLoc Addr Mem where
+    xmmLocLowLevel (Addr a) = Mem a
+
+instance XMMLoc Ind MemBase where
+    xmmLocLowLevel (Ind (Reg32 r)) = MemBase r 0
+
+instance XMMLoc (Disp, Reg32) MemBase where
+    xmmLocLowLevel (Disp d, Reg32 r) = MemBase r d
+
+
+haddps :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()
+haddps (XMMReg dreg) reg =
+   x86_haddps dreg (xmmLocLowLevel reg)
+
+haddpd :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()
+haddpd (XMMReg dreg) reg =
+   x86_haddpd dreg (xmmLocLowLevel reg)
+
+
+shufps :: XMMLoc xmm a => XMMReg -> xmm -> Word8 -> CodeGen e s ()
+shufps (XMMReg dreg) reg src =
+   x86_shufps dreg (xmmLocLowLevel reg) src
+
+shufpd :: XMMLoc xmm a => XMMReg -> xmm -> Word8 -> CodeGen e s ()
+shufpd (XMMReg dreg) reg src =
+   x86_shufpd dreg (xmmLocLowLevel reg) src
+
+
+cvtdq2ps :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()
+cvtdq2ps (XMMReg dreg) reg =
+   x86_cvtdq2ps dreg (xmmLocLowLevel reg)
+
+cvttps2dq :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()
+cvttps2dq (XMMReg dreg) reg =
+   x86_cvttps2dq dreg (xmmLocLowLevel reg)
+
+
+class Prefetchnta a where
+    prefetchnta :: a -> CodeGen e s ()
+
+instance Prefetchnta Addr where
+    prefetchnta (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetchnta_mem a
+
+instance Prefetchnta (Disp, Reg32) where
+    prefetchnta (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetchnta_membase r d
+
+instance Prefetchnta Ind where
+    prefetchnta (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetchnta_regp r
+
+class Prefetch0 a where
+    prefetch0 :: a -> CodeGen e s ()
+
+instance Prefetch0 Addr where
+    prefetch0 (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch0_mem a
+
+instance Prefetch0 (Disp, Reg32) where
+    prefetch0 (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch0_membase r d
+
+instance Prefetch0 Ind where
+    prefetch0 (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch0_regp r
+
+class Prefetch1 a where
+    prefetch1 :: a -> CodeGen e s ()
+
+instance Prefetch1 Addr where
+    prefetch1 (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch1_mem a
+
+instance Prefetch1 (Disp, Reg32) where
+    prefetch1 (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch1_membase r d
+
+instance Prefetch1 Ind where
+    prefetch1 (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch1_regp r
+
+class Prefetch2 a where
+    prefetch2 :: a -> CodeGen e s ()
+
+instance Prefetch2 Addr where
+    prefetch2 (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch2_mem a
+
+instance Prefetch2 (Disp, Reg32) where
+    prefetch2 (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch2_membase r d
+
+instance Prefetch2 Ind where
+    prefetch2 (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch2_regp r
+
+
+ptrToWord32 :: Ptr a -> Word32
+ptrToWord32 = fromIntegral . ptrToIntPtr
+
+ptrToInt :: Ptr a -> Int
+ptrToInt = fromIntegral . ptrToIntPtr
diff --git a/Harpy/X86CGCombinators.hs b/Harpy/X86CGCombinators.hs
new file mode 100644 (file)
index 0000000..0da0afc
--- /dev/null
@@ -0,0 +1,266 @@
+--------------------------------------------------------------------------
+-- |
+-- Module      :  X86CodeGen
+-- Copyright   :  (c) 2006 Martin Grabmueller and Dirk Kleeblatt
+-- License     :  GPL
+-- 
+-- Maintainer  :  {magr,klee}@cs.tu-berlin.de
+-- Stability   :  quite experimental
+-- Portability :  portable (but generated code non-portable)
+--
+-- This module exports several combinators for writing loops,
+-- conditionals and function prolog\/epilog code.
+--
+-- Note: this module is under heavy development and the exported API
+-- is definitely not yet stable.
+--------------------------------------------------------------------------
+
+module Harpy.X86CGCombinators(
+  -- * Types
+  UserState(..),
+  UserEnv(..),
+  emptyUserEnv,
+  emptyUserState,
+  CtrlDest(..),
+  DataDest(..),
+  -- * Combinators
+  ifThenElse, 
+  doWhile,
+  continue,
+  continueBranch,
+  saveRegs,
+  function,
+  withDataDest,
+  withCtrlDest,
+  withDest,
+   ) 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 Reg32            -- ^ Store into specific register
+              | StackDest                -- ^ Push onto stack
+              | MemBaseDest Reg32 Word32 -- ^ Store at memory address
+              | Ignore                   -- ^ Throw result away.
+
+-- | Destination for control transfers
+data CtrlDest = FallThrough              -- ^ Go to next instruction
+              | Return                   -- ^ Return from current functio
+              | Goto Label               -- ^ Go to specific label
+              | Branch CtrlDest CtrlDest -- ^ Go to one of the given labels
+                                         -- depending on outcome of test
+
+-- | User state is used to maintain bitmask of registers currently in use.
+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 ())],
+                         dataDest :: DataDest,
+                         ctrlDest :: CtrlDest }
+
+emptyUserState :: UserState
+emptyUserState = UserState{}
+
+emptyUserEnv :: UserEnv
+emptyUserEnv = UserEnv{bindings = [], dataDest = Ignore,
+                       ctrlDest = Return}
+
+ifThenElse :: CodeGen UserEnv s r
+             -> CodeGen UserEnv s a
+             -> CodeGen UserEnv s a1
+             -> CodeGen UserEnv s ()
+ifThenElse condCg thenCg elseCg =
+    do env <- getEnv 
+       elseLabel <- newLabel
+       endLabel <- newLabel
+       withDest Ignore (Branch FallThrough (Goto elseLabel)) condCg
+       withCtrlDest (case ctrlDest env of 
+                       FallThrough -> Goto endLabel
+                       _ -> ctrlDest env)
+                    (thenCg >> continue)
+       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
+       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) = jmp l
+  cont (Branch _ _) = error "Branch in continue"
+  cont Return = x86_epilog 0
+
+
+continueBranch :: Int -> Bool -> CodeGen UserEnv s ()
+continueBranch cc isSigned =
+    do env <- getEnv
+       let Branch c1 c2 = ctrlDest env
+       cont cc isSigned c1 c2
+  where
+  cont cc isSigned (Goto l1) (Goto l2) =
+    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 x86_branch32 cc 0 isSigned
+       emitFixup l1 (-4) Fixup32
+  cont cc isSigned FallThrough (Goto l2) =
+    do x86_branch32 (negateCC cc) 0 isSigned
+       emitFixup l2 (-4) Fixup32
+  cont cc isSigned (Goto l1) Return =
+    do x86_branch32 cc 0 isSigned
+       emitFixup l1 (-4) Fixup32
+       withCtrlDest Return continue
+  cont cc isSigned Return (Goto l2) =
+    do x86_branch32 (negateCC cc) 0 isSigned
+       emitFixup l2 (-4) Fixup32
+       withCtrlDest Return continue
+  cont _ _ _ _ = error "unhandled case in continueBranch"
+
+reg sreg =
+    do env <- getEnv
+       reg' sreg (dataDest env)
+  where
+  reg' sreg (RegDest r) = 
+    do if sreg /= r 
+          then mov r sreg
+          else return ()
+  reg' sreg (StackDest) = 
+    do push sreg
+  reg' sreg (MemBaseDest r offset) = 
+    do mov (Disp offset, r) sreg
+  reg' sreg Ignore = return () 
+
+membase reg ofs =
+    do env <- getEnv
+       membase' reg ofs (dataDest env)
+  where
+  membase' reg ofs (RegDest r) = 
+    do mov r (Disp ofs, reg)
+  membase' reg ofs (StackDest) = 
+    do push (Disp ofs, reg)
+  membase' reg ofs (MemBaseDest r offset) = 
+    do push edi
+       mov edi (Disp ofs, reg)
+       mov (Disp offset, r) edi
+       pop edi
+  membase' reg ofs Ignore = return () 
+
+global ofs =
+    do env <- getEnv
+       global' ofs (dataDest env)
+  where
+  global' ofs (RegDest r) = 
+    do mov r (Addr ofs)
+  global' ofs (StackDest) = 
+    do push (Addr ofs)
+  global' ofs (MemBaseDest r offset) = 
+    do push edi
+       mov edi (Addr ofs)
+       mov (Disp offset, r) edi
+       pop edi
+  global' ofs Ignore = return ()
+
+immediate value =
+    do env <- getEnv
+       immediate' value (dataDest env)
+  where
+  immediate' value (RegDest r) = 
+    do mov r value
+  immediate' value (StackDest) = 
+    do x86_push_imm value
+  immediate' value (MemBaseDest r offset) = 
+    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 :: [Reg32] -> CodeGen UserEnv s r -> CodeGen UserEnv s ()
+saveRegs [] cg = cg >> return ()
+saveRegs regs cg =
+    do gen_push regs
+       withCtrlDest FallThrough cg
+       gen_pop regs
+       continue
+  where
+  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 ()
+loadVar name =
+    do UserEnv{bindings = assoc} <- getEnv
+       case lookup name assoc of
+         Just cg -> cg
+         Nothing -> failCodeGen (text ("undefined variable: " ++ name))
+
+-- | Set the data destinations to the given values while
+-- running the code generator.
+withDataDest :: DataDest -> CodeGen UserEnv s r -> CodeGen UserEnv s r
+withDataDest ddest cg =
+    do env <- getEnv
+       withEnv (env{dataDest = ddest}) cg
+
+-- | Set the control destinations to the given values while
+-- running the code generator.
+withCtrlDest :: CtrlDest -> CodeGen UserEnv s r -> CodeGen UserEnv s r
+withCtrlDest cdest cg =
+    do env <- getEnv
+       withEnv (env{ctrlDest = cdest}) cg
+
+-- | Set the data and control destinations to the given values while
+-- running the code generator.
+withDest :: DataDest -> CtrlDest -> CodeGen UserEnv s r -> CodeGen UserEnv s r
+withDest ddest cdest cg =
+    do env <- getEnv
+       withEnv (env{dataDest = ddest, ctrlDest = cdest}) cg
+
+-- | Emit the necessary function prolog and epilog code and invoke the
+-- given code generator for the code inbetween.
+function :: CodeGen UserEnv s r -> CodeGen UserEnv s r
+function cg =
+    do x86_prolog 0 0
+       withDest (RegDest eax) Return $ cg
diff --git a/Harpy/X86CodeGen.hs b/Harpy/X86CodeGen.hs
new file mode 100644 (file)
index 0000000..fe8946a
--- /dev/null
@@ -0,0 +1,2184 @@
+--------------------------------------------------------------------------
+-- |
+-- Module      :  X86CodeGen
+-- Copyright   :  (c) 2006 Martin Grabmueller and Dirk Kleeblatt
+-- License     :  GPL
+-- 
+-- Maintainer  :  {magr,klee}@cs.tu-berlin.de
+-- Stability   :  provisional
+-- Portability :  portable (but generated code non-portable)
+--
+-- Functions for generating x86 machine code instructions.  The
+-- functions make use of the code generation monad in module
+-- "Harpy.CodeGenMonad" for emitting binary code into a code buffer.
+--
+-- This module is very low-level, since there are different
+-- functions for different addressing modes.  A more convenient
+-- interface is provided in module "Harpy.X86Assembler", which uses
+-- the operand types to determine the correct addressing modes for
+-- all supported instructions.
+--
+-- Note: this file does not (yet) provide the complete x86
+-- instruction set, not even all user-mode instructions.  For some
+-- operations, some addressing modes are missing as well.
+--
+-- Copyright notice:
+--
+-- The information in this file is based on the header file
+-- x86-codegen.h from the mono distribution, which has the following
+-- copyright information:
+-- 
+-- @ 
+--  * x86-codegen.h: Macros for generating x86 code
+--  *
+--  * Authors:
+--  *   Paolo Molaro (lupus\@ximian.com)
+--  *   Intel Corporation (ORP Project)
+--  *   Sergey Chaban (serge\@wildwestsoftware.com)
+--  *   Dietmar Maurer (dietmar\@ximian.com)
+--  *   Patrik Torstensson
+--  * 
+--  * Copyright (C)  2000 Intel Corporation.  All rights reserved.
+--  * Copyright (C)  2001, 2002 Ximian, Inc.
+--  *
+-- @
+--------------------------------------------------------------------------
+
+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_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_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
+    -- | 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_code,
+    x86_call_imm,
+    -- ** Function prologue and epilogue
+    x86_prolog, x86_epilog, x86_enter, x86_leave,
+    x86_ret, x86_ret_imm,
+    -- ** Jump and branch
+    x86_jecxz, x86_branch, x86_branch_pointer, x86_branch32, x86_branch8,
+    x86_jump_membase, x86_jump_pointer, x86_jump_mem, x86_jump_reg, 
+    x86_jump32, x86_jump8, 
+    x86_loopne, x86_loope, x86_loop, 
+    -- ** Stack operations
+    x86_push_reg, x86_push_regp, x86_push_mem, x86_push_membase,
+    x86_push_imm, x86_push_imm_template, x86_push_memindex,
+    x86_pop_membase, x86_pop_mem, x86_pop_reg,
+    x86_popfd, x86_pushfd, x86_popad, x86_pushad,
+    -- ** Data movement
+    x86_mov_reg_reg, x86_mov_reg_imm, x86_mov_mem_imm, x86_mov_membase_imm,
+    x86_mov_memindex_imm, x86_mov_mem_reg, x86_mov_reg_mem, 
+    x86_mov_regp_reg, x86_mov_reg_regp, x86_mov_membase_reg,
+    x86_mov_reg_membase, x86_mov_memindex_reg, x86_mov_reg_memindex,
+    -- ** Arithmetic
+    x86_xadd_reg_reg, x86_xadd_mem_reg, x86_xadd_membase_reg, 
+    x86_inc_mem, x86_inc_membase, x86_inc_reg,
+    x86_dec_mem, x86_dec_membase, x86_dec_reg,
+    x86_not_mem, x86_not_membase, x86_not_reg,
+    x86_neg_mem, x86_neg_membase, x86_neg_reg, 
+    x86_alu_mem_imm, x86_alu_membase_imm, x86_alu_membase8_imm,
+    x86_alu_mem_reg, x86_alu_membase_reg, x86_alu_reg_reg,
+    x86_alu_reg8_reg8, x86_alu_reg_mem, x86_alu_reg_membase,
+    x86_mul_reg, x86_mul_mem, x86_mul_membase, 
+    x86_imul_reg_reg, x86_imul_reg_membase, x86_imul_reg_reg_imm,
+    x86_imul_reg_mem,
+    x86_imul_reg_mem_imm, x86_imul_reg_membase_imm,
+    x86_div_reg, x86_div_mem, x86_div_membase,
+    x86_test_reg_imm, x86_test_mem_imm, x86_test_membase_imm,
+    x86_test_reg_reg, x86_test_mem_reg, x86_test_membase_reg,
+    -- ** Exchange
+    x86_cmpxchg_reg_reg, x86_cmpxchg_mem_reg, x86_cmpxchg_membase_reg,
+    x86_xchg_reg_reg, x86_xchg_mem_reg, x86_xchg_membase_reg,
+    -- ** String operations
+    x86_stosb, x86_stosl, x86_stosd, x86_movsb, x86_movsl, x86_movsd,
+    -- ** Bitwise shift
+    x86_shift_reg_imm, x86_shift_mem_imm, x86_shift_membase_imm,
+    x86_shift_reg, x86_shift_mem, x86_shift_membase,
+    x86_shrd_reg, x86_shrd_reg_imm, x86_shld_reg, x86_shld_reg_imm,
+    -- ** Conditional move
+    x86_cmov_membase, x86_cmov_mem, x86_cmov_reg, 
+    -- ** Conditional set
+    x86_set_membase, x86_set_mem, x86_set_reg,
+    -- ** Address calculation
+    x86_lea_mem, x86_lea_membase, x86_lea_memindex,
+    -- ** 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,
+    FIntSize(..),
+    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,
+    x86_fincstp, x86_fdecstp,
+    -- ** 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,
+    XMMReg(XMMReg), Mem(Mem), MemBase(MemBase),
+    XMMLocation(xmm_location_emit),
+    x86_movss_to_reg, x86_movss_from_reg,
+    x86_movsd_to_reg, x86_movsd_from_reg,
+    x86_movlps_to_reg, x86_movlps_from_reg,
+    x86_movlpd_to_reg, x86_movlpd_from_reg,
+    x86_movups_to_reg, x86_movups_from_reg,
+    x86_movupd_to_reg, x86_movupd_from_reg,
+    x86_haddps, x86_haddpd,
+    x86_shufps, x86_shufpd,
+    x86_cvtdq2ps, x86_cvttps2dq,
+    -- ** Prefetch instructions
+    x86_prefetch0_mem, x86_prefetch1_mem, x86_prefetch2_mem, x86_prefetchnta_mem,
+    x86_prefetch0_membase, x86_prefetch1_membase, x86_prefetch2_membase, x86_prefetchnta_membase,
+    x86_prefetch0_regp, x86_prefetch1_regp, x86_prefetch2_regp, x86_prefetchnta_regp,
+    -- ** 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 Data.Word
+import Data.Bits
+
+import Foreign.Ptr
+
+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.
+
+x86_dword_size, x86_qword_size :: Int
+
+x86_dword_size = 4                    -- Number of bytes in doubleword
+x86_qword_size = 8                    -- Number of bytes in quadword
+
+x86_eax, x86_ecx, x86_edx, x86_ebx, x86_esp, x86_ebp, x86_esi,
+  x86_edi :: Word8
+x86_eax = 0
+x86_ecx = 1
+x86_edx = 2
+x86_ebx = 3
+x86_esp = 4
+x86_ebp = 5
+x86_esi = 6
+x86_edi = 7
+
+x86_cmp, x86_or, x86_adc, x86_sbb, x86_and, x86_sub, x86_xor, 
+  x86_add :: Word8
+x86_add = 0
+x86_or  = 1
+x86_adc = 2
+x86_sbb = 3
+x86_and = 4
+x86_sub = 5
+x86_xor = 6
+x86_cmp = 7
+
+x86_sar, x86_shld, x86_shlr, x86_rol, x86_ror, x86_rcl, x86_rcr,
+  x86_shl, x86_shr :: Word8
+
+x86_shld = 0
+x86_shlr = 1
+x86_rol  = 0
+x86_ror  = 1
+x86_rcl  = 2
+x86_rcr  = 3
+x86_shl  = 4
+x86_shr  = 5
+x86_sar  = 7
+
+x86_fadd, x86_fmul, x86_fcom, x86_fcomp, x86_fsub, x86_fsubr :: Word8
+x86_fdiv, x86_fdivr :: Word8
+
+x86_fadd  = 0
+x86_fmul  = 1
+x86_fcom  = 2
+x86_fcomp = 3
+x86_fsub  = 4
+x86_fsubr = 5
+x86_fdiv  = 6
+x86_fdivr = 7
+
+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
+x86_cc_a, x86_cc_nbe, x86_cc_ge, x86_cc_ae, x86_cc_nb, x86_cc_nc :: Int
+x86_cc_lz, x86_cc_s, x86_cc_gez, x86_cc_ns, x86_cc_p, x86_cc_pe :: Int
+x86_cc_np, x86_cc_po, x86_cc_o :: Int
+x86_cc_eq  = 0
+x86_cc_e   = 0
+x86_cc_z   = 0
+x86_cc_ne  = 1
+x86_cc_nz  = 1
+x86_cc_lt  = 2
+x86_cc_b   = 2
+x86_cc_c   = 2
+x86_cc_nae = 2
+x86_cc_le  = 3
+x86_cc_be  = 3
+x86_cc_na  = 3
+x86_cc_gt  = 4
+x86_cc_a   = 4
+x86_cc_nbe = 4
+x86_cc_ge  = 5
+x86_cc_ae  = 5
+x86_cc_nb  = 5
+x86_cc_nc  = 5
+x86_cc_lz  = 6
+x86_cc_s   = 6
+x86_cc_gez = 7
+x86_cc_ns  = 7
+x86_cc_p   = 8
+x86_cc_pe  = 8
+x86_cc_np  = 9
+x86_cc_po  = 9
+x86_cc_o   = 10
+x86_cc_no  = 11
+
+-- | FP status
+x86_fp_c0, x86_fp_c1, x86_fp_c2, x86_fp_c3, x86_fp_cc_mask :: Word32
+x86_fp_c0 = 0x100
+x86_fp_c1 = 0x200
+x86_fp_c2 = 0x400
+x86_fp_c3 = 0x4000
+x86_fp_cc_mask = 0x4500
+
+-- | FP control word
+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 :: Word32
+
+x86_fpcw_invopex_mask = 0x1
+x86_fpcw_denopex_mask = 0x2
+x86_fpcw_zerodiv_mask = 0x4
+x86_fpcw_ovfex_mask   = 0x8
+x86_fpcw_undfex_mask  = 0x10
+x86_fpcw_precex_mask  = 0x20
+x86_fpcw_precc_mask   = 0x300
+x86_fpcw_roundc_mask  = 0xc00
+
+-- | Values for precision control
+x86_fpcw_prec_single, x86_fpcw_prec_double, 
+ x86_fpcw_prec_extended :: Word32
+x86_fpcw_prec_single    = 0
+x86_fpcw_prec_double    = 0x200
+x86_fpcw_prec_extended  = 0x300
+
+-- | Values for rounding control
+x86_fpcw_round_nearest, x86_fpcw_round_down, x86_fpcw_round_up,
+ x86_fpcw_round_tozero :: Word32
+x86_fpcw_round_nearest  = 0
+x86_fpcw_round_down     = 0x400
+x86_fpcw_round_up       = 0x800
+x86_fpcw_round_tozero   = 0xc00
+
+-- | 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 :: Word8
+x86_lock_prefix = 0xf0
+x86_repnz_prefix = 0xf2
+x86_repz_prefix = 0xf3 
+x86_rep_prefix = 0xf3
+x86_cs_prefix = 0x2e
+x86_ss_prefix = 0x36
+x86_ds_prefix = 0x3e
+x86_es_prefix = 0x26
+x86_fs_prefix = 0x64
+x86_gs_prefix = 0x65
+x86_unlikely_prefix = 0x2e
+x86_likely_prefix = 0x3e
+x86_operand_prefix = 0x66
+x86_address_prefix = 0x67
+
+-- | Mapping from condition code to opcode (unsigned)
+x86_cc_unsigned_map :: [Word8]
+x86_cc_unsigned_map = [
+       0x74, -- eq  
+       0x75, -- ne  
+       0x72, -- lt  
+       0x76, -- le  
+       0x77, -- gt  
+       0x73, -- ge  
+       0x78, -- lz  
+       0x79, -- gez 
+       0x7a, -- p   
+       0x7b, -- np  
+       0x70, -- o  
+       0x71  -- no  
+ ]
+
+-- | Mapping from condition code to opcode (signed)
+x86_cc_signed_map :: [Word8]
+x86_cc_signed_map = [
+      0x74, -- eq  
+      0x75, -- ne  
+      0x7c, -- lt  
+      0x7e, -- le  
+      0x7f, -- gt  
+      0x7d, -- ge  
+      0x78, -- lz  
+      0x79, -- gez 
+      0x7a, -- p   
+      0x7b, -- np  
+      0x70, -- o  
+      0x71  -- no  
+ ]
+
+-- | 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  
+       (x86_cc_lt, x86_cc_ge), -- lt  
+       (x86_cc_le, x86_cc_gt), -- le  
+       (x86_cc_gt, x86_cc_le), -- gt  
+       (x86_cc_ge, x86_cc_lt), -- ge  
+       (x86_cc_lz, x86_cc_gez), -- lz  
+       (x86_cc_gez, x86_cc_lz), -- gez 
+       (x86_cc_p, x86_cc_np), -- p   
+       (x86_cc_np, x86_cc_p), -- np  
+       (x86_cc_o, x86_cc_no), -- o  
+       (x86_cc_no, x86_cc_o)  -- no  
+ ]
+
+-- | Invert a condition code.
+negateCC :: Int -> Int
+negateCC cc =
+    case lookup cc x86_cc_negate of
+      Just cc' -> cc'
+      Nothing -> error ("unhandled case in negateCC" ++ show cc)
+
+-- | Used to encode the fact that no base register is used in an
+-- instruction.
+x86_nobasereg :: Word8
+x86_nobasereg = (-1)
+
+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))
+x86_edi_mask = (1 `shiftL` (fromIntegral x86_edi))
+x86_ebx_mask = (1 `shiftL` (fromIntegral x86_ebx))
+x86_ebp_mask = (1 `shiftL` (fromIntegral x86_ebp))
+x86_eax_mask = (1 `shiftL` (fromIntegral x86_eax))
+x86_ecx_mask = (1 `shiftL` (fromIntegral x86_ecx))
+x86_edx_mask = (1 `shiftL` (fromIntegral x86_edx))
+
+-- | Bitvector mask for callee-saved registers
+x86_callee_regs :: Int
+x86_callee_regs = ((1 `shiftL` (fromIntegral x86_eax)) .|. 
+           (1 `shiftL` (fromIntegral x86_ecx)) .|. 
+           (1 `shiftL` (fromIntegral x86_edx)))
+
+-- | Bitvector mask for caller-saved registers
+x86_caller_regs :: Int
+x86_caller_regs = ((1 `shiftL` (fromIntegral x86_ebx)) .|.
+           (1 `shiftL` (fromIntegral x86_ebp)) .|. 
+           (1 `shiftL` (fromIntegral x86_esi)) .|. 
+           (1 `shiftL` (fromIntegral x86_edi)))
+
+-- | Bitvector mask for byte-adressable registers
+x86_byte_regs :: Int
+x86_byte_regs =  ((1 `shiftL` (fromIntegral x86_eax)) .|.
+          (1 `shiftL` (fromIntegral x86_ecx)) .|. 
+          (1 `shiftL` (fromIntegral x86_edx)) .|. 
+          (1 `shiftL` (fromIntegral x86_ebx)))
+
+-- | Returns true when the given register is caller-saved.
+x86_is_scratch :: Int -> Bool
+x86_is_scratch reg = (x86_caller_regs .&. (1 `shiftL` (reg))) /= 0
+
+-- | Returns true when the given register is caller-saved.
+x86_is_callee :: Int -> Bool
+
+x86_is_callee reg =  (x86_callee_regs .&. (1 `shiftL` (reg))) /= 0
+
+-- | Returns true when the given register is byte-addressable.
+x86_is_byte_reg :: (Num a, Ord a) => a -> Bool
+x86_is_byte_reg reg = ((reg) < 4)
+
+
+
+-- useful building blocks
+
+
+--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)))
+
+-- | Emit a 32-bit constant to the instruction stream.
+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 :: 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 ()
+x86_imm_emit16 imm =
+    let b0 = (imm .&. 0xff)
+        b1 = ((imm `shiftR` 8) .&. 0xff)
+    in do emit8 (fromIntegral b0)
+          emit8 (fromIntegral b1)
+
+-- | Emit a 8-bit constant to the instruction stream.
+x86_imm_emit8 :: Word8 -> CodeGen e s ()
+x86_imm_emit8 imm = 
+  emit8 (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 :: 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)
+
+-- | Emit a register-indirect address encoding.
+x86_regp_emit :: Word8 -> Word8 -> CodeGen e s ()
+x86_regp_emit r regno = x86_address_byte 0 r regno
+
+-- | Emit a memory+displacement address encoding.
+x86_mem_emit :: Word8 -> Word32 -> CodeGen e s ()
+x86_mem_emit r disp = do x86_address_byte 0 r 5
+                         x86_imm_emit32 disp
+
+-- | Emit a mem+base address encoding
+x86_membase_emit :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_membase_emit r basereg disp =
+    if basereg == x86_esp
+       then if disp == 0
+               then do x86_address_byte 0 r x86_esp 
+                       x86_address_byte 0 x86_esp x86_esp
+               else if x86_is_imm8 disp
+                       then do x86_address_byte 1 r x86_esp
+                               x86_address_byte 0 x86_esp x86_esp
+                               x86_imm_emit8 (fromIntegral disp)
+                       else do x86_address_byte 2 r x86_esp
+                               x86_address_byte 0 x86_esp x86_esp
+                               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 :: 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 :: 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 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 shft indexreg (fromIntegral basereg)
+                else if x86_is_imm8 disp
+                        then do x86_address_byte 1 r 4
+                                x86_address_byte shft indexreg 
+                                             (fromIntegral basereg)
+                                x86_imm_emit8 (fromIntegral disp)
+                        else do x86_address_byte 2 r 4
+                                x86_address_byte shft indexreg 5
+                                x86_imm_emit32 disp
+
+{-
+x86_jmp_ofs_size ins =
+  do instr <- peek8At ins
+     case instr of
+       0xe8 -> return 1
+       0xe9 -> return 1
+       0x0f ->
+         do atPos <- peek8At (ins + 1)
+            if (atPos < 0x70 || atPos > 0x8f)
+               then failCodeGen (PP.text "Wrong Opcode")
+               else return 1
+       _ -> return 0
+-}
+
+-- target is the position in the code where to jump to:
+
+-- target = code;
+-- .. output loop code...
+-- x86_mov_reg_imm (code, X86_EAX, 0);
+-- loop = code;
+-- x86_loop (code, -1);
+-- ... finish method
+
+-- patch displacement
+
+-- x86_patch (loop, target);
+
+-- ins should point at the start of the instruction that encodes a target.
+-- 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
+          instr <- peek8At ins
+          let disp = target - (if instr == 0x0f then pos + 1 else pos)
+          if size == 1
+             then x86_imm_emit32_at pos (fromIntegral (disp - 4))
+             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 ()
+x86_breakpoint = emit8 0xcc
+x86_cld = emit8 0xfc
+x86_stosb = emit8 0xaa
+x86_stosl = emit8 0xab
+x86_stosd = x86_stosl
+x86_movsb = emit8 0xa4
+x86_movsl = emit8 0xa5
+x86_movsd = x86_movsl
+
+x86_prefix :: Word8 -> CodeGen s e ()
+x86_prefix p = emit8 p
+
+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 =
+    do x86_xchg size ; x86_mem_emit reg mem
+x86_xchg_membase_reg basereg disp reg size =
+    do x86_xchg size ; x86_membase_emit reg basereg disp
+
+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 =
+    x86_xadd size >> x86_membase_emit reg basereg disp
+
+x86_inc_mem mem = emit8 0xff >> x86_mem_emit 0 mem
+x86_inc_membase basereg disp = emit8 0xff >> x86_membase_emit 0 basereg disp
+x86_inc_reg reg = emit8 (0x40 + reg)
+
+x86_dec_mem mem = emit8 0xff >> x86_mem_emit 1 mem
+x86_dec_membase basereg disp = emit8 0xff >> x86_membase_emit 1 basereg disp
+x86_dec_reg reg = emit8 (0x48 + reg)
+
+x86_not_mem mem = emit8 0xf7 >> x86_mem_emit 2 mem
+x86_not_membase basereg disp = emit8 0xf7 >> x86_membase_emit 2 basereg disp
+x86_not_reg reg = emit8 0xf7 >> x86_reg_emit 2 reg
+
+x86_neg_mem mem = emit8 0xf7 >> x86_mem_emit 3 mem
+x86_neg_membase basereg disp = emit8 0xf7 >> x86_membase_emit 3 basereg disp
+x86_neg_reg reg = emit8 0xf7 >> x86_reg_emit 3 reg
+
+x86_nop :: CodeGen s e ()
+x86_nop = emit8 0x90
+
+x86_alu_reg_imm :: Word8 -> Word8 -> Int -> CodeGen e s ()
+x86_alu_reg_imm opc reg imm =
+    do if reg == x86_eax
+          then emit8 (fromIntegral (((opc) `shiftL` 3) + 5)) >> x86_imm_emit32 (fromIntegral imm)
+          else if x86_is_imm8 imm
+                  then do emit8 0x83
+                          x86_reg_emit (fromIntegral opc) (fromIntegral reg)
+                          x86_imm_emit8 (fromIntegral imm)
+                  else do emit8 0x81
+                          x86_reg_emit (fromIntegral opc) (fromIntegral reg)
+                          x86_imm_emit32 (fromIntegral imm)
+
+
+x86_alu_mem_imm opc mem imm =
+    if x86_is_imm8 imm
+       then do emit8 0x83
+               x86_mem_emit opc mem
+               x86_imm_emit8 (fromIntegral imm)
+       else do emit8 0x81
+               x86_mem_emit opc mem
+               x86_imm_emit32 imm
+
+
+x86_alu_membase_imm opc basereg disp imm =
+    if x86_is_imm8 imm
+       then do emit8 0x83
+               x86_membase_emit opc basereg disp
+               x86_imm_emit8 (fromIntegral imm)
+       else do emit8 0x81
+               x86_membase_emit opc basereg disp
+               x86_imm_emit32 imm
+x86_alu_membase8_imm opc basereg disp imm =
+    do emit8 0x80
+       x86_membase_emit opc basereg disp
+       x86_imm_emit8 imm
+x86_alu_mem_reg opc mem reg =
+        do emit8 ((opc `shiftL` 3) + 1)
+           x86_mem_emit reg mem
+x86_alu_membase_reg opc basereg disp reg =
+    do emit8 ((opc `shiftL` 3) + 1)
+       x86_membase_emit reg basereg disp
+x86_alu_reg_reg opc dreg reg =
+    do emit8 ((opc `shiftL` 3) + 3)
+       x86_reg_emit dreg reg
+
+-- @x86_alu_reg8_reg8:
+-- Supports ALU operations between two 8-bit registers.
+-- dreg := dreg opc reg
+-- X86_Reg_No enum is used to specify the registers.
+-- Additionally is_*_h flags are used to specify what part
+-- of a given 32-bit register is used - high (TRUE) or low (FALSE).
+-- For example: dreg = X86_EAX, is_dreg_h = TRUE -> use AH
+
+x86_alu_reg8_reg8 opc dreg reg is_dreg_h is_reg_h =
+    do emit8 ((opc `shiftL` 3) + 2)
+       x86_reg8_emit dreg reg is_dreg_h is_reg_h
+x86_alu_reg_mem opc reg mem =
+    do emit8 ((opc `shiftL` 3) + 3)
+       x86_mem_emit reg mem
+x86_alu_reg_membase opc reg basereg disp =
+    do emit8 ((opc `shiftL` 3) + 3)
+       x86_membase_emit reg basereg disp
+
+x86_test_reg_imm reg imm =
+    do if reg == x86_eax
+          then emit8 0xa9
+          else do emit8 0xf7 ; x86_reg_emit 0 (fromIntegral reg)
+       x86_imm_emit32 imm
+x86_test_mem_imm mem imm =
+    do emit8 0xf7 ; x86_mem_emit 0 mem ; x86_imm_emit32 imm
+x86_test_membase_imm basereg disp imm =
+    do emit8 0xf7 ; x86_membase_emit 0 basereg disp ; x86_imm_emit32 imm
+x86_test_reg_reg dreg reg = do emit8 0x85 ; x86_reg_emit reg dreg
+x86_test_mem_reg mem reg =
+    do emit8 0x85 ; x86_mem_emit reg mem
+x86_test_membase_reg basereg disp reg =
+    do emit8 0x85 ; x86_membase_emit reg basereg disp
+
+x86_shift_reg_imm opc reg imm =
+    if imm == 1
+       then do emit8 0xd1 ; x86_reg_emit opc reg
+       else do emit8 0xc1
+               x86_reg_emit opc reg
+               x86_imm_emit8 imm
+x86_shift_mem_imm opc mem imm =
+    if imm == 1
+       then do emit8 0xd1 ; x86_mem_emit opc mem
+       else do emit8 0xc1
+               x86_mem_emit opc mem
+               x86_imm_emit8 imm
+x86_shift_membase_imm opc basereg disp imm =
+    if imm == 1
+       then do emit8 0xd1 ; x86_membase_emit opc basereg disp
+       else do emit8 0xc1
+               x86_membase_emit opc basereg disp
+               x86_imm_emit8 imm
+x86_shift_reg opc reg =
+    emit8 0xd3 >> x86_reg_emit opc reg
+x86_shift_mem opc mem =
+    emit8 0xd3 >> x86_mem_emit opc mem
+x86_shift_membase opc basereg disp =
+    emit8 0xd3 >> x86_membase_emit opc basereg disp
+
+-- Multi op shift missing.
+
+x86_shrd_reg dreg reg =                     
+    emit8 0x0f >> emit8 0xad >> x86_reg_emit reg dreg 
+x86_shrd_reg_imm dreg reg shamt =
+    emit8 0x0f >> emit8 0xac >> x86_reg_emit reg dreg >> x86_imm_emit8 shamt
+x86_shld_reg dreg reg =                     
+    emit8 0x0f >> emit8 0xa5 >> x86_reg_emit reg dreg 
+x86_shld_reg_imm dreg reg shamt =
+    emit8 0x0f >> emit8 0xa4 >> x86_reg_emit reg dreg >>x86_imm_emit8 shamt
+
+-- EDX:EAX = EAX * rm
+
+x86_mul_reg :: Word8 -> Bool -> CodeGen e s ()
+x86_mul_reg reg is_signed =   
+    emit8 0xf7 >> x86_reg_emit (4 + (if is_signed then 1 else 0)) reg 
+
+x86_mul_mem :: Word32 -> Bool -> CodeGen e s ()
+x86_mul_mem mem is_signed =   
+    emit8 0xf7 >> x86_mem_emit (4 + (if is_signed then 1 else 0)) mem 
+
+x86_mul_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
+x86_mul_membase basereg disp is_signed =      
+    do emit8 0xf7
+       x86_membase_emit (4 + (if is_signed then 1 else 0)) basereg disp
+
+-- r *= rm
+
+x86_imul_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
+x86_imul_reg_reg dreg reg =   
+    emit8 0x0f >> emit8 0xaf >> x86_reg_emit dreg reg 
+
+x86_imul_reg_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_imul_reg_mem reg mem =    
+    emit8 0x0f >> emit8 0xaf >> x86_mem_emit reg mem  
+
+x86_imul_reg_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_imul_reg_membase reg basereg disp =       
+    emit8 0x0f >> emit8 0xaf >> x86_membase_emit reg basereg disp     
+
+-- dreg = rm * imm
+
+x86_imul_reg_reg_imm :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_imul_reg_reg_imm dreg reg imm =   
+    if x86_is_imm8 imm
+       then emit8 0x6b >> x86_reg_emit dreg reg >> 
+              x86_imm_emit8 (fromIntegral imm)        
+       else emit8 0x69 >> x86_reg_emit dreg reg >> x86_imm_emit32 imm 
+
+x86_imul_reg_mem_imm :: Word8 -> Word32 -> Word32 -> CodeGen e s ()
+x86_imul_reg_mem_imm reg mem imm =    
+    if x86_is_imm8 imm
+       then emit8 0x6b >> x86_mem_emit reg mem >> 
+              x86_imm_emit8 (fromIntegral imm)        
+       else emit8 0x69 >> x86_reg_emit reg (fromIntegral mem) >> 
+              x86_imm_emit32 imm      
+
+x86_imul_reg_membase_imm :: Word8 -> Word8 -> Word32 -> Word32 -> CodeGen e s ()
+x86_imul_reg_membase_imm reg basereg disp imm =       
+    if x86_is_imm8 imm
+       then emit8 0x6b >> x86_membase_emit reg basereg disp >> 
+            x86_imm_emit8 (fromIntegral imm)
+       else do emit8 0x69
+               x86_membase_emit reg basereg disp      
+               x86_imm_emit32 imm     
+
+-- divide EDX:EAX by rm;
+-- eax = quotient, edx = remainder
+
+x86_div_reg :: Word8 -> Bool -> CodeGen e s ()
+x86_div_reg reg is_signed =   
+    emit8 0xf7 >> x86_reg_emit (6 + (if is_signed then 1 else 0)) reg 
+x86_div_mem :: Word32 -> Bool -> CodeGen e s ()
+x86_div_mem mem is_signed =   
+    emit8 0xf7 >> x86_mem_emit (6 + (if is_signed then 1 else 0)) mem 
+
+x86_div_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
+x86_div_membase basereg disp is_signed =      
+    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
+         2 -> emit8 0x66 >> emit8 0x89
+         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
+         2 -> emit8 0x66 >> emit8 0x8b
+         4 -> emit8 0x8b
+         _ -> failCodeGen (PP.text "invalid operand size")
+       
+x86_mov_mem_reg :: (Num t) => Word32 -> Word8 -> t -> CodeGen e s ()
+x86_mov_mem_reg mem reg size =        
+    do x86_mov1 size ; x86_mem_emit reg mem   
+
+x86_mov_regp_reg :: (Num t) => Word8 -> Word8 -> t -> CodeGen e s ()
+x86_mov_regp_reg regp reg size =      
+    do x86_mov1 size ; x86_regp_emit reg regp
+
+x86_mov_reg_regp :: (Num t) => Word8 -> Word8 -> t -> CodeGen e s ()
+x86_mov_reg_regp reg regp size =      
+    do x86_mov2 size ; x86_regp_emit reg regp
+
+x86_mov_membase_reg :: (Num t) => Word8 -> Word32 -> Word8 -> t -> CodeGen e s ()
+x86_mov_membase_reg basereg disp reg size =   
+    do x86_mov1 size ; x86_membase_emit reg basereg disp      
+
+x86_mov_memindex_reg :: (Num t) => Word8 -> Word32 -> Word8 -> Word8 -> Word8 -> t -> CodeGen e s ()
+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 :: (Num t) => Word8 -> Word8 -> t -> CodeGen e s ()
+x86_mov_reg_reg dreg reg size =       
+    do x86_mov2 size
+       x86_reg_emit dreg reg  
+
+x86_mov_reg_mem :: (Num t) => Word8 -> Word32 -> t -> CodeGen e s ()
+x86_mov_reg_mem reg mem size =        
+    do x86_mov2 size
+       x86_mem_emit reg mem   
+
+x86_mov_reg_membase :: (Num t) => Word8 -> Word8 -> Word32 -> t -> CodeGen e s ()
+x86_mov_reg_membase reg basereg disp size =
+    do x86_mov2 size
+       x86_membase_emit reg basereg disp      
+
+x86_mov_reg_memindex :: (Num t) => Word8 -> Word8 -> Word32 -> Word8 -> Word8 -> t -> CodeGen e s ()
+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 shft size =   
+    do x86_mov2 size
+       x86_memindex_emit reg basereg disp indexreg  shft
+
+x86_mov_reg_imm :: Word8 -> Word32 -> CodeGen e s ()
+x86_mov_reg_imm reg imm =     
+    emit8 (0xb8 + reg) >> x86_imm_emit32 imm  
+
+x86_mov_mem_imm :: (Num a) => Word32 -> Word32 -> a -> CodeGen e s ()
+x86_mov_mem_imm mem imm size =        
+    if size == 1
+       then do emit8 0xc6;    
+               x86_mem_emit 0 mem     
+               x86_imm_emit8 (fromIntegral imm)       
+       else if size == 2
+               then do emit8 0x66
+                       emit8 0xc7
+                       x86_mem_emit 0 mem     
+                       x86_imm_emit16 (fromIntegral imm)      
+               else do emit8 0xc7
+                       x86_mem_emit 0 mem     
+                       x86_imm_emit32 imm     
+
+x86_mov_membase_imm :: (Num a) => Word8 -> Word32 -> Word32 -> a -> CodeGen e s ()
+x86_mov_membase_imm basereg disp imm size =   
+    if size == 1
+       then do emit8 0xc6     
+               x86_membase_emit 0 basereg disp
+               x86_imm_emit8 (fromIntegral imm)
+       else if size == 2
+               then do emit8 0x66     
+                       emit8 0xc7
+                       x86_membase_emit 0 basereg disp        
+                       x86_imm_emit16 (fromIntegral imm)      
+               else do emit8 0xc7     
+                       x86_membase_emit 0 basereg disp        
+                       x86_imm_emit32 imm     
+
+x86_mov_memindex_imm :: (Num a) => Word8 -> Word32 -> Word8 -> Word8 -> Word32 -> a -> CodeGen e s ()
+x86_mov_memindex_imm basereg disp indexreg shft imm size =   
+    if size == 1
+    then do emit8 0xc6        
+            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  shft     
+                 x86_imm_emit16 (fromIntegral imm)    
+         else do emit8 0xc7   
+                 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 :: 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) +
+                     (if is_half then 0x1 else 0)
+            emit8 0x0f
+            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 :: 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 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 :: Word8 -> Word8 -> Bool -> CodeGen e s ()
+x86_fp_op_reg opc index pop_stack =   
+    do let  opcMap = [ 0, 1, 2, 3, 5, 4, 7, 6, 8]        
+       emit8 (if pop_stack then 0xde else 0xdc)       
+       emit8 (0xc0 + ((opcMap !! fromIntegral opc) `shiftL` 3) + (index .&. 0x07))
+
+
+-- @x86_fp_int_op_membase
+-- Supports FPU operations between ST(0) and integer operand in memory.
+-- Operation encoded using X86_FP_Opcode enum.
+-- 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))
+
+data FIntSize = FInt16 | FInt32 | FInt64
+
+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 -> FIntSize -> CodeGen e s ()
+x86_fild mem size =
+    case size of
+       FInt16 -> emit8 0xdf >> x86_mem_emit 0 mem
+       FInt32 -> emit8 0xdb >> x86_mem_emit 0 mem
+       FInt64 -> emit8 0xdf >> x86_mem_emit 5 mem
+x86_fild_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
+x86_fild_membase basereg disp size =
+    case size of
+       FInt16 -> emit8 0xdb >> x86_membase_emit 0 basereg disp     
+       FInt32 -> emit8 0xdb >> x86_membase_emit 0 basereg disp     
+       FInt64 -> emit8 0xdf >> x86_membase_emit 5 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 -> FIntSize -> CodeGen e s ()
+x86_fist_pop mem size =
+    case size of
+       FInt16 -> emit8 0xdf >> x86_mem_emit 3 mem
+       FInt32 -> emit8 0xdb >> x86_mem_emit 3 mem
+       FInt64 -> emit8 0xdf >> x86_mem_emit 7 mem
+x86_fist_pop_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
+x86_fist_pop_membase basereg disp size =
+    case size of
+       FInt16 -> emit8 0xdf >> x86_membase_emit 3 basereg disp
+       FInt32 -> emit8 0xdb >> x86_membase_emit 3 basereg disp
+       FInt64 -> emit8 0xdf >> x86_membase_emit 7 basereg disp
+x86_fstsw :: CodeGen e s ()
+x86_fstsw = emit8 0x9b >> emit8 0xdf >> emit8 0xe0
+
+-- @x86_fist_membase
+-- Converts content of ST(0) to integer and stores it at memory location
+-- addressed by [basereg + disp].
+-- size specifies whether destination is int32 or int16.
+
+x86_fist_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
+x86_fist_membase basereg disp size =        
+    case size of
+       FInt16 -> emit8 0xdf >> x86_membase_emit 2 basereg disp     
+       FInt32 -> emit8 0xdb >> x86_membase_emit 2 basereg disp     
+       FInt64 -> error "fist does not support 64 bit access"
+
+x86_fincstp :: CodeGen e s ()
+x86_fincstp = emit8 0xd9 >> emit8 0xf7 
+
+x86_fdecstp :: CodeGen e s ()
+x86_fdecstp = emit8 0xd9 >> emit8 0xf6 
+
+-- 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 :: 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)
+    else emit8 0x68 >> x86_imm_emit32 imm
+
+-- 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     
+
+x86_jump_pointer :: Ptr a -> CodeGen e s ()
+x86_jump_pointer target =
+    do inst <- getCodeOffset
+       base <- getBasePtr
+       let ptr = base `plusPtr` inst
+       x86_jump32 (fromIntegral (target `minusPtr` ptr - 5))
+
+-- 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   
+          then emit8 ((x86_cc_signed_map !! cond) + 0x10)     
+          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_pointer :: Int -> Ptr a -> Bool -> CodeGen e s ()
+x86_branch_pointer cond target is_signed =
+    do inst <- getCodeOffset
+       base <- getBasePtr
+       let ptr = base `plusPtr` inst
+       x86_branch32 cond (fromIntegral (target `minusPtr` ptr - 5)) 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
+          then emit8 ((x86_cc_signed_map !! cond) + 0x20)     
+          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
+          then emit8 ((x86_cc_signed_map !! cond) + 0x20)     
+          else emit8 ((x86_cc_unsigned_map !! cond) + 0x20)   
+       x86_membase_emit 0 basereg disp        
+
+-- Call instructions.
+
+x86_call_imm :: Word32 -> CodeGen s e ()
+x86_call_imm disp = emit8 0xe8 >> x86_imm_emit32 disp 
+
+x86_call_reg :: Word8 -> CodeGen s e ()
+x86_call_reg reg = emit8 0xff >> x86_reg_emit 2 reg
+
+x86_call_mem :: Word32 -> CodeGen s e ()
+x86_call_mem mem = emit8 0xff >> x86_mem_emit 2 mem   
+
+x86_call_membase :: Word8 -> Word32 -> CodeGen s e ()
+x86_call_membase basereg disp =       
+    emit8 0xff >> x86_membase_emit 2 basereg disp     
+
+x86_call_code :: Int -> CodeGen s e ()
+x86_call_code target =        
+    do inst <- getCodeOffset
+       let  _x86_offset = (target - inst - 5)
+       x86_call_imm (fromIntegral _x86_offset)
+
+x86_call_hs :: FunPtr a -> CodeGen e s ()
+x86_call_hs fptr = do { offset <- getCodeOffset
+                      ; base <- getBasePtr
+                      ; emitRelocInfo (offset + 1)
+                          RelocPCRel fptr
+                      ; x86_call_imm $ (fromIntegral (minusPtr (castFunPtrToPtr fptr) (plusPtr base offset) - 5))
+                      }
+
+-- RET instruction.
+
+x86_ret :: CodeGen s e ()
+x86_ret = emit8 0xc3
+
+x86_ret_imm :: Word16 -> CodeGen s e ()
+x86_ret_imm imm =     
+    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      
+
+-- Note: definition for ENTER instruction is not complete.  The counter
+-- for the display setup is set to 0.
+
+x86_enter :: Word16 -> CodeGen s e ()
+x86_enter framesize = emit8 0xc8 >> x86_imm_emit16 framesize >> emit8 0
+
+x86_leave :: CodeGen s e ()
+x86_leave = emit8 0xc9
+
+x86_sahf :: CodeGen s e ()
+x86_sahf  = emit8 0x9e
+
+-- Trigonometric floating point functions
+
+x86_fsin, x86_fcos, x86_fabs, x86_ftst, x86_fxam, x86_fpatan, 
+ x86_fprem, x86_fprem1, x86_frndint, x86_fsqrt, x86_fptan :: CodeGen s e ()
+x86_fsin    = emit8 0xd9 >> emit8 0xfe
+x86_fcos    = emit8 0xd9 >> emit8 0xff
+x86_fabs    = emit8 0xd9 >> emit8 0xe1
+x86_ftst    = emit8 0xd9 >> emit8 0xe4
+x86_fxam    = emit8 0xd9 >> emit8 0xe5
+x86_fpatan  = emit8 0xd9 >> emit8 0xf3
+x86_fprem   = emit8 0xd9 >> emit8 0xf8
+x86_fprem1  = emit8 0xd9 >> emit8 0xf5
+x86_frndint = emit8 0xd9 >> emit8 0xfc
+x86_fsqrt   = emit8 0xd9 >> emit8 0xfa
+x86_fptan   = emit8 0xd9 >> emit8 0xf2
+
+-- 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
+      2 -> emit8 0x8b >> emit8  0xc0
+      3 -> emit8 0x8d >> emit8 0x6d >> emit8 0x00
+      4 -> emit8 0x8d >> emit8 0x64 >> emit8 0x24 >> emit8 0x00       
+      5 -> emit8 0x8d >> emit8 0x64 >> emit8 0x24 >> emit8 0x00 >>
+           x86_nop  
+      6 -> emit8 0x8d >> emit8 0xad >>        
+           emit8 0x00 >> emit8 0x00 >>        
+           emit8 0x00 >> emit8 0x00
+      7 -> emit8 0x8d >> emit8 0xa4 >>        
+           emit8 0x24 >> emit8 0x00 >>        
+           emit8 0x00 >> emit8 0x00 >>        
+           emit8 0x00
+      _ -> failCodeGen (PP.text "invalid padding size")
+
+-- Generate the code for a function prologue.  The frame_size is the
+-- number of bytes to be allocated as the frame size, and the reg_mask
+-- specifies which registers to save on function entry.
+
+x86_prolog :: Int -> Int -> CodeGen e s ()
+x86_prolog frame_size reg_mask =      
+    do x86_push_reg x86_ebp
+       x86_mov_reg_reg x86_ebp x86_esp x86_dword_size
+       gen_push 0 1
+       if frame_size /= 0 
+          then x86_alu_reg_imm x86_sub x86_esp frame_size
+          else return ()
+  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 ()
+
+-- Opposite to x86_prolog: destroys the stack frame and restores the
+-- registers in reg_mask, which should be the same as the register mask
+-- used on function entry.
+
+x86_epilog :: Int -> CodeGen e s ()
+x86_epilog reg_mask =
+    do gen_pop x86_edi (1 `shiftL` (fromIntegral x86_edi))
+       x86_mov_reg_reg x86_esp x86_ebp x86_dword_size
+       x86_pop_reg x86_ebp
+       x86_ret
+  where
+  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 ()
+
+-- TODO: Move signatures to definition, delete duplicates.
+x86_xchg_reg_reg ::
+  (Num a) =>
+  Word8
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_xchg_mem_reg ::
+  (Num a) =>
+  Word32
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_xchg_membase_reg ::
+  (Num a) =>
+  Word8
+  -> Word32
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_xadd_reg_reg ::
+  (Num a) =>
+  Word8
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_xadd_mem_reg ::
+  (Num a) =>
+  Word32
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_xadd_membase_reg ::
+  (Num a) =>
+  Word8
+  -> Word32
+  -> Word8
+  -> a
+  -> CodeGen e s ()
+x86_inc_mem ::
+  Word32 -> CodeGen e s ()
+x86_inc_membase ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_inc_reg ::
+  Word8 -> CodeGen e s ()
+x86_dec_mem ::
+  Word32 -> CodeGen e s ()
+x86_dec_membase ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_dec_reg ::
+  Word8 -> CodeGen e s ()
+x86_not_mem ::
+  Word32 -> CodeGen e s ()
+x86_not_membase ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_not_reg ::
+  Word8 -> CodeGen e s ()
+x86_neg_mem ::
+  Word32 -> CodeGen e s ()
+x86_neg_membase ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_neg_reg ::
+  Word8 -> CodeGen e s ()
+x86_alu_mem_imm ::
+  Word8
+  -> Word32
+  -> Word32
+  -> CodeGen e s ()
+x86_alu_membase_imm ::
+  Word8
+  -> Word8
+  -> Word32
+  -> Word32
+  -> CodeGen e s ()
+x86_alu_membase8_imm ::
+  Word8
+  -> Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_alu_mem_reg ::
+  Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_alu_membase_reg ::
+  Word8
+  -> Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_alu_reg_reg ::
+  Word8
+  -> Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_alu_reg8_reg8 ::
+  Word8
+  -> Word8
+  -> Word8
+  -> Bool
+  -> Bool
+  -> CodeGen e s ()
+x86_alu_reg_mem ::
+  Word8
+  -> Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_alu_reg_membase ::
+  Word8
+  -> Word8
+  -> Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_test_reg_imm ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_test_mem_imm ::
+  Word32
+  -> Word32
+  -> CodeGen e s ()
+x86_test_membase_imm ::
+  Word8
+  -> Word32
+  -> Word32
+  -> CodeGen e s ()
+x86_test_reg_reg ::
+  Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_test_mem_reg ::
+  Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_test_membase_reg ::
+  Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_shift_reg_imm ::
+  Word8
+  -> Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_shift_mem_imm ::
+  Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_shift_membase_imm ::
+  Word8
+  -> Word8
+  -> Word32
+  -> Word8
+  -> CodeGen e s ()
+x86_shift_reg ::
+  Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_shift_mem ::
+  Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_shift_membase ::
+  Word8
+  -> Word8
+  -> Word32
+  -> CodeGen e s ()
+x86_shrd_reg ::
+  Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_shrd_reg_imm ::
+  Word8
+  -> Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_shld_reg ::
+  Word8
+  -> Word8
+  -> CodeGen e s ()
+x86_shld_reg_imm ::
+  Word8
+  -> Word8
+  -> Word8
+  -> 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
+
+
+newtype XMMReg = XMMReg Word8
+    deriving (Eq, Ord)
+
+newtype Mem = Mem Word32
+
+data MemBase = MemBase Word8 Word32
+
+
+class XMMLocation xmm where
+   xmm_location_emit :: Word8 -> xmm -> CodeGen e s ()
+
+instance XMMLocation XMMReg where
+   xmm_location_emit dreg (XMMReg reg) =
+      x86_reg_emit dreg reg
+
+instance XMMLocation Mem where
+   xmm_location_emit dreg (Mem mem) =
+      x86_mem_emit dreg mem
+
+instance XMMLocation MemBase where
+   xmm_location_emit dreg (MemBase basereg disp) =
+      x86_membase_emit dreg basereg disp
+
+
+x86_movss_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movss_to_reg dreg reg =
+    do emit8 0xf3
+       emit8 0x0f
+       emit8 0x10
+       xmm_location_emit dreg reg
+
+x86_movss_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movss_from_reg dreg reg =
+    do emit8 0xf3
+       emit8 0x0f
+       emit8 0x11
+       xmm_location_emit dreg reg
+
+x86_movsd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movsd_to_reg dreg reg =
+    do emit8 0xf2
+       emit8 0x0f
+       emit8 0x10
+       xmm_location_emit dreg reg
+
+x86_movsd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movsd_from_reg dreg reg =
+    do emit8 0xf2
+       emit8 0x0f
+       emit8 0x11
+       xmm_location_emit dreg reg
+
+
+-- | xmm must not be a register
+x86_movlps_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movlps_to_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x12
+       xmm_location_emit dreg reg
+
+-- | xmm must not be a register
+x86_movlps_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movlps_from_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x13
+       xmm_location_emit dreg reg
+
+-- | xmm must not be a register
+x86_movlpd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movlpd_to_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x12
+       xmm_location_emit dreg reg
+
+-- | xmm must not be a register
+x86_movlpd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movlpd_from_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x13
+       xmm_location_emit dreg reg
+
+
+x86_movups_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movups_to_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x10
+       xmm_location_emit dreg reg
+
+x86_movups_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movups_from_reg dreg reg =
+    do emit8 0x0f
+       emit8 0x11
+       xmm_location_emit dreg reg
+
+x86_movupd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movupd_to_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x10
+       xmm_location_emit dreg reg
+
+x86_movupd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_movupd_from_reg dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x11
+       xmm_location_emit dreg reg
+
+
+x86_haddps :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_haddps dreg reg =
+    do emit8 0xf2
+       emit8 0x0f
+       emit8 0x7c
+       xmm_location_emit dreg reg
+
+x86_haddpd :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_haddpd dreg reg =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0x7c
+       xmm_location_emit dreg reg
+
+
+x86_shufps :: XMMLocation xmm => Word8 -> xmm -> Word8 -> CodeGen e s ()
+x86_shufps dreg reg src =
+    do emit8 0x0f
+       emit8 0xc6
+       xmm_location_emit dreg reg
+       emit8 src
+
+x86_shufpd :: XMMLocation xmm => Word8 -> xmm -> Word8 -> CodeGen e s ()
+x86_shufpd dreg reg src =
+    do emit8 0x66
+       emit8 0x0f
+       emit8 0xc6
+       xmm_location_emit dreg reg
+       emit8 src
+
+
+x86_cvtdq2ps :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_cvtdq2ps dreg reg =
+    do emit8 0x0f
+       emit8 0x5b
+       xmm_location_emit dreg reg
+
+x86_cvttps2dq :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()
+x86_cvttps2dq dreg reg =
+    do emit8 0xf3
+       emit8 0x0f
+       emit8 0x5b
+       xmm_location_emit dreg reg
+
+
+
+-- =============================================================================
+-- Prefetching instructions.
+-- =============================================================================
+
+x86_prefetch0_mem :: Word32 -> CodeGen e s ()
+x86_prefetch0_mem m = x86_prefetch_mem 1 m
+
+x86_prefetch1_mem :: Word32 -> CodeGen e s ()
+x86_prefetch1_mem m = x86_prefetch_mem 2 m
+
+x86_prefetch2_mem :: Word32 -> CodeGen e s ()
+x86_prefetch2_mem m = x86_prefetch_mem 3 m
+
+x86_prefetchnta_mem :: Word32 -> CodeGen e s ()
+x86_prefetchnta_mem m = x86_prefetch_mem 0 m
+
+x86_prefetch_mem :: Word8 -> Word32 -> CodeGen e s ()
+x86_prefetch_mem hint disp =
+    do emit8 0x0f
+       emit8 0x18
+       x86_address_byte 0 hint 0 
+       x86_imm_emit32 disp
+
+x86_prefetch0_membase :: Word8 -> Word32 -> CodeGen e s ()
+x86_prefetch0_membase r m = x86_prefetch_membase 1 r m
+
+x86_prefetch1_membase :: Word8 -> Word32 -> CodeGen e s ()
+x86_prefetch1_membase r m = x86_prefetch_membase 2 r m
+
+x86_prefetch2_membase :: Word8 -> Word32 -> CodeGen e s ()
+x86_prefetch2_membase r m = x86_prefetch_membase 3 r m
+
+x86_prefetchnta_membase :: Word8 -> Word32 -> CodeGen e s ()
+x86_prefetchnta_membase r m = x86_prefetch_membase 0 r m
+
+x86_prefetch_membase :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
+x86_prefetch_membase hint reg disp =
+    do emit8 0x0f
+       emit8 0x18
+       x86_membase_emit hint reg disp
+
+x86_prefetch0_regp :: Word8 -> CodeGen e s ()
+x86_prefetch0_regp r = x86_prefetch_regp 1 r
+
+x86_prefetch1_regp :: Word8 -> CodeGen e s ()
+x86_prefetch1_regp r = x86_prefetch_regp 2 r
+
+x86_prefetch2_regp :: Word8 -> CodeGen e s ()
+x86_prefetch2_regp r = x86_prefetch_regp 3 r
+
+x86_prefetchnta_regp :: Word8 -> CodeGen e s ()
+x86_prefetchnta_regp r = x86_prefetch_regp 0 r
+
+x86_prefetch_regp :: Word8 -> Word8 -> CodeGen e s ()
+x86_prefetch_regp hint reg =
+    do emit8 0x0f
+       emit8 0x18
+       x86_regp_emit hint reg
+
diff --git a/Harpy/X86Disassembler.hs b/Harpy/X86Disassembler.hs
new file mode 100644 (file)
index 0000000..d7cccc8
--- /dev/null
@@ -0,0 +1,32 @@
+--------------------------------------------------------------------------
+-- |
+-- Module      :  Harpy.X86Disassembler
+-- Copyright   :  (c) Martin Grabmueller and Dirk Kleeblatt
+-- License     :  GPL
+-- 
+-- Maintainer  :  {magr,klee}@cs.tu-berlin.de
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Disassembler for x86 machine code.
+--
+-- This is a module for compatibility with earlier Harpy releases.  It
+-- re-exports the disassembler from the disassembler package.
+--------------------------------------------------------------------------
+
+module Harpy.X86Disassembler(
+  -- * Types
+  Opcode,
+  Operand(..),
+  InstrOperandSize(..),
+  Instruction(..),
+  ShowStyle(..),
+  -- * Functions
+  disassembleBlock,
+  disassembleList,
+  disassembleArray,
+  showIntel,
+  showAtt
+  ) where
+
+import Text.Disassembler.X86Disassembler
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..8c5a3bd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+.PHONY: all clean install reinstall uninstall doc
+
+all:
+       runhaskell Setup.hs configure --prefix=$(HOME)/
+       runhaskell Setup.hs build
+
+clean:
+       runhaskell Setup.hs clean
+
+
+install:
+       runhaskell Setup.hs install --user
+
+reinstall:
+       runhaskell Setup.hs clean
+       runhaskell Setup.hs configure --prefix=$(HOME)/
+       runhaskell Setup.hs build
+       runhaskell Setup.hs install --user
+
+uninstall:
+       runhaskell Setup.hs unregister --user
+
+doc:
+       runhaskell Setup.hs haddock
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..6cf860c
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,93 @@
+                                                       -*-outline-*-
+* Harpy NEWS
+
+** New in version 0.4.2
+
+*** package structure
+
+- The disassembler is now in a separate package, and is re-exported for
+  compatibility by Harpy. This allows us to give the more liberal BSD licence
+  to the disassembler.
+
+*** New instructions
+
+- The "mov", "jcc" (jump on condition code), and "cmp" instructions support
+  "Ptr a" as operand
+
+- Henning Thielemann provided some further floating point and SSE
+  instructions.
+
+- The loop instruction supports labels now.
+
+*** Enhancements
+
+- The disassembly of Harpy's internal code buffers includes all labels
+  now, even when multiple labels are defined for the same location.
+
+** New in version 0.4.1
+
+*** New Instances
+
+- Many of Harpy's types are now instances of Eq.
+
+*** New instructions
+
+- Added support for the prefetching instructions PREFETCH0, PREFETCH1,
+  PREFETCH2 and PREFETCHNTA.
+
+*** Bug fixes
+
+- Harpy.X86Disassembler.disassembleBloc was too strict and caused
+  stack overflows for large inputs.  This was fixed.
+
+- Disassembler: The instruction prefix list was not cleared when
+  beginning to parse a new instruction.  This caused incorrect
+  disassembly of SSE instructions.
+
+- Disassembler: A bug has been fixed in the parsing routine for the
+  addressing mode "scaled index + 32 bit offset" without base
+  register.
+
+** 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/README b/README
new file mode 100644 (file)
index 0000000..5d276a4
--- /dev/null
+++ b/README
@@ -0,0 +1,65 @@
+                                                              -*-outline-*-
+* README file for the Harpy Haskell Run-time Code Generator
+
+Codename: Harpy - Haskell Assembler at Run-time produces Y...
+  Harpy [myth.]        f: die Harpyie
+  http://en.wikipedia.org/wiki/Harpy
+
+** Introduction
+
+Harpy is a library for run-time code generation in Haskell programs.
+
+Harpy requires several Haskell extensions and GHC-specific features
+(the Haskell FFI, Template Haskell, multi-parameter type classes and
+monad transformers).
+
+** Features
+
+The following modules are included in this package:
+
+Harpy.CodeGenMonad: This module defines the code generator monad,
+  which is a combined state/reader/exception monad.  It contains
+  all the necessary details for allocating and managing code buffers.
+
+Harpy.X86CodeGen: This module contains all the functions for generating
+  native x86 machine code.  The functions are very simple, and it is
+  necessary to specify all addressing modes etc. when emitting an
+  instruction.
+
+Harpy.X86Assembler: A type class based layer on top of X86CodeGen
+  which determines the addressing modes from the types of the
+  operands.
+
+Harpy.X86CGCombinators: Code generation combinators for conditionals,
+  loops, function entry/exit code etc.
+
+Harpy.X86Disassembler: A disassembler for x86 machine code.
+
+Harpy.Call: Exports functions for invoking the generated code.
+
+** Notes about the implementation
+
+*** X86CodeGen.lhs
+
+The file X86CodeGen.lhs is based on a header file called x86-codegen.h
+from the Mono distribution, which defines macros for emitting x86
+machine code directly into a memory buffer.  The Haskell module is a
+nearly one-to-one mapping from the original macros to Haskell
+functions.  The main differences are:
+
+- Instead of emitting the data directly into a buffer, it uses the
+  CodeGen monad from file CodeGenMonad.lhs.
+
+- The functions are strongly typed.
+
+Several things should be kept in mind when using this file:
+
+- Buffer overflow checks have to be done manually with checkBufferSize or
+  ensureBufferSize
+
+- MMX, SSE, SSE2 and SSE3 instructions and registers are not supported.
+
+- 64-bit mode is not supported.
+
+- The disassembler supports (in principle) 64-bit mode and SSE
+  instructions, but this has not been tested.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644 (file)
index 0000000..9a994af
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..a18d22c
--- /dev/null
@@ -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 (file)
index 0000000..1366af3
--- /dev/null
@@ -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 literate 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 library.
+
+Happy Harpy Hacking in Haskell!
+
+\end{document}
diff --git a/doc/tutorial.lhs b/doc/tutorial.lhs
new file mode 100644 (file)
index 0000000..7540abc
--- /dev/null
@@ -0,0 +1,199 @@
+\documentclass[a4paper]{article}
+
+\usepackage[latin1]{inputenc}
+
+\usepackage{listings}
+
+\lstnewenvironment{code}{}{}
+\lstset{
+  basicstyle=\ttfamily,
+  keywordstyle=\normalfont\bfseries,
+  identifierstyle=\bfseries,
+  commentstyle=\rmfamily,
+  texcl=true, 
+  language=Haskell,
+  flexiblecolumns=false,
+  basewidth={0.5em,0.45em},
+  extendedchars=true, 
+  frame=leftline,
+  numbers=left,
+  firstnumber=last,
+  literate={+}{{$+$}}1 {/}{{$/$}}1 {*}{{$*$}}1 {=}{{$=$}}1
+           {>}{{$>$}}1 {<}{{$<$}}1 
+           {->}{{$\rightarrow$}}2 {>=}{{$\geq$}}2 {<-}{{$\leftarrow$}}2
+           {<=}{{$\leq$}}2 {=>}{{$\Rightarrow$}}2 {\ .}{{ $\circ$}}2,
+  numberstyle=\tiny
+} 
+
+\title{Harpy Tutorial}
+\author{Martin Grabmüller \and Dirk Kleeblatt}
+
+\begin{document}
+\maketitle
+\abstract{
+We present some of the features of
+Harpy, an in-line assembler for Haskell.  This little tutorial shows how to
+write assembler programs without making one's hands dirty, staying in the
+beautiful pure functional world of Haskell.  During this tutorial, we develop
+step by step an assembler implementation of the factorial function, and show
+how assembler code can be called from ordinary Haskell code.
+
+This document is written as a literate Haskell program, so you can compile and run it
+without any modifications.
+}
+
+\section{Introduction}
+
+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 Foreign
+import Control.Monad.Trans
+\end{code}
+
+The module \lstinline-Harpy.CodeGenMonad- defines the polymorphic type
+\lstinline-CodeGen e s-, which is an instance of the \lstinline-Monad-
+class. The type parameters \lstinline-e- and \lstinline-s- can be instantiated
+to the type of an user's environment and state, respectively. These behave
+like the environments and states known from the \lstinline-Reader- and
+\lstinline-State- monads. Besides this monadic type, this module defines some
+functions to make use of code labels, and provides an interface to a
+disassembler.
+
+The module \lstinline-Harpy.X86Assembler- provides a subset of the x86
+assembler instructions, e.~g. \verb-mov- for moving memory words around. These
+instructions are implemented as class methods, to allow different addressing
+modes without hassle.
+
+We additionally import the module \lstinline-Foreign-, since we need some low
+level types to exchange parameters and results with our assembler code, and
+\lstinline-Control.Monad.MonadTrans- to have some instances available.
+
+\section{A fast factorial function}
+
+Now we are ready to define the factorial function in assembler code.
+
+\lstset{firstnumber=4}
+\begin{code}
+fac :: CodeGen e s ()
+fac = do loopTest  <- newLabel
+         loopStart <- newLabel
+         ensureBufferSize 160
+         push ecx
+         mov  ecx (Disp 8, esp)
+         mov  eax (1 :: Word32)
+         jmp  loopTest
+         loopStart @@ mul ecx
+         sub  ecx (1 :: Word32)
+         loopTest @@ cmp ecx (0 :: Word32)
+         jne  loopStart
+         pop  ecx
+         ret
+\end{code}
+
+We first create two labels, \lstinline-loopTest- and \lstinline-loopStart-, to
+mark the test and the beginning of a loop. In lines 5 and 6, these labels are
+merely announced to Harpy, they are not (yet) defined to sit at a specific
+code position.
+
+Line 8 saves the \lstinline-ecx- rigister on the system stack, because we will
+use it as a loop counter, and want to restore it before returning to Haskell
+functions.
+
+Line 9 shows an indirect adressing with displacement. Note, that all Harpy
+functions use Intel assembler style, i.~e. the first operand is the
+destination and the second one the source of each instruction. So this line
+moves the memory contents at address \lstinline-esp+8- into
+\lstinline-ecx-. Since we will make a C call into our assembler code, this
+accesses the first parameter on the stack. When returning to the Haskell world
+via \lstinline-ret-, we leave our result in \lstinline-eax-, again adhering to
+the C calling convention.
+
+The rest of \lstinline-fac- just accumulates the factorial in \lstinline-eax-
+while counting down \lstinline-ecx-. Lines 12 and 14 show how our labels
+\lstinline-loopStart- and \lstinline-loopTest- are placed at specific code
+positions.
+
+The function \lstinline-fac- is not really our wanted factorial
+function. Instead it is a monadic command that, when executed, writes
+assembler code into a buffer. To ensure, that this buffer is always large
+enough to hold the generated instruction, you have to sprinkle your code with
+calls to \lstinline-ensureBufferSize-. In line 7 we make sure that 160 bytes
+are available, which is enough for our 10 instructions. As a rule of thumb, no
+instruction can be larger than 16 bytes, so the number of assembler
+instructions times 16 is a safe upper bound.
+
+The next section shows how to prepare a call into such a buffer.
+
+\section{Preparing a call}
+
+The module \lstinline-Harpy.Call- defines some functions to call functions
+written in assembler with various argument and result types. But since it is
+possible to use all types suitable for FFI calls as argument or result, sooner
+or later you will need some combination not yet implemented. So here we show
+how to define your own calling stub.
+
+\lstset{firstnumber=18}
+\begin{code}
+$(callDecl "callFac" [t|Word32 -> Word32|])
+\end{code}
+
+The Template Haskell function \lstinline-callDecl- is used to declare a
+function \lstinline-callFac- which will call our assembler fragment. We want
+to pass a parameter of type \lstinline-Word32-, and expect a result of the
+same type, that's why we give \lstinline+Word32 -> Word32+ as argument to
+\lstinline-callDecl-. If you wonder about the fancy \lstinline-$- and
+\lstinline-[t| |]-, either look them up in the Template Haskell
+documentation, or just ignore them. However, to make this line compile, you
+have to switch on Template Haskell, which is done for the Glasgow Haskell
+compiler by the command line flag \verb+-fth+.
+
+\section{Calling \lstinline-fac-}
+
+Now we have all we need to call into our factorial function.
+
+\lstset{firstnumber=19}
+\begin{code}
+runFac :: CodeGen e s ()
+runFac = do fac
+            x <- liftIO readLn
+            y <- callFac x
+            liftIO (putStrLn (show y))
+\end{code}
+
+We first call \lstinline-fac- to write our assembler code into the internal
+buffer. Since the \lstinline-CodeGen- monad ist an instance of
+\lstinline-MonadIO-, we can use \lstinline-liftIO- to use all commands we wish
+from the \lstinline-IO- monad. Here, we use this to read the argument to the
+factorial function from the keyboard, and to write the result back to the
+screen. Line 21 calls into the internal code buffer with our assembler
+instructions using the stub declared in the last section.
+
+\section{How to use it}
+
+Up to now, all our functions live in the \lstinline-CodeGen- monad. To make
+use of them, we have to \emph{unlift} them into the \lstinline-IO- monad. This
+is done by \lstinline-runCodeGen-.
+
+\lstset{firstnumber=24}
+\begin{code}
+main :: IO ()
+main = do
+   (finalState, result) <- runCodeGen runFac () ()
+   case result of
+     Right () -> return ()
+     Left err -> putStrLn (show err)
+\end{code}
+
+The second and third arguments to \lstinline-runCodeGen- are the initial
+environment and state. Since we did not use them, their type is polymorphic
+and we can use \lstinline-()- as initial values. The result is a pair
+consisting of the final state, and a result value. A value constructed with
+the constructor \lstinline-Right- indicates a successful run, while
+\lstinline-Left- values indicate runtime errors. These might occur for
+instance because of infeasible addressing modes.
+
+ \end{document}
diff --git a/examples/evaluator/ArithParser.hs b/examples/evaluator/ArithParser.hs
new file mode 100644 (file)
index 0000000..798a03b
--- /dev/null
@@ -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 (file)
index 0000000..112ae6a
--- /dev/null
@@ -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 (file)
index 0000000..a9cdd3d
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..5c253c6
--- /dev/null
@@ -0,0 +1,67 @@
+Cabal-version:  >=1.2
+Build-type: Simple
+Name:           harpy
+Version:        0.4.3.0
+License:        GPL
+License-file:   COPYING
+Author:         Dirk Kleeblatt <klee@cs.tu-berlin.de>
+                Martin Grabmueller <martin.grabmueller@eleven.de>
+Maintainer:     klee@cs.tu-berlin.de, martin.grabmueller@eleven.de
+Homepage:       http://uebb.cs.tu-berlin.de/harpy/
+Category:       Code Generation
+Synopsis:       Runtime code generation for x86 machine code
+Description:   The package contains the following components:
+       .
+       * An x86 assembler.  We provide both low-level code generation in
+         module "Harpy.X86CodeGen" as well as a (slightly) higher-level
+         implementation in module "Harpy.X86Assembler", which figures out
+         addressing modes based on an instruction's operand types.
+       .
+       * An x86 disassembler which knows most of the opcodes available on
+         modern x86 processors and can display its output both in the style
+         used in Intel documents an in AT&T style, like the GNU tools. The
+         disassembler can be found in module "Harpy.X86Disassembler".  The
+          disassembler is re-exported from the disassembler package for
+          compatibility with earlier Harpy releases.
+       .
+       * Some abstractions over the abovementioned code generation modules,
+         such as automatic label management and code generation
+         combinators (for if-then-else statements, while-loops, functions)
+         (module "Harpy.X86CGCombinators").
+       .
+       * 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
+
+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
+
+Library
+  Build-depends:
+    base >= 4 && < 5,
+    parsec >= 1 && < 3,
+    mtl >= 1 && < 2,
+    template-haskell >= 2 && < 3,
+    pretty >= 1 && < 2,
+    containers >= 0.3 && < 1,
+    array >= 0.3 && < 1,
+    disassembler >= 0.1.0.1
+  Exposed-Modules:
+    Harpy,
+    Harpy.X86CodeGen,
+    Harpy.X86Assembler,
+    Harpy.CodeGenMonad,
+    Harpy.Call,
+    Harpy.X86Disassembler,
+    Harpy.X86CGCombinators
+  Extensions: 
+    ForeignFunctionInterface, MultiParamTypeClasses, 
+    TemplateHaskell, CPP, FlexibleContexts, FlexibleInstances,
+    RankNTypes
+