diff --git a/ANNOUNCE b/ANNOUNCE
new file mode 100644
--- /dev/null
+++ b/ANNOUNCE
@@ -0,0 +1,60 @@
+ANNOUNCE: Harpy 0.4 - Runtime code generation for x86 machine code
+
+We are pleased to announce the release of Harpy 0.4, a library for
+runtime code generation for x86 machine code.
+
+Harpy is available from Hackage:
+
+  http://hackage.haskell.org/cgi-bin/hackage-scripts/package/harpy-0.4
+
+Also see Harpy's homepage, which features two tutorials and access to
+the darcs repo (and to the Haddock documentation, until it is available
+from Hackage, too):
+
+  http://uebb.cs.tu-berlin.de/harpy/
+
+Harpy is supposed to be built with GHC 6.8 and GHC 6.6 (with Cabal 1.2
+or greater).  Please report any build problems you encounter.
+
+This release features the following additions and fixes:
+
+- 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.
+
+Happy Haskell Hacking with Harpy,
+
+  Martin and Dirk
diff --git a/Harpy/CodeGenMonad.hs b/Harpy/CodeGenMonad.hs
--- a/Harpy/CodeGenMonad.hs
+++ b/Harpy/CodeGenMonad.hs
@@ -162,6 +162,7 @@
 
 -- | 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
diff --git a/Harpy/X86Assembler.hs b/Harpy/X86Assembler.hs
--- a/Harpy/X86Assembler.hs
+++ b/Harpy/X86Assembler.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances #-}
 --------------------------------------------------------------------------
 -- |
 -- Module      :  Harpy.X86Assembler
@@ -64,7 +65,7 @@
 si = Reg16 6
 di = Reg16 7
 
-newtype Reg32 = Reg32 Word8 deriving Eq
+newtype Reg32 = Reg32 Word8 deriving (Eq, Ord)
 eax, ecx, edx, ebx, esp, ebp, esi, edi :: Reg32
 
 eax = Reg32 0
@@ -77,7 +78,9 @@
 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
@@ -87,6 +90,9 @@
 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
@@ -1572,6 +1578,9 @@
   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
@@ -2952,6 +2961,18 @@
 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 ()
 
@@ -3743,4 +3764,52 @@
 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 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
 
diff --git a/Harpy/X86CodeGen.hs b/Harpy/X86CodeGen.hs
--- a/Harpy/X86CodeGen.hs
+++ b/Harpy/X86CodeGen.hs
@@ -113,7 +113,7 @@
     x86_ret, x86_ret_imm,
     -- ** Jump and branch
     x86_jecxz, x86_branch, x86_branch32, x86_branch8,
-    x86_jump_membase, x86_jump_mem, x86_jump_reg, 
+    x86_jump_membase, x86_jump_pointer, x86_jump_mem, x86_jump_reg, 
     x86_jump32, x86_jump8, 
     x86_loopne, x86_loope, x86_loop, 
     -- ** Stack operations
@@ -187,6 +187,10 @@
     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,
+    -- ** 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,
@@ -786,36 +790,51 @@
 
 -- 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 >> 
@@ -827,10 +846,14 @@
 -- 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
@@ -851,33 +874,53 @@
          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;    
@@ -891,6 +934,8 @@
                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     
@@ -905,6 +950,7 @@
                        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        
@@ -1179,6 +1225,13 @@
 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.
 
 {-
@@ -1594,143 +1647,10 @@
   -> Word8
   -> Word8
   -> CodeGen e s ()
-x86_mul_reg ::
-  Word8 -> Bool -> CodeGen e s ()
-x86_mul_mem ::
-  Word32 -> Bool -> CodeGen e s ()
-x86_mul_membase ::
-  Word8
-  -> Word32
-  -> Bool
-  -> CodeGen e s ()
-x86_imul_reg_reg ::
-  Word8
-  -> Word8
-  -> CodeGen e s ()
-x86_imul_reg_mem ::
-  Word8
-  -> Word32
-  -> CodeGen e s ()
-x86_imul_reg_membase ::
-  Word8
-  -> Word8
-  -> Word32
-  -> CodeGen e s ()
-x86_imul_reg_reg_imm ::
-  Word8
-  -> Word8
-  -> Word32
-  -> CodeGen e s ()
-x86_imul_reg_mem_imm ::
-  Word8
-  -> Word32
-  -> Word32
-  -> CodeGen e s ()
-x86_imul_reg_membase_imm ::
-  Word8
-  -> Word8
-  -> Word32
-  -> Word32
-  -> CodeGen e s ()
-x86_div_reg ::
-  Word8 -> Bool -> CodeGen e s ()
-x86_div_mem ::
-  Word32 -> Bool -> CodeGen e s ()
-x86_div_membase ::
-  Word8
-  -> Word32
-  -> Bool
-  -> CodeGen e s ()
-x86_mov_mem_reg ::
-  (Num t) =>
-  Word32
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_regp_reg ::
-  (Num t) =>
-  Word8
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_regp ::
-  (Num t) =>
-  Word8
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_membase_reg ::
-  (Num t) =>
-  Word8
-  -> Word32
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_memindex_reg ::
-  (Num t) =>
-  Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_reg ::
-  (Num t) =>
-  Word8
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_mem ::
-  (Num t) =>
-  Word8
-  -> Word32
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_membase ::
-  (Num t) =>
-  Word8
-  -> Word8
-  -> Word32
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_memindex ::
-  (Num t) =>
-  Word8
-  -> Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> t
-  -> CodeGen e s ()
-x86_mov_reg_imm ::
-  Word8
-  -> Word32
-  -> CodeGen e s ()
-x86_mov_mem_imm ::
-  (Num a) =>
-  Word32
-  -> Word32
-  -> a
-  -> CodeGen e s ()
-x86_mov_membase_imm ::
-  (Num a) =>
-  Word8
-  -> Word32
-  -> Word32
-  -> a
-  -> CodeGen e s ()
-x86_mov_memindex_imm ::
-  (Num a) =>
-  Word8
-  -> Word32
-  -> Word8
-  -> Word8
-  -> Word32
-  -> a
-  -> CodeGen e s ()
 
+-- =============================================================================
 -- SSE instructions.
+-- =============================================================================
 
 data X86_SSE_PFX = X86_SSE_SD
                  | X86_SSE_SS
@@ -2009,4 +1929,63 @@
     do emit8 0x0f
        emit8 0x2e
        x86_membase_emit dreg basereg disp
+
+-- =============================================================================
+-- 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
--- a/Harpy/X86Disassembler.hs
+++ b/Harpy/X86Disassembler.hs
@@ -490,7 +490,7 @@
 	    | XOR
 	    | XORPD
 	    | XORPS
-  deriving (Show)
+  deriving (Show, Eq)
 
 -- Display an opcode in lower case.
 
@@ -534,6 +534,7 @@
        		 -- ^ Scaled index with displacement
               | OpBaseIndexDisp String String Int Int InstrOperandSize
        		 -- ^ Base plus scaled index with displacement
+  deriving (Eq)
 
 -- Show an operand in AT&T style.
 
@@ -597,7 +598,7 @@
        	        | OPF32	       -- ^ 32-bit floating point operand
        	        | OPF64	       -- ^ 64-bit floating point operand
        	        | OPF80	       -- ^ 80-bit floating point operand
-  deriving (Show)
+  deriving (Show, Eq)
 
 
 -- | The disassembly routines return lists of the following datatype.  It
@@ -615,6 +616,7 @@
                   address :: Int,             -- ^ Start address of instruction
        		  bytes ::[Word8]	      -- ^ Instruction bytes
                  }			      -- ^ Valid instruction
+  deriving (Eq)
 
 instance Show Instruction where
     show = showIntel
@@ -779,16 +781,16 @@
 
 disassembleBlock :: Ptr Word8 -> Int -> IO (Either ParseError [Instruction])
 disassembleBlock ptr len = do
-  l <- toList ptr len 0
+  l <- toList ptr len 0 []
   parseInstructions 
-    defaultState{startAddr = fromIntegral (minusPtr ptr nullPtr)} l
+    defaultState{startAddr = fromIntegral (minusPtr ptr nullPtr)} (reverse l)
   where 
-  toList :: (Ptr Word8) -> Int -> Int -> IO [Word8]
-  toList ptr len idx | idx < len =
+  toList :: (Ptr Word8) -> Int -> Int -> [Word8] -> IO [Word8]
+  toList ptr len idx acc | idx < len =
        	   do p <- peekByteOff ptr idx
-       	      r <- toList ptr len (idx + 1)
-       	      return (p : r)
-  toList ptr len idx | idx >= len = return []
+       	      toList ptr len (idx + 1) (p : acc)
+--       	      return (p : r)
+  toList ptr len idx acc | idx >= len = return acc
 
 -- | Disassemble the contents of the given array.
 
@@ -870,7 +872,8 @@
     input <- getInput
     st <- getState
     setState st{operandBitMode = defaultBitMode st,
-                 addressBitMode = defaultBitMode st}
+                 addressBitMode = defaultBitMode st,
+               prefixes = []}
     many parsePrefix
     b <- anyWord8
     case lookup b oneByteOpCodeMap of
@@ -1503,12 +1506,27 @@
     0 -> case rm of
             4 -> do 
 	     (s, i, b) <- parseSIB
-       	     case i of
-       	       4 -> return (OpInd (addregnames !! fromIntegral b) opsize,
+       	     case (i, b) of
+               (4, 5) -> do
+                           disp <- anyWord32
+                           return (OpAddr (fromIntegral disp) opsize,
+                                          OpReg (opregnames !! fromIntegral reg_opc)
+                                                (fromIntegral reg_opc),
+                                          mod, reg_opc, rm)
+               (_, 5) -> do
+                           disp <- anyWord32
+                           return (OpIndexDisp (addregnames !! fromIntegral i)
+                                               (scaleToFactor s)
+                                               (fromIntegral disp)
+                                               opsize,
+                                   OpReg (opregnames !! fromIntegral reg_opc)
+                                         (fromIntegral reg_opc),
+                                   mod, reg_opc, rm)
+       	       (4, _) -> return (OpInd (addregnames !! fromIntegral b) opsize,
        	                   OpReg (opregnames !! fromIntegral reg_opc)
 			     (fromIntegral reg_opc),
        		           mod, reg_opc, rm)
-       	       _ -> return (OpBaseIndex 
+       	       (_ ,_) -> return (OpBaseIndex 
        		              (addregnames !! fromIntegral b)
        	                      (addregnames !! fromIntegral i)
        		              (scaleToFactor (fromIntegral s))
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,30 @@
 							-*-outline-*-
 * Harpy NEWS
 
+** 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
diff --git a/doc/larger-tutorial.lhs b/doc/larger-tutorial.lhs
--- a/doc/larger-tutorial.lhs
+++ b/doc/larger-tutorial.lhs
@@ -16,7 +16,7 @@
 This tutorial is an introduction to some of the more advanced features
 of Harpy.  In the course of the tutorial, we will build a small
 run-time compiler for a call-by-value lambda-calculus.
-This document is written as a litarate Haskell program, so you can
+This document is written as a literate Haskell program, so you can
 compile and run it without any modifications.  
 \end{abstract}
 
@@ -305,7 +305,7 @@
 
 This completes our little just-in-time compiled lambda calculus
 evaluator.  We hope that this tutorial makes clear many of the fine
-points in using the libray.
+points in using the library.
 
 Happy Harpy Hacking in Haskell!
 
diff --git a/doc/tutorial.lhs b/doc/tutorial.lhs
--- a/doc/tutorial.lhs
+++ b/doc/tutorial.lhs
@@ -38,7 +38,7 @@
 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 litarate Haskell program, so you can compile and run it
+This document is written as a literate Haskell program, so you can compile and run it
 without any modifications.
 }
 
diff --git a/examples/evaluator/README b/examples/evaluator/README
new file mode 100644
--- /dev/null
+++ b/examples/evaluator/README
@@ -0,0 +1,21 @@
+The three modules contained in this directory contain an evaluator
+for arithmetic expressions.
+
+Load it into ghci using the command
+
+  ghci -XTemplateHaskell Evaluator.hs
+
+or compile it with
+
+  ghc --make -XTemplateHaskell Evaluator.hs
+
+and start it with
+
+  ./Evaluator
+
+Then type the command
+
+  :help
+
+and start playing with it.
+
diff --git a/harpy.cabal b/harpy.cabal
--- a/harpy.cabal
+++ b/harpy.cabal
@@ -1,6 +1,7 @@
 Cabal-version:  >=1.2
+Build-type: Simple
 Name:           harpy
-Version:        0.4
+Version:        0.4.1
 License:        GPL
 License-file:   COPYING
 Author:         Dirk Kleeblatt <klee@cs.tu-berlin.de>
