The Trap Manager is a collection of routines that lets you add extra capabilities to system software routines.
In order to execute system software routines, system software takes advantage of the unimplemented instruction feature of the MC680x0 family of microprocessors, which are the central processing units (CPUs) used in the Macintosh family of computers.
The MC680x0, like other microprocessors, executes a stream of instructions. Information encoded in an instruction indicates the operation to be performed by the microprocessor. The MC680x0 family of microprocessors recognizes a defined set of instructions. When the microprocessor encounters an instruction that it doesn’t recognize, an exception is generated. An exception refers to bus errors, interrupts, and unimplemented instructions. When an exception occurs, the microprocessor suspends normal execution and transfers control to an appropriate exception handler.
In the MC680x0 family of microprocessors, all instructions starting with the hexadecimal digit $A are unimplemented instructions. These unimplemented instructions are also called A-line instructions . System software uses these unimplemented A-line instructions to execute system software routines. When you call a system software routine, the call to the system software routine is translated into an A-line instruction. The MC680x0 microprocessor doesn’t recognize this A-line instruction, and transfers control to an exception handler.
System software provides an exception handler, called a trap dispatcher, to handle exceptions generated by A-line instructions. Whenever a MC680x0 microprocessor encounters an A-line instruction, an exception is generated, and the microprocessor transfers control to the trap dispatcher. An exception generated by an A-line instruction is called a trap.
When the trap dispatcher receives the A-line instruction, it looks into a table, called a trap dispatch table, to find the address of the called system software routine. After the trap dispatcher retrieves the address, it transfers control to the specified system software routine.
You can use the Trap Manager routines to read from and write to the two trap dispatch tables maintained by system software.
Trap Dispatch Tables
System software uses trap dispatch tables to locate the address of system software routines. System software maintains two trap dispatch tables: an Operating System trap dispatch table and a Toolbox trap dispatch table.
At system startup time, system software builds the trap dispatch tables and places them in RAM. The Operating System trap dispatch table contains 256 entries, and the Toolbox trap dispatch table contains 1024 entries. Each entry in the Operating System trap dispatch table contains a 32-bit address of an Operating System routine, and each entry in the Toolbox trap dispatch table contains a 32-bit address of a Toolbox routine. The system software routines can be located in either ROM or RAM.
Process for Accessing System Software Routines
As previously described, when your application calls a system software routine, an A-line instruction is sent to the microprocessor. The microprocessor does not recognize this instruction, and an exception is generated. This exception is then handled by the trap dispatcher. When the trap dispatcher receives the A-line instruction, it looks into one of the two trap dispatch tables to find the address of the called system software routine. When the trap dispatcher retrieves the address, it transfers control to the specified system software routine. For example, Figure 8-3 illustrates a call to the Toolbox procedure, FillRect. When the application calls the FillRect procedure, an exception is generated. The trap dispatcher looks into the Toolbox trap dispatch table to find the address of the FillRect procedure. When the address is found, the trap dispatcher transfers control to the FillRect procedure.
Patches and System Software Routines
You can modify the trap dispatch table so that the address that gets returned to the trap dispatcher points to a different routine instead of the intended system software routine; this is useful if you want to augment or override an existing system software routine. The routine that augment an existing system software routine is called a patch. The method of augmenting or overriding a system software routine is called patching a trap.
For example, you can augment the FillRect procedure with your own procedure MyPatchFillRect. Figure 8-4 illustrates another call to the Toolbox procedure FillRect. When the application calls the FillRect procedure the application-defined patch MyPatchFillRect is executed first. After the application-defined patch MyPatchFillRect completes its primary action, it transfers control (through a JMP instruction) to the original FillRect procedure.
When your application calls a Toolbox or an Operating System routine, an A-line instruction is sent to the microprocessor. Each A-line instruction contains information about the called system software routine.
The high-order 4 bits of an A-line instruction have the hexadecimal value $A, hence the name A-line instruction. Bit 11 of the A-line instruction indicates the type of system software routine to be invoked: a value of 0 in bit 11 indicates an Operating System routine, a value of 1 in bit 11 indicates a Toolbox routine. The trap number in an A-line instruction is used as an index into the appropriate dispatch table. The meaning of the flags vary accordingly to the type of A-line instruction.
When your application calls a system software routine (thereby generating an exception), the microprocessor pushes an exception stack frame onto the stack. After pushing the exception stack frame on the stack, the microprocessor transfers control to the trap dispatcher.
The trap dispatcher discards the status register and vector offset. Depending on whether the A-line instruction is used to invoke an Operating System routine or a Toolbox routine, the trap dispatcher deals with the stack and registers in two very different ways, as described in the next section, “A-line Instructions for Operating System Routines.”
A-Line Instructions for Operating System Routines
An Operating System trap is an exception that is caused by an A-line instruction that executes an Operating System routine.
When dispatching an Operating System trap, the trap dispatcher extracts the trap number from the A-line instruction and uses it as an index into the Operating System trap dispatch table. The entry in the Operating System trap dispatch table contains the address of the desired Operating System routine.
Bit 11 tells the trap dispatcher that this A-line instruction invokes an Operating System routine. Two flag bits, bit 10 and bit 9, are reserved for use by the Operating System routine itself and are discussed in detail in “Flag Bits” on page 8-14. Bit 8 indicates whether the value in register A0 is returned from the Operating System routine. If bit 8 is 0, the value in register A0 is returned from the Operating System routine. If bit 8 is 1, the value in register A0 is not returned by the Operating System routine. As previously described, the trap number is in bits 7–0 and is used to determine which of the 256 possible Operating System routines is executed.
For example, a call to the Operating System function GetPtrSize is translated to the A-line instruction $A021. This A-line instruction causes the microprocessor to transfer control to the trap dispatcher, which deals with any instruction of the form $Axxx. The trap dispatcher first saves registers D0, D1, D2, A1, and, if bit 8 is 0, A0. The trap dispatcher places the A-line instruction itself into the low-order word of register D1 so that the Operating System routine can inspect the flag bits. Next, the trap dispatcher examines the other bits in the A-line instruction. The value (0) of bit 11 indicates that GetPtrSize is an Operating System routine, and that the value in bits 7–0 is the index into the Operating System trap dispatch table. The trap dispatcher uses the index (which is 33 in this example) to find the address of the GetPtrSize function in the Operating System trap dispatch table. When the address is found, the trap dispatcher transfers control to the GetPtrSize function.
The Operating System routine may alter any of the registers D0–D2 and A0–A2, but it must preserve registers D3–D7 and A3–A6. The Operating System routine may return information in register D0 (and A0 if bit 8 is set). To return to the trap dispatcher, the Operating System routine executes the RTS (return from subroutine) instruction.
When the trap dispatcher resumes control, first it restores the value of registers D1, D2, A1, A2, and, if bit 8 is 0, A0. The values in registers D0 and, if bit 8 is 1, in A0 are not restored.
A-Line Instructions for Toolbox Routines
A Toolbox trap is an exception that is caused by an A-line instruction that executes a Toolbox routine.
When dispatching a Toolbox trap, the trap dispatcher extracts the trap number from the A-line instruction and uses it as an index into the Toolbox trap dispatch table. The index points to the entry in the Toolbox trap dispatch table that contains the address of the desired Toolbox routine. Figure 8-9 illustrates an A-line instruction that is used to access a Toolbox routine.
The Auto-Pop Bit
The auto-pop bit is bit 10 in an A-line instruction for a Toolbox routine. Some language systems prefer to generate jump-subroutine calls (JSR) to intermediate routines, called glue routines, which then call Toolbox routines instead of executing the Toolbox routine directly. This glue method would normally interfere with Toolbox traps because the return address of the glue subroutine is placed on the stack between the Toolbox routine's parameters and the address of the place where the glue routine was called from (where control returns once the Toolbox routine has completed execution).
The auto-pop bit forces the trap dispatcher to remove the top 4 bytes from the stack before dispatching to the Toolbox routine. After the Toolbox routine completes execution, control is transferred back to the place where the glue routine was called from, not back to the glue routine.
Most development environments, including MPW, do not use this feature.
About Trap Macros
A trap macro is an assembly-language macro that assembles into an A-line instruction, used for calling a Toolbox or Operating System routine from assembly language. The names of all trap macros begin with the underscore character (_), followed by the name of the corresponding routine. As a rule, the macro name is the same as the name used to call the routine from Pascal. For example, to call the Window Manager function NewWindow, you should use an instruction with the macro name _NewWindow. There are some exceptions, however, in which the spelling of the macro differs from the name of the Pascal routine itself; these are noted in the documentation for the individual routines.
Trap macros for Toolbox routines take no arguments; any parameters must be pushed on the stack before invoking the routine. See “Calling Conventions for Stack-Based Routines” on page 8-16 for more information. Trap macros for Operating System routines may have as many as three optional arguments. The first argument, if present, is used to load a register with a parameter value for the routine you’re calling. The remaining arguments control the settings of the various flag bits in the A-line instruction.
About Routine Selectors
A routine selector is a value that is pushed on the stack to select a particular routine from a group of routines to be executed. Many trap macros take routine selectors. For example, the trap macro _HFSDispatch has the possibility of calling 42 different system software routines. Hence, the trap macro has 42 different routine selectors. The routine selector that is passed on the stack (for _HFSDispacth to access) selects which of the 42 software routines _HFSDispatch executes.
Most system software routines that are accessed through a trap macro and a routine selector also have a corresponding macro that expands to call the original trap macro and automatically puts the correct routine selector on the stack. For example, the trap macro _GetCatInfo expands to call _HFSDispatch and places the selector $0009 on the stack after the parameters.