outHookAdd :: Storable a
           => Engine        -- ^ 'Unicorn' engine handle
           -> OutHook a     -- ^ OUT instruction callback
           -> a             -- ^ User-defined data. This will be passed to the
                            -- callback function
           -> Word64        -- ^ Start address
           -> Word64        -- ^ End address
           -> Emulator Hook -- ^ The hook handle on success, or an 'Error' on
                            -- failure
outHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalOutHook callback
        getResult $ ucInsnHookAdd uc HookInsn funPtr userDataPtr begin end
                                  X86.Out
    hoistEither result

-- | Register a callback for a SYSCALL instruction hook event (X86).
outHookAdd :: Storable a
           => Engine        -- ^ 'Unicorn' engine handle
           -> OutHook a     -- ^ OUT instruction callback
           -> a             -- ^ User-defined data. This will be passed to the
                            -- callback function
           -> Word64        -- ^ Start address
           -> Word64        -- ^ End address
           -> Emulator Hook
outHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalOutHook callback
        getResult $ ucInsnHookAdd uc HookInsn funPtr userDataPtr begin end
                                  X86.Out
    hoistEither result

-- | Register a callback for a SYSCALL instruction hook event (X86).
outHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalOutHook callback
        getResult $ ucInsnHookAdd uc HookInsn funPtr userDataPtr begin end
                                  X86.Out
    hoistEither result

-- | Register a callback for a SYSCALL instruction hook event (X86).