mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-25 15:39:02 +00:00
86 lines
2.4 KiB
Haskell
86 lines
2.4 KiB
Haskell
|
-- Sample code to demonstrate how to emulate Sparc code
|
||
|
|
||
|
import Unicorn
|
||
|
import Unicorn.Hook
|
||
|
import qualified Unicorn.CPU.Sparc as Sparc
|
||
|
|
||
|
import qualified Data.ByteString as BS
|
||
|
import Data.Word
|
||
|
import qualified Numeric as N (showHex)
|
||
|
|
||
|
-- Code to be emulated
|
||
|
--
|
||
|
-- add %g1, %g2, %g3
|
||
|
sparcCode :: BS.ByteString
|
||
|
sparcCode = BS.pack [0x86, 0x00, 0x40, 0x02]
|
||
|
|
||
|
-- 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)
|
||
|
|
||
|
testSparc :: IO ()
|
||
|
testSparc = do
|
||
|
putStrLn "Emulate SPARC code"
|
||
|
|
||
|
result <- runEmulator $ do
|
||
|
-- Initialize emulator in Sparc mode
|
||
|
uc <- open ArchSparc [ModeSparc32, 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 sparcCode
|
||
|
|
||
|
-- Initialize machine registers
|
||
|
regWrite uc Sparc.G1 0x1230
|
||
|
regWrite uc Sparc.G2 0x6789
|
||
|
regWrite uc Sparc.G3 0x5555
|
||
|
|
||
|
-- Tracing all basic blocks with customized callback
|
||
|
blockHookAdd uc hookBlock () 1 0
|
||
|
|
||
|
-- Tracing all instructions with customized callback
|
||
|
codeHookAdd uc hookCode () 1 0
|
||
|
|
||
|
-- Emulate machine code in infinite time (last param = Nothing), or
|
||
|
-- when finishing all the code
|
||
|
let codeLen = codeLength sparcCode
|
||
|
start uc address (address + codeLen) Nothing Nothing
|
||
|
|
||
|
-- Return results
|
||
|
g3 <- regRead uc Sparc.G3
|
||
|
|
||
|
return g3
|
||
|
case result of
|
||
|
Right g3 -> do
|
||
|
-- Now print out some registers
|
||
|
putStrLn ">>> Emulation done. Below is the CPU context"
|
||
|
putStrLn $ ">>> G3 = 0x" ++ showHex g3
|
||
|
Left err -> putStrLn $ "Failed with error: " ++ show err ++ " (" ++
|
||
|
strerror err ++ ")"
|
||
|
|
||
|
main :: IO ()
|
||
|
main =
|
||
|
testSparc
|