|
Mac OS 9
|
Mixed Mode Manager Interfaces. More...
#include <MacTypes.h>Go to the source code of this file.
Data Structures | |
| struct | RoutineRecord |
| struct | RoutineDescriptor |
| struct | MixedModeStateRecord |
Macros | |
| #define | GetCurrentArchitecture() 0 |
| #define | BUILD_ROUTINE_DESCRIPTOR(procInfo, procedure) |
| #define | BUILD_FAT_ROUTINE_DESCRIPTOR(m68kProcInfo, m68kProcPtr, powerPCProcInfo, powerPCProcPtr) |
| #define | NewRoutineDescriptor(theProc, theProcInfo, theISA) ((UniversalProcPtr)theProc) |
| #define | DisposeRoutineDescriptor(theUPP) |
| #define | SIZE_CODE(size) |
| #define | RESULT_SIZE(sizeCode) ((ProcInfoType)(sizeCode) << kResultSizePhase) |
| #define | STACK_ROUTINE_PARAMETER(whichParam, sizeCode) |
| #define | DISPATCHED_STACK_ROUTINE_PARAMETER(whichParam, sizeCode) |
| #define | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(sizeCode) ((ProcInfoType)(sizeCode) << kDispatchedSelectorSizePhase) |
| #define | REGISTER_RESULT_LOCATION(whichReg) ((ProcInfoType)(whichReg) << kRegisterResultLocationPhase) |
| #define | REGISTER_ROUTINE_PARAMETER(whichParam, whichReg, sizeCode) |
| #define | SPECIAL_CASE_PROCINFO(specialCaseCode) (kSpecialCase | ((ProcInfoType)(specialCaseCode) << 4)) |
| #define | STACK_UPP_TYPE(name) name |
| #define | REGISTER_UPP_TYPE(name) name |
| #define | TVECTOR_UPP_TYPE(name) name |
| #define | CALL_ZERO_PARAMETER_UPP(upp, procInfo) (*(upp))() |
| #define | CALL_ONE_PARAMETER_UPP(upp, procInfo, p1) (*(upp))((p1)) |
| #define | CALL_TWO_PARAMETER_UPP(upp, procInfo, p1, p2) (*(upp))((p1), (p2)) |
| #define | CALL_THREE_PARAMETER_UPP(upp, procInfo, p1, p2, p3) (*(upp))((p1), (p2), (p3)) |
| #define | CALL_FOUR_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4) (*(upp))((p1), (p2), (p3), (p4)) |
| #define | CALL_FIVE_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5) (*(upp))((p1), (p2), (p3), (p4), (p5)) |
| #define | CALL_SIX_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6)) |
| #define | CALL_SEVEN_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6), (p7)) |
| #define | CALL_EIGHT_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8)) |
| #define | CALL_NINE_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8, p9) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9)) |
| #define | CALL_TEN_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9), (p10)) |
| #define | CALL_ELEVEN_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) (*(upp))((p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9), (p10), (p11)) |
| #define | CALL_TWELVE_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) |
| #define | CALL_THIRTEEN_PARAMETER_UPP(upp, procInfo, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) |
Typedefs | |
| typedef unsigned short | CallingConventionType |
| typedef SInt8 | ISAType |
| typedef SInt8 | RTAType |
| typedef unsigned short | registerSelectorType |
| typedef unsigned long | ProcInfoType |
| typedef unsigned short | RoutineFlagsType |
| typedef struct RoutineRecord | RoutineRecord |
| typedef RoutineRecord * | RoutineRecordPtr |
| typedef RoutineRecordPtr * | RoutineRecordHandle |
| typedef UInt8 | RDFlagsType |
| typedef struct RoutineDescriptor | RoutineDescriptor |
| typedef RoutineDescriptor * | RoutineDescriptorPtr |
| typedef RoutineDescriptorPtr * | RoutineDescriptorHandle |
| typedef struct MixedModeStateRecord | MixedModeStateRecord |
Enumerations | |
| enum | { kRoutineDescriptorVersion = 7 } |
| enum | { _MixedModeMagic = 0xAAFE } |
| enum | { kCurrentMixedModeStateRecord = 1 } |
| enum | { kPascalStackBased = 0 , kCStackBased = 1 , kRegisterBased = 2 , kD0DispatchedPascalStackBased = 8 , kD1DispatchedPascalStackBased = 12 , kD0DispatchedCStackBased = 9 , kStackDispatchedPascalStackBased = 14 , kThinkCStackBased = 5 } |
| enum | { kM68kISA = 0 , kPowerPCISA = 1 } |
| enum | { kOld68kRTA = 0 << 4 , kPowerPCRTA = 0 << 4 , kCFM68kRTA = 1 << 4 } |
| enum | { kRegisterD0 = 0 , kRegisterD1 = 1 , kRegisterD2 = 2 , kRegisterD3 = 3 , kRegisterD4 = 8 , kRegisterD5 = 9 , kRegisterD6 = 10 , kRegisterD7 = 11 , kRegisterA0 = 4 , kRegisterA1 = 5 , kRegisterA2 = 6 , kRegisterA3 = 7 , kRegisterA4 = 12 , kRegisterA5 = 13 , kRegisterA6 = 14 , kCCRegisterCBit = 16 , kCCRegisterVBit = 17 , kCCRegisterZBit = 18 , kCCRegisterNBit = 19 , kCCRegisterXBit = 20 } |
| enum | { kNoByteCode = 0 , kOneByteCode = 1 , kTwoByteCode = 2 , kFourByteCode = 3 } |
| enum | { kProcDescriptorIsAbsolute = 0x00 , kProcDescriptorIsRelative = 0x01 } |
| enum | { kFragmentIsPrepared = 0x00 , kFragmentNeedsPreparing = 0x02 } |
| enum | { kUseCurrentISA = 0x00 , kUseNativeISA = 0x04 } |
| enum | { kPassSelector = 0x00 , kDontPassSelector = 0x08 } |
| enum | { kRoutineIsNotDispatchedDefaultRoutine = 0x00 , kRoutineIsDispatchedDefaultRoutine = 0x10 } |
| enum | { kProcDescriptorIsProcPtr = 0x00 , kProcDescriptorIsIndex = 0x20 } |
| enum | { kSelectorsAreNotIndexable = 0x00 , kSelectorsAreIndexable = 0x01 } |
| enum | { kCallingConventionWidth = 4 , kCallingConventionPhase = 0 , kCallingConventionMask = 0x0F , kResultSizeWidth = 2 , kResultSizePhase = kCallingConventionWidth , kResultSizeMask = 0x30 , kStackParameterWidth = 2 , kStackParameterPhase = (kCallingConventionWidth + kResultSizeWidth) , kStackParameterMask , kRegisterResultLocationWidth = 5 , kRegisterResultLocationPhase , kRegisterParameterWidth = 5 , kRegisterParameterPhase , kRegisterParameterMask = 0x7FFFF800 , kRegisterParameterSizePhase = 0 , kRegisterParameterSizeWidth = 2 , kRegisterParameterWhichPhase = kRegisterParameterSizeWidth , kRegisterParameterWhichWidth , kDispatchedSelectorSizeWidth = 2 , kDispatchedSelectorSizePhase , kDispatchedParameterPhase , kSpecialCaseSelectorWidth = 6 , kSpecialCaseSelectorPhase = kCallingConventionWidth , kSpecialCaseSelectorMask = 0x03F0 } |
| enum | { kSpecialCase = 0x000F } |
| enum | { kSpecialCaseHighHook = 0 , kSpecialCaseCaretHook = 0 , kSpecialCaseEOLHook = 1 , kSpecialCaseWidthHook = 2 , kSpecialCaseTextWidthHook = 2 , kSpecialCaseNWidthHook = 3 , kSpecialCaseDrawHook = 4 , kSpecialCaseHitTestHook = 5 , kSpecialCaseTEFindWord = 6 , kSpecialCaseProtocolHandler = 7 , kSpecialCaseSocketListener = 8 , kSpecialCaseTERecalc = 9 , kSpecialCaseTEDoText = 10 , kSpecialCaseGNEFilterProc = 11 , kSpecialCaseMBarHook = 12 } |
Functions | |
| UniversalProcPtr | NewRoutineDescriptor (ProcPtr theProc, ProcInfoType theProcInfo, ISAType theISA) |
| void | DisposeRoutineDescriptor (UniversalProcPtr theUPP) |
| UniversalProcPtr | NewFatRoutineDescriptor (ProcPtr theM68kProc, ProcPtr thePowerPCProc, ProcInfoType theProcInfo) |
| long | CallUniversalProc (UniversalProcPtr theProcPtr, ProcInfoType procInfo,...) |
| long | CallOSTrapUniversalProc (UniversalProcPtr theProcPtr, ProcInfoType procInfo,...) |
Mixed Mode Manager Interfaces.
For bug reports, consult the following page on the World Wide Web:
http://developer.apple.com/bugreporter/
| #define BUILD_FAT_ROUTINE_DESCRIPTOR | ( | m68kProcInfo, | |
| m68kProcPtr, | |||
| powerPCProcInfo, | |||
| powerPCProcPtr | |||
| ) |
a macro which creates a static instance of a fat routine descriptor
| #define BUILD_ROUTINE_DESCRIPTOR | ( | procInfo, | |
| procedure | |||
| ) |
Macros for building static Routine Descriptors (not available in Carbon) A macro which creates a static instance of a non-dispatched routine descriptor
| #define CALL_THIRTEEN_PARAMETER_UPP | ( | upp, | |
| procInfo, | |||
| p1, | |||
| p2, | |||
| p3, | |||
| p4, | |||
| p5, | |||
| p6, | |||
| p7, | |||
| p8, | |||
| p9, | |||
| p10, | |||
| p11, | |||
| p12, | |||
| p13 | |||
| ) |
| #define CALL_TWELVE_PARAMETER_UPP | ( | upp, | |
| procInfo, | |||
| p1, | |||
| p2, | |||
| p3, | |||
| p4, | |||
| p5, | |||
| p6, | |||
| p7, | |||
| p8, | |||
| p9, | |||
| p10, | |||
| p11, | |||
| p12 | |||
| ) |
| #define CALL_ZERO_PARAMETER_UPP | ( | upp, | |
| procInfo | |||
| ) | (*(upp))() |
CALL_©_PARAMETER_UPP - used in Call©Proc macros
Example:
#define CallIOCompletionProc(userRoutine, paramBlock) \
CALL_TWO_PARAMETER_UPP((userRoutine), uppIOCompletionProcInfo,
(paramBlock))
| #define DISPATCHED_STACK_ROUTINE_PARAMETER | ( | whichParam, | |
| sizeCode | |||
| ) |
DISPATCHED_STACK_ROUTINE_PARAMETER - Return a parameter field of a ProcInfo, for a dispatched, stack based routine. The same macro is used regardless of the type of dispatching. whichParam - which parameter sizeCode
| #define DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE | ( | sizeCode | ) | ((ProcInfoType)(sizeCode) << kDispatchedSelectorSizePhase) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE - Return a the selector size field of a ProcInfo for a dispatched, stack based routine. The same macro is used regardless of the type of dispatching. sizeCode - size code
| #define REGISTER_RESULT_LOCATION | ( | whichReg | ) | ((ProcInfoType)(whichReg) << kRegisterResultLocationPhase) |
REGISTER_RESULT_LOCATION - Return the Result Location field of a ProcInfo, given the location. whichReg - which register
| #define REGISTER_ROUTINE_PARAMETER | ( | whichParam, | |
| whichReg, | |||
| sizeCode | |||
| ) |
REGISTER_ROUTINE_PARAMETER - Return a parameter field of a ProcInfo for a register based routine.
| #define RESULT_SIZE | ( | sizeCode | ) | ((ProcInfoType)(sizeCode) << kResultSizePhase) |
RESULT_SIZE - Return the result field of a ProcInfo, given the return object©s size. This is the same for all ProcInfos sizeCode - size code
| #define SIZE_CODE | ( | size | ) |
CALL_NOT_IN_CARBON !TARGET_CPU_68K || TARGET_RT_MAC_CFM TARGET_CPU_68K
Macros for building ProcInfos. Examples:
uppModalFilterProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(Boolean))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DialogRef))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EventRecord*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(short*))),
uppDeskHookProcInfo = kRegisterBased | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(Boolean))) | REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(EventRecord*)))
uppGXSpoolResourceProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(gxSpoolFile))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(ResType))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
uppTEFindWordProcInfo = SPECIAL_CASE_PROCINFO( 6 ),
SIZE_CODE - Return the size code for an object, given its size in bytes. size - size of an object in bytes
| #define SPECIAL_CASE_PROCINFO | ( | specialCaseCode | ) | (kSpecialCase | ((ProcInfoType)(specialCaseCode) << 4)) |
SPECIAL_CASE_PROCINFO - Returns the procInfo constant for the following special cases:
High Hook & Caret Hook - (see I-379)
C calling conventions, Rect on stack, pointer in A3, no return
value EOL Hook - (see VI-15-26) Register-based; inputs in D0, A3, A4; output is Z flag of status register Width Hook - (see VI-15-27) Register-based; inputs in D0, D1, A0, A3, A4; output in D1 NWidth Hook - (see VI-15-27) Register-based; inputs in D0, D1, D2, A0, A2, A3, A4; output in D1 TextWidthHook - (see VI-15-28) Register-based; inputs in D0, D1, A0, A3, A4; output in D1 DrawHook - (see VI-15-28) Register-based; inputs in D0, D1, A0, A3, A4; no output HitTestHook - (See VI-15-29) Register-based; inputs in D0, D1, D2, A0, A3, A4; outputs in D0, D1, D2 FindWord - (see VI-15-30) Register-based; inputs in D0, D2, A3, A4; outputs in D0, D1 ADBRoutines - (see V-371) Register-based; inputs in A0, A1, A2, D0; no outputs ProtocolHandler - (see II-326) Register-based; inputs in A0, A1, A2, A3, A4, D1.w; output in Z SocketListener - (see II-329) Register-based; inputs in A0, A1, A2, A3, A4, D0.b, D1.w; output in Z Reclac - (see I-391) Register-based; inputs in A3, D7; outputs in D2, D3, D4 DoText - (see I-391) Register-based; inputs in A3, D3, D4, D7; outputs in A0, D0 GNEFilterProc - (see tech note 85) Register & Stack Based; inputs in A1, D0 & on the stack; outputs on the stack MenuBarHook - (see I-356) Register & Stack Based; input on the stack; output in D0
| #define STACK_ROUTINE_PARAMETER | ( | whichParam, | |
| sizeCode | |||
| ) |
STACK_ROUTINE_PARAMETER - Return a parameter field of a ProcInfo, for a simple, non-dispatched, stack based routine. whichParam - which parameter sizeCode - size code
| #define STACK_UPP_TYPE | ( | name | ) | name |
STACK_UPP_TYPE - used in typedefs to create ©UPP type REGISTER_UPP_TYPE - used in typedefs to create ©UPP type TVECTOR_UPP_TYPE - used in typedefs to create ©UPP type
Example:
typedef STACK_UPP_TYPE(ModalFilterProcPtr) ModalFilterUPP; typedef REGISTER_UPP_TYPE(IOCompletionProcPtr) IOCompletionUPP;
other runtimes
| typedef unsigned short CallingConventionType |
Calling Conventions
| typedef SInt8 ISAType |
ISA Types
| typedef unsigned long ProcInfoType |
Mixed Mode Routine Records
| typedef UInt8 RDFlagsType |
Mixed Mode Routine Descriptors Definitions of the Routine Descriptor Flag Bits
| typedef unsigned short RoutineFlagsType |
Routine Flag Bits
| typedef SInt8 RTAType |
RTA Types
| anonymous enum |
Mixed Mode constants Current Routine Descriptor Version
| anonymous enum |
MixedModeMagic Magic Cookie/Trap number
| anonymous enum |
MixedModeState Version for CFM68K Mixed Mode
| anonymous enum |
| anonymous enum |
SizeCodes we use everywhere
| anonymous enum |
CALL_NOT_IN_CARBON Mixed Mode ProcInfos
| anonymous enum |
| long CallOSTrapUniversalProc | ( | UniversalProcPtr | theProcPtr, |
| ProcInfoType | procInfo, | ||
| ... | |||
| ) |
| long CallUniversalProc | ( | UniversalProcPtr | theProcPtr, |
| ProcInfoType | procInfo, | ||
| ... | |||
| ) |
CALL_NOT_IN_CARBON TARGET_CPU_68K && !TARGET_RT_MAC_CFM CallUniversalProc is defined for all targets except classic 68k code. This will catch accidental calls from classic 68K code that previously only showed up as linker errors. CallUniversalProc()
| void DisposeRoutineDescriptor | ( | UniversalProcPtr | theUPP | ) |
| UniversalProcPtr NewFatRoutineDescriptor | ( | ProcPtr | theM68kProc, |
| ProcPtr | thePowerPCProc, | ||
| ProcInfoType | theProcInfo | ||
| ) |
CALL_NOT_IN_CARBON NewFatRoutineDescriptor()
| UniversalProcPtr NewRoutineDescriptor | ( | ProcPtr | theProc, |
| ProcInfoType | theProcInfo, | ||
| ISAType | theISA | ||
| ) |
NOTES ON USING ROUTINE DESCRIPTOR FUNCTIONS
When calling these routine from classic 68k code there are two possible intentions.
The first is source compatibility with code ported to CFM (either PowerPC or 68k CFM). When the code is compiled for CFM the functions create routine descriptors that can be used by the mixed mode manager operating on that machine. When the code is compiled for classic 68k these functions do nothing so that the code will run on Macintoshes that do not have a mixed mode manager. The dual nature of these functions is achieved by turning the CFM calls into "no-op" macros for classic 68k: You can put "NewRoutineDescriptor" in your source, compile it for any runtime or instruction set architecture, and it will run correctly on the intended runtime/instruction platform. All without source changes and/or conditional source.
The other intention is for code that "knows" that it is executing as classic 68k runtime and is specifically trying to call code of another architecture using mixed mode. Since the routines were designed with classic <-> CFM source compatibility in mind this second case is treated special. For classic 68k code to create routines descriptors for use by mixed mode it must call the "Trap" versions of the routines (NewRoutineDescriptorTrap). These versions are only available to classic 68k callers: rigging the interfaces to allow calling them from CFM code will result in runtime failure because no shared library implements or exports the functions.
This almost appears seamless until you consider "fat" routine descriptors and the advent of CFM-68K. What does "fat" mean? CFM-68K is not emulated on PowerPC and PowerPC is not emulated on CFM-68K. It makes no sense to create a routine descriptor having both a CFM-68K routine and a PowerPC native routine pointer. Therefore "fat" is defined to be a mix of classic and CFM for the hardware's native instruction set: on PowerPC fat is classic and PowerPC native, on a 68k machine with CFM-68K installed fat is classic and CFM-68K.
By definition fat routine descriptors are only constructed by code that is aware of the architecture it is executing as and that another architecture exists. Source compatibility between code intented as pure classic and pure CFM is not an issue and so NewFatRoutineDescriptor is not available when building pure classic code.
NewFatRoutineDescriptorTrap is available to classic code on both PowerPC and CFM-68K. The classic code can use the code fragment manager routine "FindSymbol" to obtain the address of a routine in a shared library and then construct a routine descriptor with both the CFM routine and classic routine. NewRoutineDescriptor()