x86-64bit 0.3 → 0.3.1
raw patch · 7 files changed
+72/−24 lines, 7 files
Files
- CHANGELOG.md +9/−0
- CodeGen/X86.hs +5/−1
- CodeGen/X86/Asm.hs +17/−3
- CodeGen/X86/CodeGen.hs +34/−13
- CodeGen/X86/Tests.hs +1/−1
- CodeGen/X86/Utils.hs +2/−5
- x86-64bit.cabal +4/−1
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