+ -- place something like `mov edx $mtable_of_objref' instead
+ trapaddr <- emitSigIllTrap 4
+ push (0 :: Word32)
+ let patcher reax reip = do
+ emitSigIllTrap 4
+ let classname = buildClassID cls cpidx
+ check <- liftIO $ isInstanceOf (fromIntegral reax) classname
+ if check
+ then push (1 :: Word32)
+ else push (0 :: Word32)
+ return (reip + 4)
+ return $ Just (trapaddr, InstanceOf patcher)
+ emit' (NEW objidx) = do
+ let objname = buildClassID cls objidx
+ -- place something like `push $objsize' instead
+ trapaddr <- emitSigIllTrap 5
+ callMalloc
+ -- 0x13371337 is just a placeholder; will be replaced with mtable ptr
+ mov (Disp 0, eax) (0x13371337 :: Word32)
+ mov (Disp 4, eax) (0x1337babe :: Word32)
+ let patcher reip = do
+ objsize <- liftIO $ getObjectSize objname
+ push32 objsize
+ callMalloc
+ mtable <- liftIO $ getMethodTable objname
+ mov (Disp 0, eax) mtable
+ mov (Disp 4, eax) (0x1337babe :: Word32)
+ return reip
+ return $ Just (trapaddr, NewObject patcher)
+
+ emit' ATHROW = do
+ pop eax
+ push eax
+ mov eax (Disp 0, eax)
+ trapaddr <- emitSigIllTrap 2
+ let patcher :: TrapPatcherEaxEsp
+ patcher reax resp reip = do
+ liftIO $ printfJit $ printf "reip: %d\n" (fromIntegral reip :: Word32)
+ liftIO $ printfJit $ printf "reax: %d\n" (fromIntegral reax :: Word32)
+ (_, jnmap) <- liftIO $ getMethodEntry miThis
+ liftIO $ printfJit $ printf "size: %d\n" (BI.size jnmap)
+ liftIO $ printfJit $ printf "jnmap: %s\n" (show $ BI.toList jnmap)
+ -- TODO: (-4) is a hack (due to the insns above)
+ let jpc = fromIntegral (jnmap BI.!> (fromIntegral reip - 4))
+ let exceptionmap = rawExcpMap method
+ liftIO $ printfJit $ printf "exmap: %s\n" (show $ M.toList exceptionmap)
+ let key =
+ case find f $ M.keys exceptionmap of
+ Just x -> x
+ Nothing -> error "exception: no handler found. (TODO1)"
+ where
+ f (x, y) = jpc >= x && jpc <= y
+ liftIO $ printfJit $ printf "exception: key is: %s\n" (show key)
+ let handlerJPCs = exceptionmap M.! key
+ let f (x, y) = do x' <- getMethodTable x; return (fromIntegral x', y)
+ handlers <- liftIO $ mapM f handlerJPCs
+ liftIO $ printfJit $ printf "exception: handlers: %s\n" (show handlers)
+ let handlerJPC =
+ case find ((==) reax . fst) handlers of
+ Just x -> x
+ Nothing -> error "exception: no handler found (TODO2)"
+ let handlerNPC = jnmap BI.! (fromIntegral $ snd handlerJPC)
+ liftIO $ printfJit $ printf "exception: handler at: 0x%08x\n" handlerNPC
+ emitSigIllTrap 2
+ return $ fromIntegral handlerNPC
+ return $ Just (trapaddr, ThrowException patcher)
+
+ emit' insn = emit insn >> return Nothing
+
+ emit :: J.Instruction -> CodeGen e s ()
+ emit POP = add esp (ptrSize :: Word32) -- drop value
+ emit DUP = push (Disp 0, esp)
+ emit DUP_X1 = do pop eax; pop ebx; push eax; push ebx; push eax
+ emit DUP_X2 = do pop eax; pop ebx; pop ecx; push eax; push ecx; push ebx; push eax
+ emit AASTORE = emit IASTORE
+ emit IASTORE = do
+ pop eax -- value
+ pop ebx -- offset
+ add ebx (1 :: Word32)
+ pop ecx -- aref
+ mov (ecx, ebx, S4) eax
+ emit CASTORE = do
+ pop eax -- value
+ pop ebx -- offset
+ add ebx (1 :: Word32)
+ pop ecx -- aref
+ mov (ecx, ebx, S1) eax -- TODO(bernhard): char is two byte
+ emit AALOAD = emit IALOAD
+ emit IALOAD = do
+ pop ebx -- offset
+ add ebx (1 :: Word32)
+ pop ecx -- aref
+ push (ecx, ebx, S4)
+ emit CALOAD = do
+ pop ebx -- offset
+ add ebx (1 :: Word32)
+ pop ecx -- aref
+ push (ecx, ebx, S1) -- TODO(bernhard): char is two byte
+ emit ARRAYLENGTH = do
+ pop eax
+ push (Disp 0, eax)
+ emit (ANEWARRAY _) = emit (NEWARRAY 10) -- 10 == T_INT
+ emit (NEWARRAY typ) = do
+ let tsize = case decodeS (0 :: Integer) (B.pack [typ]) of
+ T_INT -> 4
+ T_CHAR -> 2
+ _ -> error "newarray: type not implemented yet"
+ -- get length from stack, but leave it there
+ mov eax (Disp 0, esp)
+ mov ebx (tsize :: Word32)
+ -- multiple amount with native size of one element
+ mul ebx -- result is in eax
+ add eax (ptrSize :: Word32) -- for "length" entry
+ -- push amount of bytes to allocate
+ push eax
+ callMalloc
+ pop eax -- ref to arraymemory
+ pop ebx -- length
+ mov (Disp 0, eax) ebx -- store length at offset 0
+ push eax -- push ref again
+
+ emit (CHECKCAST _) = 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 (ICONST_3) = push (3 :: Word32)
+ emit (ICONST_4) = push (4 :: Word32)
+ emit (ICONST_5) = push (5 :: Word32)
+
+ emit (ALOAD_ x) = emit (ILOAD_ x)
+ emit (ILOAD_ x) = emit (ILOAD $ cArgs_ x)
+ emit (ALOAD x) = emit (ILOAD x)
+ emit (ILOAD x) = push (Disp (cArgs x), ebp)
+
+ emit (ASTORE_ x) = emit (ISTORE_ x)
+ emit (ISTORE_ x) = emit (ISTORE $ cArgs_ x)
+ emit (ASTORE x) = emit (ISTORE x)
+ emit (ISTORE x) = do
+ pop eax
+ mov (Disp (cArgs x), ebp) eax
+
+ emit (LDC1 x) = emit (LDC2 $ fromIntegral x)
+ emit (LDC2 x) = do
+ value <- case constsPool cls M.! x of
+ (CString s) -> liftIO $ getUniqueStringAddr s
+ (CInteger i) -> liftIO $ return i
+ e -> error $ "LDCI... missing impl.: " ++ show e
+ push value
+
+ 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 IUSHR = do pop ecx; pop eax; sar eax cl; 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
+ pop ebx -- value1
+ cmp ebx eax -- intel syntax is swapped (TODO(bernhard): test that plz)
+ emitIF cond
+
+ emit (IF cond _) = do
+ pop eax -- value1
+ cmp eax (0 :: Word32) -- TODO(bernhard): test that plz
+ emitIF cond
+
+ emit (GOTO _ ) = do
+ let sid = case successor bb of OneTarget t -> t; _ -> error "bad"
+ jmp $ getLabel sid lmap
+
+ emit RETURN = do mov esp ebp; pop ebp; ret
+ emit ARETURN = emit IRETURN
+ emit IRETURN = do pop eax; emit RETURN
+ emit invalid = error $ "insn not implemented yet: " ++ show invalid
+
+ emitIF :: CMP -> CodeGen e s ()
+ emitIF cond = let
+ sid = case successor bb of TwoTarget _ t -> t; _ -> error "bad"
+ l = getLabel sid lmap
+ sid2 = case successor bb of TwoTarget t _ -> t; _ -> error "bad"
+ l2 = getLabel sid2 lmap
+ in do
+ case cond of
+ C_EQ -> je l; C_NE -> jne l
+ C_LT -> jl l; C_GT -> jg l
+ C_GE -> jge l; C_LE -> jle l
+ -- TODO(bernhard): ugly workaround, to get broken emitBB working
+ -- (it didn't work for gnu/classpath/SystemProperties.java)
+ jmp l2
+
+ emitSigIllTrap :: Int -> CodeGen e s NativeWord
+ emitSigIllTrap traplen = do
+ when (traplen < 2) (error "emitSigIllTrap: trap len too short")
+ trapaddr <- getCurrentOffset
+ -- 0xffff causes SIGILL
+ emit8 (0xff :: Word8); emit8 (0xff :: Word8)
+ -- fill rest up with NOPs
+ sequence_ [nop | _ <- [1 .. (traplen - 2)]]
+ return trapaddr
+
+
+ -- for locals we use a different storage
+ cArgs :: Word8 -> Word32
+ cArgs x = ptrSize * (argcount - x' + isLocal)
+ where
+ x' = fromIntegral x
+ argcount = rawArgCount method
+ isLocal = if x' >= argcount then (-1) else 1
+
+ cArgs_ :: IMM -> Word8
+ cArgs_ x = case x of I0 -> 0; I1 -> 1; I2 -> 2; I3 -> 3
+