x86-64bit 0.4.4 → 0.4.5
raw patch · 7 files changed
+70/−30 lines, 7 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- CodeGen.X86: type IndexReg s = Maybe (Scale, Reg s)
+ CodeGen.X86: S1 :: Size
+ CodeGen.X86: [HighReg] :: Word8 -> Reg S8
+ CodeGen.X86: [NormalReg] :: Word8 -> Reg s
+ CodeGen.X86: [Refl] :: EqT s s
+ CodeGen.X86: [XMM] :: Word8 -> Reg S128
+ CodeGen.X86: bsf :: IsSize s => Operand RW s -> Operand r s -> Code
+ CodeGen.X86: bsr :: IsSize s => Operand RW s -> Operand r s -> Code
+ CodeGen.X86: bswap :: IsSize s => Operand RW s -> Code
+ CodeGen.X86: bt :: IsSize s => Operand r s -> Operand RW s -> Code
+ CodeGen.X86: data EqT s s'
+ CodeGen.X86: data IndexReg s
+ CodeGen.X86: sizeEqCheck :: forall s s' f g. (IsSize s, IsSize s') => f s -> g s' -> Maybe (EqT s s')
- CodeGen.X86: if_ :: Condition -> CodeM a -> CodeM a1 -> CodeM ()
+ CodeGen.X86: if_ :: Condition -> CodeM a1 -> CodeM a -> CodeM ()
Files
- CHANGELOG.md +4/−0
- CodeGen/X86.hs +15/−7
- CodeGen/X86/Asm.hs +16/−9
- CodeGen/X86/CodeGen.hs +20/−10
- CodeGen/X86/Tests.hs +3/−3
- TODO.md +11/−0
- x86-64bit.cabal +1/−1
CHANGELOG.md view
@@ -1,3 +1,7 @@+# Version 0.4.5 + +- fix build with newer base + # Version 0.4.4 - export some useful data types
CodeGen/X86.hs view
@@ -8,8 +8,10 @@ , Size (..) , HasSize (..) , IsSize+ , EqT (..)+ , sizeEqCheck -- * Registers- , Reg , FromReg (..)+ , Reg (..) , FromReg (..) -- ** 64 bit registers , rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 -- ** 32 bit registers@@ -62,13 +64,14 @@ , align , Label , label- -- ** Control+ -- ** Control instructions , j , jmp , jmpq , call , ret- -- ** Flags+ , nop+ -- ** Flag manipulation , cmc , clc , stc@@ -78,17 +81,23 @@ , std , pushf , popf+ -- *** Conditionals , cmp , test+ , bt+ , bsf+ , bsr -- ** Arithmetic , inc , dec- , not_ , neg , add , adc , sub , sbb+ , lea+ -- ** Bit manipulation+ , not_ , and_ , or_ , xor_@@ -99,9 +108,8 @@ , shl , shr , sar- , lea- -- ** Other- , nop+ -- ** Byte manipulation/move+ , bswap , xchg , mov , cmov
CodeGen/X86/Asm.hs view
@@ -63,11 +63,12 @@ ------------------------------------------------------- sizes -- | The size of a register (in bits)-data Size = S8 | S16 | S32 | S64 | S128+data Size = S1 | S8 | S16 | S32 | S64 | S128 deriving (Eq, Ord) instance Show Size where show = \case+ S1 -> "bit" S8 -> "byte" S16 -> "word" S32 -> "dword"@@ -100,6 +101,7 @@ -- | Singleton type for size data SSize (s :: Size) where+ SSize1 :: SSize S1 SSize8 :: SSize S8 SSize16 :: SSize S16 SSize32 :: SSize S32@@ -108,6 +110,7 @@ instance HasSize (SSize s) where size = \case+ SSize1 -> S1 SSize8 -> S8 SSize16 -> S16 SSize32 -> S32@@ -117,6 +120,7 @@ class IsSize (s :: Size) where ssize :: SSize s +instance IsSize S1 where ssize = SSize1 instance IsSize S8 where ssize = SSize8 instance IsSize S16 where ssize = SSize16 instance IsSize S32 where ssize = SSize32@@ -220,15 +224,13 @@ deriving (Eq) type BaseReg s = Maybe (Reg s)-type IndexReg s = Maybe (Scale, Reg s)+data IndexReg s = NoIndex | IndexReg Scale (Reg s)+ deriving (Eq) type Displacement = Maybe Int32 pattern NoDisp = Nothing pattern Disp a = Just a -pattern NoIndex = Nothing-pattern IndexReg a b = Just (a, b)- -- | intruction pointer (RIP) relative address ipRel :: Label -> Operand rw s ipRel l = IPMemOp $ LabelRelValue S32 l@@ -315,8 +317,8 @@ signum = error "signum @Operand" instance Monoid (Addr s) where- mempty = Addr (getFirst mempty) (getFirst mempty) (getFirst mempty)- Addr a b c `mappend` Addr a' b' c' = Addr (getFirst $ First a <> First a') (getFirst $ First b <> First b') (getFirst $ First c <> First c')+ mempty = Addr (getFirst mempty) (getFirst mempty) mempty+ Addr a b c `mappend` Addr a' b' c' = Addr (getFirst $ First a <> First a') (getFirst $ First b <> First b') (c <> c') instance Monoid (IndexReg s) where mempty = NoIndex@@ -553,9 +555,10 @@ data CodeLine where Ret_, Nop_, PushF_, PopF_, Cmc_, Clc_, Stc_, Cli_, Sti_, Cld_, Std_ :: CodeLine - Inc_, Dec_, Not_, Neg_ :: IsSize s => Operand RW s -> CodeLine- Add_, Or_, Adc_, Sbb_, And_, Sub_, Xor_, Cmp_, Test_, Mov_ :: IsSize s => Operand RW s -> Operand r s -> CodeLine+ Inc_, Dec_, Not_, Neg_, Bswap :: IsSize s => Operand RW s -> CodeLine+ Add_, Or_, Adc_, Sbb_, And_, Sub_, Xor_, Cmp_, Test_, Mov_, Bsf, Bsr :: IsSize s => Operand RW s -> Operand r s -> CodeLine Rol_, Ror_, Rcl_, Rcr_, Shl_, Shr_, Sar_ :: IsSize s => Operand RW s -> Operand r S8 -> CodeLine+ Bt :: IsSize s => Operand r s -> Operand RW s -> CodeLine Movdqa_, Paddb_, Paddw_, Paddd_, Paddq_, Psubb_, Psubw_, Psubd_, Psubq_, Pxor_ :: Operand RW S128 -> Operand r S128 -> CodeLine Psllw_, Pslld_, Psllq_, Pslldq_, Psrlw_, Psrld_, Psrlq_, Psrldq_, Psraw_, Psrad_ :: Operand RW S128 -> Operand r S8 -> CodeLine@@ -604,6 +607,9 @@ Xor_ op1 op2 -> showOp2 "xor" op1 op2 Cmp_ op1 op2 -> showOp2 "cmp" op1 op2 Test_ op1 op2 -> showOp2 "test" op1 op2+ Bsf op1 op2 -> showOp2 "bsf" op1 op2+ Bsr op1 op2 -> showOp2 "bsr" op1 op2+ Bt op1 op2 -> showOp2 "bt" op1 op2 Rol_ op1 op2 -> showOp2 "rol" op1 op2 Ror_ op1 op2 -> showOp2 "ror" op1 op2 Rcl_ op1 op2 -> showOp2 "rcl" op1 op2@@ -641,6 +647,7 @@ Dec_ op -> showOp1 "dec" op Not_ op -> showOp1 "not" op Neg_ op -> showOp1 "neg" op+ Bswap op -> showOp1 "bswap" op Pop_ op -> showOp1 "pop" op Push_ op -> showOp1 "push" op Call_ op -> showOp1 "call" op
CodeGen/X86/CodeGen.hs view
@@ -71,7 +71,7 @@ regs :: IsSize s => Operand r s -> [SReg] regs = \case- MemOp (Addr r _ i) -> foldMap (pure . SReg) r ++ foldMap (pure . SReg . snd) i+ MemOp (Addr r _ i) -> foldMap (pure . SReg) r ++ case i of NoIndex -> []; IndexReg _ x -> [SReg x] RegOp r -> [SReg r] _ -> mempty @@ -280,13 +280,16 @@ where (dest', src') = if isMemOp src then (src, dest) else (dest, src) - Mov_ dest@(RegOp r) ((if size dest == S64 then mkImm S32 <> mkImmS S32 <> mkImmS S64 else mkImmS (size dest)) -> FJust ((se, si), im))+ Mov_ dest@(RegOp r) ((if size dest == S64 then mkImmU S32 <> mkImm S64 else mkImm (size dest)) -> FJust ((se, si), im)) | (se, si, size dest) /= (True, S32, S64) -> regprefix si dest (oneReg (0x16 .|. indicator (size dest /= S8)) r) im | otherwise -> regprefix'' dest 0x63 (reg8 0x0 dest) im Mov_ dest@(size -> s) (mkImmNo64 s -> FJust (_, im)) -> regprefix'' dest 0x63 (reg8 0x0 dest) im Mov_ dest src -> op2' 0x44 dest $ noImm (show (dest, src)) src Cmov_ (Condition c) dest src | size dest /= S8 -> regprefix2 src dest $ codeByte 0x0f <> codeByte (0x40 .|. c) <> reg2x8 dest src+ Bsf dest src | size dest /= S8 -> regprefix2 src dest $ codeByte 0x0f <> codeByte 0xbc <> reg2x8 dest src+ Bsr dest src | size dest /= S8 -> regprefix2 src dest $ codeByte 0x0f <> codeByte 0xbd <> reg2x8 dest src+ Bt src dest | size dest /= S8 -> regprefix2 src dest $ codeByte 0x0f <> codeByte 0xa3 <> reg2x8 dest src Lea_ dest src | size dest /= S8 -> regprefix2' (resizeOperand' dest src) dest 0x46 $ reg2x8 dest src where@@ -297,6 +300,8 @@ Neg_ a -> op1 0x7b 0x3 a Inc_ a -> op1 0x7f 0x0 a Dec_ a -> op1 0x7f 0x1 a+ Bswap a@RegOp{} | size a >= S32 -> op1 0x07 0x1 a+ Bswap a -> error $ "wrong bswap operand: " ++ show a Call_ (ImmOp (LabelRelValue S32 l)) -> codeByte 0xe8 <> mkRef S32 4 l Call_ a -> op1' 0xff 0x2 a@@ -329,8 +334,8 @@ Pop_ dest@(RegOp r) -> regprefix S32 dest (oneReg 0x0b r) mempty Pop_ dest -> regprefix S32 dest (codeByte 0x8f <> reg8 0x0 dest) mempty - Push_ (mkImmS S8 -> FJust (_, im)) -> codeByte 0x6a <> im- Push_ (mkImmS S32 -> FJust (_, im)) -> codeByte 0x68 <> im+ Push_ (mkImmS S8 -> FJust (_, im)) -> codeByte 0x6a <> im+ Push_ (mkImm S32 -> FJust (_, im)) -> codeByte 0x68 <> im Push_ dest@(RegOp r) -> regprefix S32 dest (oneReg 0x0a r) mempty Push_ dest -> regprefix S32 dest (codeByte 0xff <> reg8 0x6 dest) mempty @@ -392,10 +397,11 @@ convertImm True b (ImmOp (LabelRelValue s d)) | b == s = FJust $ (,) (True, b) $ mkRef s (sizeLen s) d convertImm _ _ _ = FNothing - mkImmS, mkImm, mkImmNo64 :: Size -> Operand r s -> First ((Bool, Size), CodeBuilder)+ mkImmS, mkImmU, mkImm, mkImmNo64 :: Size -> Operand r s -> First ((Bool, Size), CodeBuilder) mkImmS = convertImm True- mkImm = convertImm False- mkImmNo64 s = mkImmS (no64 s)+ mkImmU = convertImm False+ mkImm s = mkImmS s <> mkImmU s+ mkImmNo64 s = mkImm (no64 s) xchg_a :: IsSize s => Operand r s -> CodeBuilder xchg_a dest@(RegOp r) | size dest /= S8 = regprefix (size dest) dest (oneReg 0x12 r) mempty@@ -466,7 +472,7 @@ sse op a@OpXMM b = regprefix S128 b (codeByte 0x0f <> codeByte op <> reg2x8 a b) mempty sseShift :: Word8 -> Word8 -> Word8 -> Operand RW S128 -> Operand r S8 -> CodeBuilder- sseShift op x op' a@OpXMM b@(mkImm S8 -> FJust (_, i)) = regprefix S128 b (codeByte 0x0f <> codeByte op <> reg8 x a) i+ sseShift op x op' a@OpXMM b@(mkImmU S8 -> FJust (_, i)) = regprefix S128 b (codeByte 0x0f <> codeByte op <> reg8 x a) i -- TODO: xmm argument extension :: HasSize a => a -> Word8 -> CodeBuilder@@ -474,7 +480,7 @@ extbits :: Operand r s -> Word8 extbits = \case- MemOp (Addr b _ i) -> maybe 0 indexReg b .|. maybe 0 ((`shiftL` 1) . indexReg . snd) i+ MemOp (Addr b _ i) -> maybe 0 indexReg b .|. case i of NoIndex -> 0; IndexReg _ x -> indexReg x `shiftL` 1 RegOp r -> indexReg r _ -> 0 where@@ -533,7 +539,7 @@ shiftOp :: IsSize s => Word8 -> Operand RW s -> Operand r S8 -> CodeBuilder shiftOp c dest (ImmOp (Immediate 1)) = op1 0x68 c dest- shiftOp c dest (mkImm S8 -> FJust (_, i)) = op1_ 0x60 c dest i+ shiftOp c dest (mkImmU S8 -> FJust (_, i)) = op1_ 0x60 c dest i shiftOp c dest RegCl = op1 0x69 c dest shiftOp _ _ _ = error "invalid shift operands" @@ -569,6 +575,10 @@ dec a = mkCodeLine (Dec_ a) not_ a = mkCodeLine (Not_ a) neg a = mkCodeLine (Neg_ a)+bswap a = mkCodeLine (Bswap a)+bsf a b = mkCodeLine (Bsf a b)+bsr a b = mkCodeLine (Bsr a b)+bt a b = mkCodeLine (Bt a b) add a b = mkCodeLine (Add_ a b) or_ a b = mkCodeLine (Or_ a b) adc a b = mkCodeLine (Adc_ a b)
CodeGen/X86/Tests.hs view
@@ -110,8 +110,8 @@ instance Arbitrary (Addr S64) where arbitrary = suchThat (Addr <$> base <*> disp <*> index) ok where - ok (Addr Nothing _ Nothing) = False - ok (Addr Nothing _ (Just (sc, _))) = sc == s1 + ok (Addr Nothing _ NoIndex) = False + ok (Addr Nothing _ (IndexReg sc _)) = sc == s1 ok _ = True base = oneof [ return Nothing @@ -393,7 +393,7 @@ Disp v -> fromIntegral v rx = resizeOperand $ RegOp x :: Operand RW S64 return (v, ((leaData rx v >> mov helper (fromIntegral d') >> sub rx helper >> setvi) >>)) - mkVal helper o@(MemOp (Addr Nothing d (Just (sc, x)))) = do + mkVal helper o@(MemOp (Addr Nothing d (IndexReg sc x))) = do v <- arbVal $ size o let d' = case d of
TODO.md view
@@ -1,4 +1,15 @@ +# Instructions DSL++The main problem is typing the instructions in Haskell.++Unsolved problems:++- How to support instructions with variable arguments (like imul)?+- How to support instructions with mixed sized arguments (like bt)?+- How to prevent more misuse statically?++ # Support more instructions - pusha / popa ?
x86-64bit.cabal view
@@ -1,5 +1,5 @@ name: x86-64bit -version: 0.4.4 +version: 0.4.5 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.