HPlogo PA-RISC Procedure Calling Conventions Reference Manual > Chapter 5 Inter-Module Procedure Calls

5.3 PIC Requirements for Compilers and Assembly Code

MPE documents

Complete PDF
Table of Contents

Any code which is PIC or which makes calls to PIC must follow the standard procedure call mechanism. In addition, register gr19 (the linkage table pointer register) must be stored at sp-32 by all PIC routines. This should be done once upon procedure entry. Register gr19 must also be restored upon return from each procedure call, even if gr19 is not referenced explicitly before the next procedure call. The LTP register, gr19, is used by the import stubs and must be valid at all procedure call points in position independent code. If the PIC routine makes several procedure calls, it may be wise to copy gr19 into a callee-saves register as well, to avoid a memory reference when restoring gr19 upon return from each procedure call. As with gr27 (DP), the compilers must treat gr19 as a reserved register whenever position-independent code is being generated.

5.3.1 Long Calls

Normally, the compilers generate a single-instruction call sequence using the BL instruction. The compilers will generate a long call sequence if the user explicitly requests long branch generation via a command-line option, or if the module is so large that the BL is not guaranteed to reach the beginning of the subspace (where a stub can be inserted by the linker). The existing long call sequence is three instructions, using an absolute target address:

  LDIL    L'target,r1       ; load target address into r1
  BLE     R'target(sr4,r1)  ; branch to target address
  COPY    r31,rp            ; copy return address (link register)
                            ; into rp

When the PIC option is in effect, the following seven-instruction sequence, which is PC-relative, must be used:

        BL      .+8,rp                    ; get PC into RP
        ADDIL   L'target - $L0 + 4, rp    ; add PC-reI offset to RP
        LDO     R'target - $L1 + 8(r1), r1
  $L0:  LDSID   (r1), r31
  $L1:  MTSP    r31, sr0
        BLE     0(sr0,r1)
        COPY    r31,rp

5.3.2 Procedure Labels and Dynamic Calls

The HP PA-RISC compilers generate the code sequence required for proper handling of procedure labels and dynamic procedure calls. Assembler programmers must use the same code sequence, described below, in order to insure proper handling of procedure labels and dynamic procedure calls.

A procedure label is a specially-formatted variable that is used to link dynamic procedure calls. The format of a procedure label is shown below:

[Procedure Label]

The X field in the address section of the procedure label is the XRT flag, which is used for MPE XL procedure labels to determine whether the call is local (off) or external (on). On HP-UX the L field is used to flag whether the procedure label is a pointer to an LT entry (L-field is on) or to the entry point of the procedure.

The plabel calculation produced by the compilers in both shared libraries and incomplete executables is modified by the linker, when building shared libraries and incomplete executables, to load the contents of an LT entry which is built for each symbol associated with a CODE_PLABEL fixup.

In shared libraries and incomplete executables, a plabel value is the address of a PLT (Procedure Linkage Table) entry for the target routine, rather than a procedure address; therefore a utility routine named $$dyncall must be used when calling a routine via a procedure label. The linker sets the L field (second-to-last bit) in the procedure label to flag this as a special PLT procedure label. The $$dyncall routine checks this field to determine which type of procedure label has been passed, and calls the target procedure accordingly. The $$dyncall routine assumes that the X field is always 0.

The following pseudo-code sequence shows the process used by $$dyncall to perform dynamic calls:

  IF (L-field in Plabel) = 0 THEN
    Perform interspace branch using Plabel as target address;
  ELSE BEGIN
    Clear L-field;
    Load new LTP value into gr19;
    Load address of target;
    Save RP';
    Perform interspace branch to target address;
  END.

In order to generate a procedure label that can be used for shared libraries and incomplete execu tables, assembly code must specify that a procedure address is being taken (and that a plabel is wanted) by using the P' assembler fix up mode. For example, to generate an assembly plabel, the following sequence must be used:

  ; Take the address of a function
  LDIL    LP'function,r1
  LDO     RP'function(r1), r22

This code sequence will generate the necessary PLABEL fixups that the linker needs in order to generate the proper procedure label. The $$dyncall millicode routine in /lib/milli.a must be used to call a procedure using this type of procedure label (i.e. a BL/BV will not work). For example:

  ; Now to call the routine using a plabel
  BL      $$dyncall, 31   ; r22 is the input register for $$dyncall
  COPY    r31, r2

The compilers generate the necessary code sequence required for proper handling of procedure labels.




5.2 External Calls on HP-UX


Chapter 6 Millicode Calls