Important: The information in this document is obsolete and should not be used for new development.
The Direct Data Area Switching Method
In the CFM-68K runtime environment, the standard direct data area switching procedure takes the following steps.
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.
- 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.
- 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.
- 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.
- 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.
- After executing the function, the program then runs the epilog and throws away its local variables (including the saved copy of A5).
- After running the epilog, the program returns to the calling fragment.
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_CTIf 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_CTIn certain cases, you may omit some of the switching steps to optimize your code. Three different optimization possibilities exist:
- 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.
- You can choose to not save A5 in the prolog. This choice is useful only when you are certain that the routine you are calling will never make any indirect or cross-fragment calls and thus will never need to restore A5. Routines using this optimization may still use A5, however.
- You can remove the external entry point and transition vector. This choice removes the initial
MOVE.L (A1), A5
instruction and is equivalent to tagging the routine asinternal
during a compile. You should use this optimization only if you are sure that the routine will never be called indirectly or from another fragment.- You can remove the
MOVE.L (A1), A5
instruction but keep the transition vector. This optimization works only for calling routines that never use the A5 register during execution (for example, a leaf routine that doesn't access global variables). Note that all the following actions do use A5 and disqualify routines from using this option:
- Direct (in-fragment) calls, because the called procedure may use A5, or the call may have to go through the jump table (which uses A5). Note that segmented shared libraries use the jump table if calling direct between two code segments.
- Any cross-fragment call or access to an imported data item, because the CFM-68K code uses the A5 register to access such data items indirectly.