+ trapaddr <- getCurrentOffset
+ mov (Addr 0x00000000) eax -- it's a trap
+ return $ Just (trapaddr, StaticField $ buildStaticFieldID cls cpidx)
+ emit' (GETSTATIC cpidx) = do
+ trapaddr <- getCurrentOffset
+ mov eax (Addr 0x00000000) -- it's a trap
+ push eax
+ return $ Just (trapaddr, StaticField $ buildStaticFieldID cls cpidx)
+
+ emit' (GETFIELD x) = do
+ pop eax -- this pointer
+ -- like: 099db064 ff b0 e4 14 00 00 pushl 5348(%eax)
+ trapaddr <- emitSigIllTrap 6
+ let patcher reip = do
+ let (cname, fname) = buildFieldOffset cls x
+ offset <- liftIO $ fromIntegral <$> getFieldOffset cname fname
+ push32RelEax (Disp offset) -- get field
+ return reip
+ return $ Just (trapaddr, ObjectField patcher)
+ emit' (PUTFIELD x) = do
+ pop ebx -- value to write
+ pop eax -- this pointer
+ -- like: 4581fc6b 89 98 30 7b 00 00 movl %ebx,31536(%eax)
+ trapaddr <- emitSigIllTrap 6
+ let patcher reip = do
+ let (cname, fname) = buildFieldOffset cls x
+ offset <- liftIO $ fromIntegral <$> getFieldOffset cname fname
+ mov32RelEbxEax (Disp offset) -- set field
+ return reip
+ return $ Just (trapaddr, ObjectField patcher)
+
+ emit' (INSTANCEOF cpidx) = do
+ pop eax
+ -- 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
+ trapaddr <- emitSigIllTrap 2
+ let patcher resp reip = do
+ error "no athrow for you, sorry"
+ emitSigIllTrap 2
+ return reip
+ 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)