To introduce the calling conventions associated with leaf procedures on the SPARC.
After completing this lab, you will be able to write assembly language programs that:
This lab is the first of three labs that cover procedure calling conventions on the SPARC. In this lab we consider the conventions associated with leaf procedures: procedures that do not make calls to other procedures. In Lab 11 we consider the use of register windows on the SPARC. In Lab 12 we complete our coverage of procedure calling conventions by considering the standard calling conventions used by compilers.
The SPARC Architecture Manual describes a class of procedures called ``optimized leaf procedures.'' As we have noted, a leaf procedure is a procedure that does not call any other procedures. Optimized refers to restrictions placed on the procedure's use of the registers.
Table 10.1 summarizes register uses for optimized leaf procedures. This table specifies which registers can be modified by a leaf procedure. Registers %r8-%r13 are used for parameters passed to the leaf procedure. The first parameter (i.e., the leftmost parameter) should be placed in %r8, the next in %r9, and so forth. Note that %r8 is used for the first parameter and the return value.
Table 10.1: Register usage for optimized leaf procedures
Beyond the registers used to pass parameters to the leaf procedure, there are a few other conventions in Table 10.1 that are worth noting. Register %r1 can always be used as a temporary register and the caller cannot assume that it will retain its value across a call to a leaf procedure. We have frequently used this register in the sethi instructions used with the load and store instructions, and you can continue to do this in leaf procedures. The stack pointer is stored in %r14. We will discuss the use of the stack pointer when we consider stack based calling conventions in Lab 12. For the moment, note that a leaf procedure should not alter the value stored in register %r14. Finally, note that the return address (actually, the address of the call instruction used to call the leaf procedure) is stored in register %r15. A leaf procedure can alter this register; however, it will be difficult to return to the point of the call if you alter the value in%r15.
An optimized leaf procedure should only alter the values stored in registers %r1 and %r8-%r13. If the leaf procedure requires more local storage than these registers provide, or if the parameters do not fit in these registers, the leaf procedure cannot be implemented as an ``optimized'' leaf procedure. We will discuss the techniques use to implement other types of procedures in the next two labs.
In assembly language, a procedure is a block of instructions. The first instruction in this block is labeled by the name of the procedure.
Table 10.2 summarizes the operations used to call and return from optimized leaf procedures. Like the branching operations introduced in Lab 3, these operations have a branch delay slot. The call and link operation saves the current value of the PC in %r15, updates the PC, and sets the nPC to the address specified in the call. The retl operation updates the PC and sets to nPC to the contents of %r15 plus eight. The ``plus eight'' is needed to skip over the call instruction and the instruction in the delay slot of the call. Examples 10.1 and 10.2 illustrate the use of these operations.
Table 10.2: The call and retl operations
.text ! pr_str - print a null terminated string ! ! Parameters: %r8 - pointer to string (initially) ! ! Temporaries: %r8 - the character to be printed ! %r9 - pointer to string !
pr_str: mov %r8, %r9 ! we need %r8 for the "ta 1" pr_lp: ldub [%r9], %r8 ! load character cmp %r8, 0 ! check for null be pr_dn nop ta 1 ! print character ba pr_lp inc %r9 ! increment the pointer
pr_dn: retl ! return from leaf procedure nop ! (branch delay)
.data str: .asciz "Hello, World!$$n"
.text main: set str, %r8 ! setup the first argument call pr_str ! call print string nop ! (branch delay) end: ta 0 ! exit gracefully
We have introduced two new instructions in this lab: call and retl. Figure 10.1 illustrates the format used to encode call instructions. This instruction encoding uses two fields. The first field holds the 2-bit value 01, the second holds a 30-bit displacement for the program counter. This field is encoded in the same fashion as the displacement field for the conditional branch instructions (see Lab 9 for more details).
Figure 10.1: Instruction format for call instructions
.text main: set str, %r8 ! setup the first argument call pr_string ! call print string nop ! (branch delay) ta 0 ! exit gracefully
pr_string: mov %r8, %r9 ! we need %r8 for the "ta 1"
In this case, the target is 3 instructions from the call instruction, so the disp field is set to the 30-bit binary encoding of 3.
This leads to the following machine instruction:
That is, 0100 0000 0000 0000 0000 0000 0000 0011 in binary, or 0x40000003.
The retl instruction is actually a synthetic instruction that is translated to a jmpl (jump and link) instruction. The jmpl instruction has two operands: an address, and a destination register. The address is similar to the addresses used in the load and store instructions; however, the brackets surrounding the address in the load and store instructions are omitted in the jmpl instruction. When a SPARC processor executes a jmpl instruction, it saves the address of the jmpl instruction in the destination register and sets the next program counter to the address specified in the instruction. Figure 10.2 illustrates the formats used to encode jmpl instructions.
Figure 10.2: Instruction formats for jmpl instructions
The retl instruction is translated to a jmpl instruction with the address set to %r15+8 and the destination register set to %r0. That is, the target of the branch is instruction after the branch delay slot of the call instruction (remember, call instruction saved its address in %r15), and the address of the retl instruction is discarded (saved in %r0).
A retl instruction is translated to the instruction jmpl %r15+8, %r0. This instruction is encoded using the second format shown in Figure 10.2. Figure 9.3. As such, we must determine the values for the rd, rs , and siconst fields. The following table summarizes these encodings:
These encodings lead to the following machine instruction:
That is, 1000 0001 1100 0011 1110 0000 0000 1000 in binary, or 0x81C3E008.
A leaf procedure is a procedure that never calls any other procedure. In this lab we have introduced the SPARC instructions used to write leaf procedures: call and retl. In the next two labs, we will examine more general procedure calling conventions.
You should also provide a small driver to test your procedure.
You should also provide a small driver to test your procedure.
void draw_pixel(int x, int y)