mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-26 08:35:39 +00:00
143 lines
4.5 KiB
Haskell
143 lines
4.5 KiB
Haskell
|
-- Sample code to demonstrate how to emulate m68k code
|
||
|
|
||
|
import Unicorn
|
||
|
import Unicorn.Hook
|
||
|
import qualified Unicorn.CPU.M68k as M68k
|
||
|
|
||
|
import qualified Data.ByteString as BS
|
||
|
import Data.Word
|
||
|
import qualified Numeric as N (showHex)
|
||
|
|
||
|
-- Code to be emulated
|
||
|
--
|
||
|
-- movq #-19, %d3
|
||
|
m68kCode :: BS.ByteString
|
||
|
m68kCode = BS.pack [0x76, 0xed]
|
||
|
|
||
|
-- Memory address where emulation starts
|
||
|
address :: Word64
|
||
|
address = 0x10000
|
||
|
|
||
|
-- Pretty-print integral as hex
|
||
|
showHex :: (Integral a, Show a) => a -> String
|
||
|
showHex =
|
||
|
flip N.showHex ""
|
||
|
|
||
|
-- Calculate code length
|
||
|
codeLength :: Num a => BS.ByteString -> a
|
||
|
codeLength =
|
||
|
fromIntegral . BS.length
|
||
|
|
||
|
hookBlock :: BlockHook ()
|
||
|
hookBlock _ addr size _ =
|
||
|
putStrLn $ ">>> Tracing basic block at 0x" ++ showHex addr ++
|
||
|
", block size = 0x" ++ (maybe "0" showHex size)
|
||
|
|
||
|
hookCode :: CodeHook ()
|
||
|
hookCode _ addr size _ =
|
||
|
putStrLn $ ">>> Tracing instruction at 0x" ++ showHex addr ++
|
||
|
", instruction size = 0x" ++ (maybe "0" showHex size)
|
||
|
|
||
|
testM68k :: IO ()
|
||
|
testM68k = do
|
||
|
putStrLn "Emulate M68K code"
|
||
|
|
||
|
result <- runEmulator $ do
|
||
|
-- Initialize emulator in M68K mode
|
||
|
uc <- open ArchM68k [ModeBigEndian]
|
||
|
|
||
|
-- Map 2MB memory for this emulation
|
||
|
memMap uc address (2 * 1024 * 1024) [ProtAll]
|
||
|
|
||
|
-- Write machine code to be emulated to memory
|
||
|
memWrite uc address m68kCode
|
||
|
|
||
|
-- Initialize machine registers
|
||
|
regWrite uc M68k.D0 0x0000
|
||
|
regWrite uc M68k.D1 0x0000
|
||
|
regWrite uc M68k.D2 0x0000
|
||
|
regWrite uc M68k.D3 0x0000
|
||
|
regWrite uc M68k.D4 0x0000
|
||
|
regWrite uc M68k.D5 0x0000
|
||
|
regWrite uc M68k.D6 0x0000
|
||
|
regWrite uc M68k.D7 0x0000
|
||
|
|
||
|
regWrite uc M68k.A0 0x0000
|
||
|
regWrite uc M68k.A1 0x0000
|
||
|
regWrite uc M68k.A2 0x0000
|
||
|
regWrite uc M68k.A3 0x0000
|
||
|
regWrite uc M68k.A4 0x0000
|
||
|
regWrite uc M68k.A5 0x0000
|
||
|
regWrite uc M68k.A6 0x0000
|
||
|
regWrite uc M68k.A7 0x0000
|
||
|
|
||
|
regWrite uc M68k.Pc 0x0000
|
||
|
regWrite uc M68k.Sr 0x0000
|
||
|
|
||
|
-- Tracing all basic blocks with customized callback
|
||
|
blockHookAdd uc hookBlock () 1 0
|
||
|
|
||
|
-- Tracing all instruction
|
||
|
codeHookAdd uc hookCode () 1 0
|
||
|
|
||
|
-- Emulate machine code in infinite time (last param = Nothing), or
|
||
|
-- when finishing all the code
|
||
|
let codeLen = codeLength m68kCode
|
||
|
start uc address (address + codeLen) Nothing Nothing
|
||
|
|
||
|
-- Return the results
|
||
|
d0 <- regRead uc M68k.D0
|
||
|
d1 <- regRead uc M68k.D1
|
||
|
d2 <- regRead uc M68k.D2
|
||
|
d3 <- regRead uc M68k.D3
|
||
|
d4 <- regRead uc M68k.D4
|
||
|
d5 <- regRead uc M68k.D5
|
||
|
d6 <- regRead uc M68k.D6
|
||
|
d7 <- regRead uc M68k.D7
|
||
|
|
||
|
a0 <- regRead uc M68k.A0
|
||
|
a1 <- regRead uc M68k.A1
|
||
|
a2 <- regRead uc M68k.A2
|
||
|
a3 <- regRead uc M68k.A3
|
||
|
a4 <- regRead uc M68k.A4
|
||
|
a5 <- regRead uc M68k.A5
|
||
|
a6 <- regRead uc M68k.A6
|
||
|
a7 <- regRead uc M68k.A7
|
||
|
|
||
|
pc <- regRead uc M68k.Pc
|
||
|
sr <- regRead uc M68k.Sr
|
||
|
|
||
|
return (d0, d1, d2, d3, d4, d5, d6, d7,
|
||
|
a0, a1, a2, a3, a4, a5, a6, a7,
|
||
|
pc, sr)
|
||
|
case result of
|
||
|
Right (d0, d1, d2, d3, d4, d5, d6, d7,
|
||
|
a0, a1, a2, a3, a4, a5, a6, a7,
|
||
|
pc, sr) -> do
|
||
|
-- Now print out some registers
|
||
|
putStrLn ">>> Emulation done. Below is the CPU context"
|
||
|
putStrLn $ ">>> A0 = 0x" ++ showHex a0 ++
|
||
|
"\t\t>>> D0 = 0x" ++ showHex d0
|
||
|
putStrLn $ ">>> A1 = 0x" ++ showHex a1 ++
|
||
|
"\t\t>>> D1 = 0x" ++ showHex d1
|
||
|
putStrLn $ ">>> A2 = 0x" ++ showHex a2 ++
|
||
|
"\t\t>>> D2 = 0x" ++ showHex d2
|
||
|
putStrLn $ ">>> A3 = 0x" ++ showHex a3 ++
|
||
|
"\t\t>>> D3 = 0x" ++ showHex d3
|
||
|
putStrLn $ ">>> A4 = 0x" ++ showHex a4 ++
|
||
|
"\t\t>>> D4 = 0x" ++ showHex d4
|
||
|
putStrLn $ ">>> A5 = 0x" ++ showHex a5 ++
|
||
|
"\t\t>>> D5 = 0x" ++ showHex d5
|
||
|
putStrLn $ ">>> A6 = 0x" ++ showHex a6 ++
|
||
|
"\t\t>>> D6 = 0x" ++ showHex d6
|
||
|
putStrLn $ ">>> A7 = 0x" ++ showHex a7 ++
|
||
|
"\t\t>>> D7 = 0x" ++ showHex d7
|
||
|
putStrLn $ ">>> PC = 0x" ++ showHex pc
|
||
|
putStrLn $ ">>> SR = 0x" ++ showHex sr
|
||
|
Left err -> putStrLn $ "Failed with error: " ++ show err ++ " (" ++
|
||
|
strerror err ++ ")"
|
||
|
|
||
|
main :: IO ()
|
||
|
main =
|
||
|
testM68k
|