Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Mac OS Runtime Architectures /
Chapter 2 - Indirect Addressing in the CFM-Based Architecture / CFM-68K Implementation


The Direct Data Area Switching Method

In the CFM-68K runtime environment, the standard direct data area switching procedure takes the following steps.

  1. The program uses the transition vector to jump to the external entry point of the procedure. At this point, the A1 register points to the second word of the transition vector, which contains the address of the direct data area.
  2. The external entry point loads the A5 register with the new direct data area address (using the register A1) and then enters the internal entry point.
  3. The function's prolog code is executed, part of which saves a copy of A5 in case the function must in turn make other indirect or cross-fragment calls.
  4. The program executes the function. If the routine makes any indirect or cross-fragment calls, it restores the saved value of A5 after each such call.
  5. After executing the function, the program then runs the epilog and throws away its local variables (including the saved copy of A5).
  6. After running the epilog, the program returns to the calling fragment.

Direct callers and indirect callers can enter the procedure at different locations, so you can set up slightly different prolog sequences depending on the type of call.

Listing 2-3 illustrates glue code surrounding a simple function call.

Listing 2-3 Glue code for a simple function

MOVE.L         (A1), A5          ; set up A5 from A1
LINK           A6, #LOCALS       ; (this is the internal entry point)
MOVEM.L        <REGSET/A5>,-(A7) ; save new A5

<body of function  here>

MOVEM.L        (A7)+, <REGSET>   ; note A5 not restored here
UNLK           A6
RTD            #PARAM_CT
If the function itself makes indirect or cross-fragment calls, you must save the A5 value before the call and restore it after each return. Listing 2-4 shows how to handle an indirect call within an indirectly called function:

Listing 2-4 Making an indirect call from within an indirectly called function

MOVE.L         (A1), A5          ; set up A5 from A1
LINK           A6, #LOCALS       ; the reserved space
MOVEM.L        D7/D6/A5, -(A7)   ; save new A5 at -12(A6)

...

                                 ; now making cross-fragment call to
                                 ; the imported function mooCall
MOVE.L         _@mooCall(A5), A1 ; load transition vector into A1 via
                                 ;  the pointer to the transition vector
MOVE.L         (A1)+,A0          ; get code address
JSR            (A0)              ; call function
MOVE.L         -12(A6), A5       ; restore A5 from saved location

...

                                 ; no A5 restore here (but pop saved
MOVEM.L        (A7)+, D7/D6      ; data registers)
UNLK           A6                ; UNLK compensates for unbalanced stack
RTD            #PARAM_CT
Note
You do not have to save your A5 value on the stack. In some cases (such as when you know the called procedure will make a lot of indirect calls) it may be advantageous to save your A5 value in a data register, or even another address register.
In certain cases, you may omit some of the switching steps to optimize your code. Three different optimization possibilities exist:


Previous Book Contents Book Index Next

© Apple Computer, Inc.
11 MARCH 1997