packages feed

x86-64bit 0.3 → 0.3.1

raw patch · 7 files changed

+72/−24 lines, 7 files

Files

CHANGELOG.md view
@@ -1,3 +1,12 @@+# Version 0.3.1
+
+-   use multi-byte nop operations for padding
+-   `preBuild` operation (may speed up code generation)
+-   branch-predicition friendlier if-then-else
+-   not-condition pattern: `N`  
+    usage example: `j (N E)` which is the same as `j NE`
+-   bugfix: fix if-then-else condition
+
 # Version 0.3
 
 -   simpler API for label handling  
CodeGen/X86.hs view
@@ -27,13 +27,16 @@     , addr16
     , addr32
     , addr64
-    , ipBase
+    , ipRel
+    , ipRel8
     -- * Operands
     , Access (..)
     , Operand
     , resizeOperand
+    , ipRelValue
     -- * Conditions
     , Condition
+    , pattern N
     , pattern O
     , pattern NO
     , pattern B,  pattern C
@@ -134,6 +137,7 @@     -- * Compilation
     , Callable
     , compile
+    , preBuild
     -- * Calling convention
     , saveNonVolatile
     , arg1, arg2, arg3, arg4
CodeGen/X86/Asm.hs view
@@ -222,8 +222,16 @@ pattern NoIndex = Nothing pattern IndexReg a b = Just (a, b) -ipBase l = IPMemOp $ LabelRelValue S32 l+-- | intruction pointer relative address+ipRel :: Label -> Operand rw s+ipRel l = IPMemOp $ LabelRelValue S32 l +ipRelValue l = ImmOp $ LabelRelValue S32 l++-- | `ipRel` with specialized type+ipRel8 :: Label -> Operand rw S8+ipRel8 = ipRel+ instance IsSize s => Show (Reg s) where     show = \case         XMM i -> "xmm" ++ show i@@ -526,6 +534,12 @@         0xe -> "le"         0xf -> "nle" +pattern N cc <- (notCond -> cc)+  where N = notCond++notCond :: Condition -> Condition+notCond (Condition c) = Condition $ c `xor` 1+ -------------------------------------------------------------- asm code lines  data CodeLine where@@ -546,8 +560,8 @@     Pop_  :: Operand RW S64 -> CodeLine     Push_ :: Operand r  S64 -> CodeLine -    Call_ :: Operand RW S64 -> CodeLine-    Jmpq_ :: Operand RW S64 -> CodeLine+    Call_ :: Operand r S64 -> CodeLine+    Jmpq_ :: Operand r S64 -> CodeLine      J_    :: Condition -> Maybe Size -> Label -> CodeLine     Jmp_  :: Maybe Size -> Label -> CodeLine
CodeGen/X86/CodeGen.hs view
@@ -20,7 +20,7 @@ import Numeric import Data.Maybe import Data.Monoid-import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as V import Data.Bits import Data.Int import Data.Word@@ -179,6 +179,12 @@   where     sizes = map (\(s, c) -> sizeLen s + length c) ss +-- prebuild code+preBuild :: Code -> Code+preBuild c = CodeM $ tell $ Prebuilt (compactCode (buildCode lc)) lc+  where+    lc = withLabels c+ ------------------------------------------------------- code to code builder  instance Show Code where@@ -189,7 +195,7 @@       where         ss = snd . runWriter . flip evalStateT 0 . showCode $ c         (x, s) = buildCode c-        bs = V.toList $ V.replicate s 0 V.// [p | Right p <- x]+        bs = V.toList $ compactCode (x, s)         is = [i | Left i <- x]          showLine addr [] s = s@@ -199,11 +205,9 @@          maxbytes = 12 -{--codeBytes c = Bytes $ V.toList $ V.replicate s 0 V.// [p | Right p <- x]-  where-    (x, s) = buildTheCode c--}+compactCode :: (CodeBuilderRes, Int) -> V.Vector Word8+compactCode (x, s) = V.replicate s 0 V.// [p | Right p <- x]+ buildTheCode :: Code -> (CodeBuilderRes, Int) buildTheCode = buildCode . withLabels @@ -215,7 +219,7 @@ mkCodeBuilder :: LCode -> CodeBuilder mkCodeBuilder = \case     CodeLine x _ -> x-    Group x _ -> x+    Prebuilt v _ -> mkCodeBuilder' (Align_ 4) <> codeBytes (V.toList v)     AppendCode x _ _ -> x     EmptyCode -> mempty @@ -228,6 +232,21 @@ withLabels =     snd . runWriter . flip evalStateT 0 . unCodeM +-- multi-byte nop operations+nops :: Int -> Bytes+nops = \case+    0 -> []+    1 -> [0x90]+    2 -> [0x66, 0x90]+    3 -> [0x0f, 0x1f, 0x00]+    4 -> [0x0f, 0x1f, 0x40, 0x00]+    5 -> [0x0f, 0x1f, 0x44, 0x00, 0x00]+    6 -> [0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00]+    7 -> [0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00]+    8 -> [0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00]+    9 -> [0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00]+    x -> nops 9 ++ nops (x-9)+ mkCodeBuilder' :: CodeLine -> CodeBuilder mkCodeBuilder' = \case     Add_  a b -> op2 0x0 a b@@ -278,7 +297,6 @@     Inc_  a -> op1 0x7f 0x0 a     Dec_  a -> op1 0x7f 0x1 a     Call_ a -> op1' 0xff 0x2 a-    Jmpq_ a -> op1' 0xff 0x4 a      Movd_ a@OpXMM b -> sse 0x6e a b     Movd_ b a@OpXMM -> sse 0x7e a b@@ -333,6 +351,9 @@     Jmp_ (Just S32) l -> codeByte 0xe9 <> mkRef S32 4 l     Jmp_ Nothing    l -> mkAutoRef [(S8, [0xeb]), (S32, [0xe9])] l +    Jmpq_ (ImmOp (LabelRelValue S32 l)) -> mkAutoRef [(S8, [0xeb]), (S32, [0xe9])] l+    Jmpq_ a -> op1' 0xff 0x4 a+     Label_ -> CodeBuilder 0 0 $ do         bs <- lift $ mdo             (n, ls, ps) <- getPast@@ -359,7 +380,7 @@             sendPast (ma + s-1, mls)             ~(ma, mls) <- getFuture             let n' = fromIntegral $ ((fromIntegral n - 1 :: Int64) .|. (fromIntegral s - 1)) + 1-            return $ zip [n..] $ replicate (n' - n) 0x90+            return $ zip [n..] $ nops $ n' - n         tell $ Right <$> bs    where@@ -504,7 +525,7 @@     op1 :: IsSize s => Word8 -> Word8 -> Operand r s -> CodeBuilder     op1 a b c = op1_ a b c mempty -    op1' :: Word8 -> Word8 -> Operand RW S64 -> CodeBuilder+    op1' :: Word8 -> Word8 -> Operand r S64 -> CodeBuilder     op1' r1 r2 dest = regprefix S32 dest (codeByte r1 <> reg8 r2 dest) mempty      shiftOp :: IsSize s => Word8 -> Operand RW s -> Operand r S8 -> CodeBuilder@@ -521,7 +542,7 @@ -------------------------------------------------------------- asm codes  data LCode where-    Group       :: CodeBuilder -> LCode -> LCode+    Prebuilt    :: V.Vector Word8 -> LCode -> LCode     EmptyCode   :: LCode     AppendCode  :: CodeBuilder -> LCode -> LCode -> LCode     CodeLine    :: CodeBuilder -> CodeLine -> LCode@@ -616,6 +637,6 @@ showCode = \case     EmptyCode  -> return ()     AppendCode _ a b -> showCode a >> showCode b-    Group _ c -> codeLine "{" >> showCode c >> codeLine "}"+    Prebuilt _ c -> showCodeLine (Align_ 4) >> codeLine "{" >> showCode c >> codeLine "}"     CodeLine _ x -> showCodeLine x 
CodeGen/X86/Tests.hs view
@@ -100,7 +100,7 @@ 
 genRegs = RegOp <$> arbitrary
 
-genIPBase = pure $ ipBase $ Label 0
+genIPBase = pure $ ipRel $ Label 0
 
 instance Arbitrary (Addr S64) where
     arbitrary = suchThat (Addr <$> base <*> disp <*> index) ok
CodeGen/X86/Utils.hs view
@@ -35,7 +35,7 @@ 
 -- | if-then-else
 if_ cc a b = mdo
-    j cc l1
+    j (N cc) l1
     a
     jmp l2
     l1 <- label
@@ -43,11 +43,8 @@     l2 <- label
     return ()
 
-lea8 :: IsSize s => Operand RW s -> Operand RW S8 -> Code
-lea8 = lea
-
 leaData r d = mdo
-    lea8 r $ ipBase l1
+    lea r $ ipRel8 l1
     jmp l2
     l1 <- label
     db $ toBytes d
x86-64bit.cabal view
@@ -1,5 +1,5 @@ name:                x86-64bit
-version:             0.3
+version:             0.3.1
 homepage:            https://github.com/divipp/x86-64
 synopsis:            Runtime code generation for x86 64 bit machine code
 description:         The primary goal of x86-64bit is to provide a lightweight assembler for machine generated 64 bit x86 assembly instructions. See README.md for further details.
@@ -32,6 +32,7 @@     CodeGen.X86.Utils
     CodeGen.X86.Tests
 
+  default-language:    Haskell2010
   other-extensions:
     NoMonomorphismRestriction
     LambdaCase
@@ -78,4 +79,6 @@ 
   if os(windows)
     build-depends: Win32
+
+  default-language:    Haskell2010