10.3. MIPS Subprograms

Most modern CPU architectures provide specific instructions to support jumping to and returning from subprograms.

10.3.1. JAL and JR

MAL provides two basic instructions for ordinary subprogram calls:

  • The jal instruction (jump and link), performs an unconditional jump to the address provided, and saves the address of the next instruction in the $ra (return address) register, thus linking the subprogram to the origin of the call. Note that by ``next instruction'', we mean the instruction at the next address after jal, not the instruction that gets executed after jal. We want to be able to continue with the code sequence that contains the jal instruction exactly where it left off.
  • The jr (jump register) instruction jumps to the address contained in a register. This instruction is not used exclusively for returning from subprograms, but the instruction:
    		jr      $ra
    		
    complements the jal instruction, so this is the most typical use.

The basic structure of a subprogram call looks something like this:

		    .text
	    main:   
	    
		    jal     subprog
		    
		    # End of main
		    jr      $ra
		    
		    # Beginning of subprogram
	    subprog:
		    
		    # End of subprogram
		    jr      $ra
	    

As discussed in Section 5.3, “The MIPS Register Files”, MAL programmers adhere to a convention for use of registers. Table 5.3, “MIPS Registers” shows the conventional use for all registers in the CPU and the floating point coprocessor.

With respect to subprograms, the following conventions must be followed:

  • Registers $a0 through $a3 are used for the first four arguments to the subprogram. If more than four arguments are required, it is up to the programmer to decide how to pass them, and it must be clearly documented in the block comment above the subprogram. The convention for additional arguments is to pass them on the stack, which is discussed in Section 10.4, “Memory Segments”.
  • Register $v0 is used for a return value of up to 32 bits. If between 33 and 64 bits of information must be returned, then $v1 must be used as well. If more than 64 bits are returned, it is up to the programmer to decide how to return them, and it must be clearly documented in the block comment above the subprogram.

Suppose we have a subprogram that computes the area of a rectangle. The Java method might be called as follows:

	    int     yard_size, length, width;
	    
	    // Some other code
	    
	    // Compute area of yard
	    yard_size = area(length, width);
	    
	    // More code
	    

If this code were compiled to MAL, the compiler output might look like this:

		    .data
	    yard_size:  .word   0
	    length:     .word   0
	    width:      .word   0
	    
		    .text
	    # Some other code
	    
	    # Compute area of yard
		    lw      $a0, length     # Pass length argument
		    lw      $a1, width      # Pass width argument
		    jal     area
		    sw      $v0, yard_size  # Store return value
	    
	    # more code
	    

If passing floating point values, we use the floating point registers as arguments and return values. Register $f12 should be used for the first argument, $f13 for the second (or $f14 if the first argument was a double). Register $f0 should be used for the return value.

		    .data
	    yard_size:  .double 0.0
	    length:     .double 0.0
	    width:      .double 0.0
	    
		    .text
	    # Some other code
	    
	    # Compute area of yard
		    l.d     $f12, length    # Pass length argument
		    l.d     $f14, width     # Pass width argument
		    jal     area
		    s.d     $f0, yard_size  # Store return value
	    
	    # more code
	    

Note that some registers must be preserved by subprograms. For example, a program can assume that $s0 or $f20 will have the same value after a subprogram call (including a syscall) that it had before. Hence, if a subprogram alters the value of either $s0 or $f20, the original value must be restored before the subprogram returns. We cannot assume the same about temporary registers such as $t0. They may have different values after a jal or syscall than they had before it.

10.3.2. syscall