HP.com home PA-RISC Procedure Calling Conventions Reference Manual > Appendix C The Stack Unwind Library

C.1 The Unwind Descriptor

MPE documents

Complete PDF
Table of Contents

When the assembler sees procedure directives such as .ENTER or .LEAVE, it builds fixup requests for the linker. Using the information in these fixup requests, the linker builds a 4-word unwind descriptor for each unwind region. These descriptors monitor a particular code address range, typically an entire procedure. The unwind descriptors provide information about the stack size, registers usage, and the lengths of the entry and exit sequences. The linker sorts these entries in the increasing order of code addresses and places them in a separate subspace.

Here is a C language declaration of the unwind descriptor.

  struct unwind_table_entry {
          unsigned int region_start;                /* Word 1  */
          unsigned int region_end;                  /* Word 2. */
          unsigned int Cannot_unwind:1;             /* Word 3. */
          unsigned int Millicode;1;
          unsigned int Millicode_save_sr0:1;
          unsigned int Region_description:2;
          unsigned int reserved1:1;
          unsigned int Entry_SR:1;
          unsigned int Entry_FR:4;
          unsigned int Entry_GR:5;
          unsigned int Args_stored:1;
          unsigned int Variable_Frame:1;
          unsigned int Separate_Package_Body:1;
          unsigned int Frame_Extension_Millicode:1;
          unsigned int Stack_Overflov_Check:1;
          unsigned int Two_Instruction_SP_Increment:1;
          unsigned int Ada_Region:1;
          unsigned int reserved2:4;
          unsigned int Save_SP:1;
          unsigned int Save_RP:1;
          unsigned int Save_MRP_in_frame:1;
          unsigned int reserved3:1;
          unsigned int Cleanup_defined:1;
          unsigned int MPE_XL_interrupt_marker:1;   /* Word 4 */
          unsigned int BP_UX_interrupt~arker:1; 
          unsigned int Large_frame_r3:1;
          unsigned int reserved4:2;
          unsigned int Total_frame_size:27;
  };

Each of the fields in this structure are used as follows:
  1. Cannot_unwind: One if this region does not follow unwind conventions and is therefore not unwindable; zero otherwise. (Creation of non-unwindable assembly code is strongly discouraged.)
  2. Millicode: One if this region is a millicode routine; zero otherwise.
  3. Millicode_save_sr0: One if this (millicode) routine saves sr0 in its frame (at curren_SP - 16); zero otherwise.
  4. Region_description: Describes the code between the starting and ending offsets of this region:

    00: Normal (entry point at start of region, exit point at end; contains no other entry /exit points)
    01: Entry point only (contains no exit point)
    10: Exit point only (contains no entry point)
    11: Discontinuous (contains no entry or exit point)

    Normal context is code that falls between the last entry point and first exit point of a routine.

    Entry point only context is code that makes up an alternate entry point. It consists of entry code inserted by the assembler or compiler as well as user code. It does not contain exit code.

    Exit point only context is code that makes up an alternate exit point. It consists of exit code inserted by the assembler or compiler as well as user code. It does not contain entry code.

    Discontinuous context is code within an assembled or compiled routine that is either not preceded by some entry point or not followed by some exit point.

    One unwind table entry is generated per routine, plus one for each additional entry point, exit point, and discontinuous region. Normally, all unwind descriptors are identical except for the Region_description field. The entry and exit points to any region are marked using the .ENTRY and .EXIT assembler directives.
  5. Entry_SR: One if the sole entry-save space register sr3 is saved/restored by the associated entry/exit code sequence; zero otherwise.
  6. Entry_FR: The number of entry-save floating-point registers saved/restored by the associated entry/exit code sequence.
  7. Entry_GR: The number of entry-save general registers saved/restored by the associated entry/exit code sequence. Note that the semantics of this field are different from those of the similarly named field of the .CALLINFO directive to the assembler. For example, a value of 5 in this field would mean that gr3 through gr7 (inclusive) have been saved in the entry save code.
  8. Arqs_stored: One if this region's prologue includes storing any arguments to the routine in memory in the architected locations; zero otherwise. (Note: this bit may not be correct if the associated routine was compiled with optimization, as the optimizer may remove initial stores of arguments, but will never clear this bit.)
  9. Variable_Frame: Indicates that this region's frame may be expanded during the region's execution (using the Ada dynamic frame facility). Such frames require different unwinding techniques.
  10. Separate_Packaqe_Body: Indicates the associated region is an Ada separate package body. It has no frame of its own, but uses space in a parent frame to save RP and spill any entry save registers.
  11. Frame_Extension_Millicode: Indicates the associated region is a special millicode routine which implements the Ada frame extension operation.
  12. Stack_Overflow_Check: Indicates the associated region has an Ada stack overflow check in its entry sequence(s).
  13. Two_Instruction_SP_Increment: Indicates the associated (Ada) region had a large frame such that two instructions were necessary to produce that portion of the frame increment which cannot be deduced from the frame size field in the unwind descriptor.
  14. Ada_Region: One if the associated region should be treated as an Ada routine. Currently this bit is intended for use by the Ada exception handler.
  15. Save_SP: One if the entry value of SP is saved by this region's entry sequence in the current frame marker (current_SP - 4); zero otherwise.
  16. Save_RP: For non-millicode, one if the entry value of RP is saved by the entry sequence in the previous frame (at previous_SP - 20); zero otherwise. For millicode, one if the entry values of MRP and sr0 are saved by the entry sequence in the current frame (at current_SP - 20 and current_SP - 16, respectively); zero otherwise. If this bit is one, the Save_MRP_in_frame and Millicode_save_sr0 bits are ignored.
  17. Save_MRP_in_frame: One if the entry value of MRP is saved by the entry code in the current frame (at current_SP - 20); zero otherwise. Applies only to millicode.
  18. Cleanup_defined: The interpretation of this field is dependent upon the language processor which compiled the routine.
  19. MPE_XL_interrup_marker: One if the frame layout corresponds to that of an MPE XL interrupt marker.
  20. HP_UX_interrup_marker: One if the frame layout corresponds to that of an HP-UX interrupt marker.
  21. Large_frame_r3: One if gr3 is changed during the entry sequence to contain the address of the base of the (new) frame.
  22. Total frame size: The amount of space, in 8-byte units, added to SP by the entry sequence of this region. This space includes register save and spill areas, as well as padding. This quantity is needed during unwinding to locate the entry-save register save area. It is also used to determine the value of previous_SP if it was not saved in the stack marker.




Appendix C The Stack Unwind Library


C.2 Unwind Utility Routines