harpy 0.4 → 0.4.1
raw patch · 10 files changed
+327/−154 lines, 10 filesnew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Harpy.Call: conv[a10Ee] :: FunPtr () -> IO ()
- Harpy.Call: conv[a10FL] :: FunPtr (Word32 -> Word32) -> Word32 -> IO Word32
- Harpy.Call: conv[a10Lb] :: FunPtr (Ptr a[a10L4] -> Ptr b[a10L5] -> Ptr c[a10L6] -> Ptr d[a10L7] -> Ptr e[a10L8] -> Ptr f[a10L9] -> Ptr g[a10La] -> ()) -> Ptr a[a10L4] -> Ptr b[a10L5] -> Ptr c[a10L6] -> Ptr d[a10L7] -> Ptr e[a10L8] -> Ptr f[a10L9] -> Ptr g[a10La] -> IO ()
+ Harpy.Call: conv[a126I] :: FunPtr () -> IO ()
+ Harpy.Call: conv[a128f] :: FunPtr (Word32 -> Word32) -> Word32 -> IO Word32
+ Harpy.Call: conv[a12dF] :: FunPtr (Ptr a[a12dy] -> Ptr b[a12dz] -> Ptr c[a12dA] -> Ptr d[a12dB] -> Ptr e[a12dC] -> Ptr f[a12dD] -> Ptr g[a12dE] -> ()) -> Ptr a[a12dy] -> Ptr b[a12dz] -> Ptr c[a12dA] -> Ptr d[a12dB] -> Ptr e[a12dC] -> Ptr f[a12dD] -> Ptr g[a12dE] -> IO ()
+ Harpy.CodeGenMonad: instance Eq Label
+ Harpy.CodeGenMonad: instance Ord Label
+ Harpy.X86Assembler: class Prefetch0 a
+ Harpy.X86Assembler: class Prefetch1 a
+ Harpy.X86Assembler: class Prefetch2 a
+ Harpy.X86Assembler: class Prefetchnta a
+ Harpy.X86Assembler: instance Eq XMMReg
+ Harpy.X86Assembler: instance Jmp (Ptr a)
+ Harpy.X86Assembler: instance Ord Reg32
+ Harpy.X86Assembler: instance Ord XMMReg
+ Harpy.X86Assembler: instance Prefetch0 (Disp, Reg32)
+ Harpy.X86Assembler: instance Prefetch0 Addr
+ Harpy.X86Assembler: instance Prefetch0 Ind
+ Harpy.X86Assembler: instance Prefetch1 (Disp, Reg32)
+ Harpy.X86Assembler: instance Prefetch1 Addr
+ Harpy.X86Assembler: instance Prefetch1 Ind
+ Harpy.X86Assembler: instance Prefetch2 (Disp, Reg32)
+ Harpy.X86Assembler: instance Prefetch2 Addr
+ Harpy.X86Assembler: instance Prefetch2 Ind
+ Harpy.X86Assembler: instance Prefetchnta (Disp, Reg32)
+ Harpy.X86Assembler: instance Prefetchnta Addr
+ Harpy.X86Assembler: instance Prefetchnta Ind
+ Harpy.X86Assembler: instance Show XMMReg
+ Harpy.X86Assembler: prefetch0 :: (Prefetch0 a) => a -> CodeGen e s ()
+ Harpy.X86Assembler: prefetch1 :: (Prefetch1 a) => a -> CodeGen e s ()
+ Harpy.X86Assembler: prefetch2 :: (Prefetch2 a) => a -> CodeGen e s ()
+ Harpy.X86Assembler: prefetchnta :: (Prefetchnta a) => a -> CodeGen e s ()
+ Harpy.X86Assembler: xmm0 :: XMMReg
+ Harpy.X86Assembler: xmm1 :: XMMReg
+ Harpy.X86Assembler: xmm2 :: XMMReg
+ Harpy.X86Assembler: xmm3 :: XMMReg
+ Harpy.X86Assembler: xmm4 :: XMMReg
+ Harpy.X86Assembler: xmm5 :: XMMReg
+ Harpy.X86Assembler: xmm6 :: XMMReg
+ Harpy.X86Assembler: xmm7 :: XMMReg
+ Harpy.X86CodeGen: x86_jump_pointer :: Ptr a -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch0_mem :: Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch0_membase :: Word8 -> Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch0_regp :: Word8 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch1_mem :: Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch1_membase :: Word8 -> Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch1_regp :: Word8 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch2_mem :: Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch2_membase :: Word8 -> Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetch2_regp :: Word8 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetchnta_mem :: Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetchnta_membase :: Word8 -> Word32 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_prefetchnta_regp :: Word8 -> CodeGen e s ()
+ Harpy.X86Disassembler: instance Eq InstrOperandSize
+ Harpy.X86Disassembler: instance Eq Instruction
+ Harpy.X86Disassembler: instance Eq Opcode
+ Harpy.X86Disassembler: instance Eq Operand
Files
- ANNOUNCE +60/−0
- Harpy/CodeGenMonad.hs +1/−0
- Harpy/X86Assembler.hs +70/−1
- Harpy/X86CodeGen.hs +115/−136
- Harpy/X86Disassembler.hs +31/−13
- NEWS +24/−0
- doc/larger-tutorial.lhs +2/−2
- doc/tutorial.lhs +1/−1
- examples/evaluator/README +21/−0
- harpy.cabal +2/−1
+ ANNOUNCE view
@@ -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
Harpy/CodeGenMonad.hs view
@@ -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
Harpy/X86Assembler.hs view
@@ -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
Harpy/X86CodeGen.hs view
@@ -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
Harpy/X86Disassembler.hs view
@@ -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))
NEWS view
@@ -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
doc/larger-tutorial.lhs view
@@ -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!
doc/tutorial.lhs view
@@ -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. }
+ examples/evaluator/README view
@@ -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.+
harpy.cabal view
@@ -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>