home *** CD-ROM | disk | FTP | other *** search
- /* See the file Distribution for distribution terms.
- (c) Copyright 1994 Ari Halberstadt */
-
- #pragma once
- #ifndef PATCH_LIB
- #define PATCH_LIB
-
- #include <MixedMode.h>
- #include <OSUtils.h>
-
- typedef struct PatchStructure PatchStructure;
- typedef struct PatchStructure *PatchType;
- typedef const PatchStructure *PatchCType;
-
- /* Data needed by a patch. The 'trap' member should be the first
- member of the structure. If you move the 'trap' member, then
- you must modify the _patch_return inline function (defined
- later in this file). */
- struct PatchStructure {
- UniversalProcPtr trap; /* saved trap address */
- UniversalProcPtr addr; /* address of patch routine */
- PatchType next; /* next patch */
- TrapType type; /* type of trap */
- short number; /* trap number */
- Boolean installed; /* true if patch is installed */
- };
-
- /* µThe PATCH_ENTER macro should be the first executable statement in
- your patch routine.
-
- For M68K patches, the PATCH_ENTER macro saves all of the registers
- and sets up register a5. PATCH_ENTER also ensures that the routine\
- has a stack frame so that the PATCH_RETURN macro can be used.
-
- For PPC patches, the PATCH_ENTER macro is currently a no-op. You
- don't have to do anything special on entry to a PPC patch. However,
- you should still include the PATCH_ENTER macro, for compatability
- with M68K versions of your code. */
-
- /* µThe PATCH_RETURN macro should be the last executable statement
- in your patch routine.
-
- For M68K patches, the PATCH_RETURN macro jumps to the address of the
- originally patched routine. The 'patch' parameter should be a pointer
- returned from PatchBegin.
-
- For PPC patches, the PATCH_RETURN macro is currently a no-op. You must
- use either CallUniversalProc or CallOSTrapUniversalProc to call the
- original patched routine. You should call one of these functions before
- the macro PATCH_RETURN, which you should still include in your patches
- for compatability with M68K versions of your code. */
-
- #if USESROUTINEDESCRIPTORS
-
- #define PATCH_ENTER() ((void) 0)
- #define PATCH_RETURN(patch) ((void) 0)
-
- #else /* USESROUTINEDESCRIPTORS */
-
- /* WS_INLINE_M68K */
-
- // _patch_enter expands to the following M68K assembly instructions:
- // movem.l a0-a5/d0-d7, -(sp) /* save registers */
- // movea.l #0x0904, a5 /* setup register a5 */
- // movea.l (a5), a5
- extern void _patch_enter(void)
- SIXWORDINLINE(
- 0x48E7, 0xFFFC,
- 0x2A7C, 0x0000, 0x0904,
- 0x2A55);
-
- // _patch_return expands to the following M68K assembly instructions:
- // movea.l patch, a0 /* get pointer to patch structure */
- // movea.l a6, a1 /* get current value of a6 */
- // move.l (a6), -(a6) /* shift location of saved a6 */
- // move.l PatchStructure.trap(a0), (a1) /* put patched routine's address on stack */
- // movem.l (sp)+, a0-a5/d0-d7 /* restore registers */
- // unlk a6 /* pop stack frame */
- // rts /* return to patched routine */
- #pragma parameter _patch_return(__A0)
- extern void _patch_return(PatchType patch)
- EIGHTWORDINLINE(
- 0x224E,
- 0x2D16,
- 0x22A8, 0x0000,
- 0x4CDF, 0x3FFF,
- 0x4E5E,
- 0x4E75);
-
- #define PATCH_ENTER() \
- { volatile long _patch_stack_frame; /* force stack frame of at least 4 bytes */ \
- _patch_enter(); /* initialize patch */ \
- _patch_stack_frame = 0; /* so stack frame isn't optimized out */ \
- {
-
- #define PATCH_RETURN(patch) \
- } \
- _patch_return(patch); \
- }
-
- #endif /* USESROUTINEDESCRIPTORS */
-
- void PatchInstall(PatchType patch);
- void PatchRemove(PatchType patch);
- void PatchRemoveAll(void);
- PatchType PatchBegin(UniversalProcPtr addr, short number);
- void PatchEnd(PatchType patch);
- void PatchEndAll(void);
-
- #endif /* PATCH_LIB */
-