#include "debug.h"
module Mate.X86CodeGen where
-import Prelude hiding (and)
+import Prelude hiding (and, div)
import Data.Binary
import Data.BinaryState
import Data.Int
import Mate.Utilities
import Mate.ClassPool
import Mate.Strings
+#ifdef DEBUG
+import Text.Printf
+#endif
foreign import ccall "dynamic"
type CompileInfo = (EntryPoint, BBStarts, Int, TrapMap)
-emitFromBB :: B.ByteString -> Class Direct -> MapBB -> CodeGen e s (CompileInfo, [Instruction])
-emitFromBB method cls hmap = do
+emitFromBB :: B.ByteString -> MethodSignature -> Class Direct -> MapBB -> CodeGen e s (CompileInfo, [Instruction])
+emitFromBB method sig cls hmap = do
llmap <- sequence [newNamedLabel ("bb_" ++ show x) | (x,_) <- M.toList hmap]
let lmap = zip (Prelude.fst $ unzip $ M.toList hmap) llmap
ep <- getEntryPoint
-- note, the "mi" has the wrong class reference here.
-- we figure that out at run-time, in the methodpool,
-- depending on the method-table-ptr
- return $ Just (calladdr, II mi)
+ let imm8 = is8BitOffset offset
+ return $ Just (calladdr + (if imm8 then 3 else 6), II imm8 mi)
emit' (INVOKEVIRTUAL cpidx) = do
-- get methodInfo entry
let mi@(MethodInfo methodname objname msig@(MethodSignature args _)) = buildMethodID cls cpidx
-- note, the "mi" has the wrong class reference here.
-- we figure that out at run-time, in the methodpool,
-- depending on the method-table-ptr
- return $ Just (calladdr, VI mi)
+ let imm8 = is8BitOffset offset
+ return $ Just (calladdr + (if imm8 then 3 else 6), VI imm8 mi)
emit' (PUTSTATIC cpidx) = do
pop eax
trapaddr <- getCurrentOffset
emit :: J.Instruction -> CodeGen e s ()
emit POP = add esp (4 :: Word32) -- drop value
emit DUP = push (Disp 0, esp)
+ emit DUP_X1 = do pop eax; pop ebx; push eax; push ebx; push eax
emit AASTORE = emit IASTORE
emit IASTORE = do
pop eax -- value
mtable <- liftIO $ getMethodTable objname
mov (Disp 0, eax) mtable
emit (CHECKCAST _) = nop -- TODO(bernhard): ...
+ -- TODO(bernhard): ...
+ emit (INSTANCEOF _) = do
+ pop eax
+ push (1 :: Word32)
+ emit ATHROW = nop -- TODO(bernhard): ...
emit I2C = do
pop eax
and eax (0x000000ff :: Word32)
push eax
emit (BIPUSH val) = push (fromIntegral val :: Word32)
emit (SIPUSH val) = push (fromIntegral (fromIntegral val :: Int16) :: Word32)
+ emit ACONST_NULL = push (0 :: Word32)
+ emit (ICONST_M1) = push ((-1) :: Word32)
emit (ICONST_0) = push (0 :: Word32)
emit (ICONST_1) = push (1 :: Word32)
emit (ICONST_2) = push (2 :: Word32)
emit (LDC2 x) = do
value <- case constsPool cls M.! x of
(CString s) -> liftIO $ getUniqueStringAddr s
- _ -> error "LDCI... missing impl."
+ e -> error $ "LDCI... missing impl.: " ++ show e
push value
emit (GETFIELD x) = do
offset <- emitFieldOffset x
emit IADD = do pop ebx; pop eax; add eax ebx; push eax
emit ISUB = do pop ebx; pop eax; sub eax ebx; push eax
emit IMUL = do pop ebx; pop eax; mul ebx; push eax
+ emit IDIV = do pop ebx; pop eax; xor edx edx; div ebx; push eax
+ emit IREM = do pop ebx; pop eax; xor edx edx; div ebx; push edx
emit IXOR = do pop ebx; pop eax; xor eax ebx; push eax
+ emit INEG = do pop eax; neg eax; push eax
emit (IINC x imm) =
add (Disp (cArgs x), ebp) (s8_w32 imm)
+ emit (IFNONNULL x) = emit (IF C_NE x)
+ emit (IFNULL x) = emit (IF C_EQ x)
emit (IF_ACMP cond x) = emit (IF_ICMP cond x)
emit (IF_ICMP cond _) = do
pop eax -- value2
thisMethodArgCnt :: Word32
thisMethodArgCnt = isNonStatic + fromIntegral (length args)
where
- (Just m) = lookupMethod method cls
- (MethodSignature args _) = methodSignature m
+ (Just m) = lookupMethodSig method sig cls
+ (MethodSignature args _) = sig
isNonStatic = if S.member ACC_STATIC (methodAccessFlags m)
then 0 else 1 -- one argument for the this pointer
s8_w32 :: Word8 -> Word32
s8_w32 w8 = fromIntegral s8
where s8 = fromIntegral w8 :: Int8
+
+ is8BitOffset :: Word32 -> Bool
+ is8BitOffset w32 = s32 < 128 && s32 > (-127)
+ where s32 = fromIntegral w32 :: Int32