Stack Usage

   

PA-RISC uses a stack to keep track of local data and procedure call return information for each procedure call. The PA-RISC architecture does not provide explicit stack manipulation instructions. To manage the stack, the runtime architecture specifies that general register GR30 will be used as a stack pointer. This register is commonly referred to as the sp register.

The stack in PA-RISC grows upward in memory. That is, as data is added to the stack, it goes at increasing addresses and the stack pointer increases. When data is removed from the stack, the stack pointer decreases.

Each called procedure begins by increasing the stack pointer, thus allocating itself memory for local data storage and linkage information. This area is called a stack frame. The amount of space allocated for a stack frame depends on how much local data storage the procedure needs.

Stack usage differs between narrow mode and wide mode. We discuss the narrow mode stack usage first, then look at the differences when running in wide mode.

Stack Usage in Narrow Mode

Figure 2-1 shows the stack frame for a narrow-mode call. By convention, we draw the stack with lower addresses higher on the page, and the stack grows down to higher addresses. The first thing on the stack is a frame marker, which is always eight words long. The frame marker for the current process is located at SP-4 through SP-0x20. The space in the frame marker is reserved for a variety of uses, but the only one we need be concerned with is at SP-0x14. SP-0x14 contains the Return Pointer (RP) of a called procedure. In other words, when a procedure is called, it saves the return pointer at SP-0x14 in the calling procedure's stack frame.

Figure 2-1. Stack Usage in Narrow Mode

graphics/02fig01.gif


The area at SP-0x24 through SP-0x30 is reserved for arguments zero through three. This space is always allocated even if there are fewer than four arguments. Beyond that is a variable-sized area for storing any arguments beyond four. This area is used only if the called procedure takes more than four arguments. Finally, beyond the variable arguments area, the called procedure can allocate additional space to store callee save registers and for local data storage.

Listing 2.1 is an example of C code and the corresponding assembly showing the linkage in the procedure call.

Listing 2.1. Narrow Mode Procedure Call Example
 #include <stdio.h> int proc(int x); main() {   int i;   int j;   i = 10;   j = proc(i);   printf("j is %d\n", j); } int proc(int x) {   int r;   r = 2*x;   return r; } main starting at 0x28d8: +0x0         NOP +0x4         STW        rp,-0x14(sp)           ; save the return pointer +0x8         LDO        0x40(sp),sp            ; grow the stack +0xc         LDI        0xa,r1                 ; i = 10 +0x10        STW        r1,-0x38(sp)           ; save I on the stack +0x14        LDW        -0x38(sp),arg0         ; arg0 = i +0x18        LDIL       0x2800,r31             ; calculate address for proc +0x1c        BE,L       0x124(sr4,r31)         ; call proc +0x20        COPY       r31,rp +0x24        STW        ret0,-0x34(sp)         ; save the return value in j +0x28        LDIL       0x2800,r31             ; load address of constant +0x2c        LDO        0x768(r31),arg0        ; string into arg0 +0x30        LDW        -0x34(sp),arg1         ; load j into arg1 +0x34        LDIL       0x2800,r31             ; calculate address of printf +0x38        BE,L       0xc0(sr4,r31)          ; call printf +0x3c        COPY       r31,rp +0x40        LDW        -0x54(sp),rp           ; get the return pointer from +0x44        BV         (rp)                   ; our caller and branch there +0x48        LDO        -0x40(sp),sp           ; restore the stack pointer proc starting at 0x2924: +0x0         NOP +0x4         LDO        0x40(sp),sp            ; Grow stack +0x8         STW        arg0,-0x64(sp)         ; Store arg0 +0xc         LDW        -0x64(sp),r19          ;  r19 = arg0 +0x10        SHLADD     r19,1,0,r20            ; r20 = 2 * r19 +0x14        STW        r20,-0x28(sp)          ; save r20 +0x18        LDW        -0x28(sp),ret0         ; ret0 = r20 +0x1c        COPY       ret0,ret0 +0x20        BV         (rp)                   ; Branch to rp +0x24        LDO        -0x40(sp),sp           ; Shrink stack 

Stack Usage in Wide Mode

Figure 2-2 shows the stack usage for a wide-mode procedure call. Recall that in wide mode all our registers are 64 bits wide. Each entry on the stack is also treated as a 64-bit doubleword.

Figure 2-2. Stack Usage in Wide Mode

graphics/02fig02.gif


The frame marker for wide mode is only two doublewords long to allow for storing two values. The return pointer is stored at SP-0x10. SP-0x08 is reserved for storing the previous stack pointer if needed.

After the frame marker, eight doublewords are allocated to store eight arguments. Additional space may be allocated for arguments if there are more than eight. Unlike in narrow mode, these are stored at increasing addresses, not decreasing addresses. In addition, arguments are no longer addressed relative to the stack pointer. Instead, GR29 is set to point to the address of the ninth argument (even if there are fewer than nine arguments, the pointer is set to point to the doubleword after the location reserved for the eighth argument).

After the area for arguments are optional areas to accommodate stack growth for allocated memory, local storage, and callee save registers.

Listing 2.2 is the assembly language for the same code as above, this time compiled in wide mode. Note that gr9 is decoded as ret1 by this tool because of its alternate use as a return value.

Listing 2.2. Wide Mode Procedure Call Example
 main starting at 0x4000000000001e08: +0x0         STD        rp,-0x10(sp) +0x4         STD,MA     r3,0x90(sp)              ; save r3, grow stack +0x8         STD        r4,-0x88(sp)           ; save r4 +0xc         COPY       ret1,r3 +0x10        STD        dp,-0x80(sp) +0x14        MFIA       r1 +0x18        ADDIL      -0x800,r1 +0x1c        LDO        0x7ec(r1),r31 +0x20        LDI        0xa,r19                  ; i = 10 +0x24        STW        r19,-0x78(sp)            ; store i +0x28        LDW        -0x78(sp),arg0           ; arg0 = i +0x2c        BLL        0x1e88,rp                ; call proc() +0x30        LDO        -0x30(sp),ret1           ; ap = SP-0x30 +0x34        LDD        -0x80(sp),dp +0x38        STW        ret0,-0x74(sp) +0x3c        ADDIL      -0x800,dp +0x40        COPY       r1,ret0 +0x44        LDD        0x760(ret0),r19 +0x48        LDW        -0x74(sp),r20 +0x4c        COPY       r19,arg0 +0x50        COPY       r20,arg1 +0x54        BLL        0x1e78,rp +0x58        LDO        -0x30(sp),ret1 +0x5c        LDD        -0x80(sp),dp +0x60        LDD        -0xa0(sp),rp +0x64        LDD        -0x88(sp),r4 +0x68        BVE        (rp) +0x6c        LDD,MB     -0x90(sp),r3 proc starting at 0x4000000000001e88: +0x0         NOP +0x4         STD,MA     r3,0x50(sp)              ; save r3,                                                  ; grow stack +0x8         STD        r4,-0x48(sp)             ; save r4 +0xc         COPY       ret1,r3                  ; r3 = ap +0x10        NOP +0x14        STW        arg0,-0x3c(ret1)         ; save arg0 at                                                  ; ap-0x3c +0x18        LDW        -0x3c(ret1),r19          ; r19 = arg0 +0x1c        SHLADD     r19,1,0,r19              ; r19 *= 2 +0x20        STW        r19,-0x38(sp)            ; save r19 +0x24        LDW        -0x38(sp),ret0           ; ret0 = r19 +0x28        COPY       ret0,ret0 +0x2c        LDD        -0x48(sp),r4             ; restore r4 +0x30        BVE        (rp)                     ; branch to rp +0x34        LDD,MB     -0x50(sp),r3             ; shrink stack,                                                  ; restore r3 

Figure 2-3 shows the stack usage for the call to proc(). You can see that the stack is first grown by 0x50; then GR3, GR4, and G26 (arg0) are stored on the stack. GR3 and GR4 are callee saves, so proc() has to store them in its own stack to be restored later. GR26 gets stored into the caller's argument area.

Figure 2-3. Stack Usage for the Call to proc()

graphics/02fig03.gif




HP-UX 11i Internals
HP-UX 11i Internals
ISBN: 0130328618
EAN: 2147483647
Year: 2006
Pages: 167

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net