Transcript Chapter 7
Chapter 7 – Subroutines
These are lecture notes to accompany the book
SPARC Architecture, Assembly Language
Programming, and C,
by Richard P. Paul, 2nd edition, 2000.
By Anu G. Bourgeois
Richard P. Paul, SPARC Architecture, Assembly Language Programming, and C
Subroutines allow us to either to repeat a computation or to repeat the
computation with different arguments.
• Subroutines can be used in such situations
• Subroutines may be either open or closed
Open subroutine
• inserts code whenever it is needed in the program --- macros
• arguments are passed in the registers that are given as arguments to
the subroutine.
Closed subroutine
•code appears only once in the program; whenever it is needed, a
jump to the code is executed, and when it completes, a return is made
to the instruction occurring after the call instruction (after the delay)
• arguments may be placed in registers or on the stack
• A subroutine also allows you to debug code once and then ensure
that all future instantiations of the code will be correct
• Any register that the subroutine uses must first be saved and then
restored after the subroutine completes execution
• Arguments to subroutines are normally considered to be local
variables of the subroutine, and the subroutine is free to change
them
• However, this is not always the case, for e.g., in multiplication,
multiplicand is not changed
3
• Open Subroutines are very efficient with no wasted instructions
• Open Subroutines are very flexible and can be as general as the program
wishes to make them
• Every time open subroutine referenced, the code is expanded, resulting
in long code
• So it is better to write code once as a closed subroutine and to branch to
the code, whenever needed
Register Saving
•
Almost any computation will involve the use of registers
• Usually when subroutines are called, registers are pushed onto the stack
and popped from, when it returns
• To avoid the execution time involved, in CISC, sometimes a special
register save mask is used, that would indicate, by bits that were set, which
registers were to be saved
SPARC Registers
• SPARC architecture provides a register file with a mapping register that
indicates the active registers
• It provides 128 registers, with the programmer having access to the eight
global registers, and only 24 of the mapped registers at a time
• save instruction changes the register mapping so that new registers are
provided
• restore instruction restores the register mapping on subroutine return
• The 32 registers are divided into four groups : in, local, out and general
• The eight general register %g0 to %g8 are not mapped and are global to
all subroutines
• “in” & “out” register are used to pass arguments to closed subroutine
• “local” registers are used for subroutine’s local variables
• When save instruction is executed the out register become the in register,
and a new set of local and out registers is provided
Register Saving
• When the save instruction
is executed
– the out registers become
the in registers, and
– a new set of local and out
registers is provided.
• The mapping pointer into
the register file is changed
by 16 registers
REGISTER FILE
8-Global
REGISTER FILE
8-Global
10
Current register window
11
After branch to subroutine
12
After the return back to the
calling portion of the code
13
• If a further five subroutine calls are made without any returns, window
overflow will occur
• saves and restores can be made in a range of six without window overflows
or underflows (it is expensive if recursive subroutine calls are frequently
made)
Restore Instruction
• restore instruction restores the register window set. On doing this, a
register window can underflow if the cwp is moved to the wim. When
this happens the window trap routine restores the registers from the
stack and resets the pointers
• restore is also an add instruction and is used as the final add
instruction in a subroutine
Subroutine Linkage
• The SPARC architecture supports two instructions, call and jmpl, for
linking to subroutines
•
The address of instruction which called the subroutine is stored in
%o7
•
The return from subroutine is to %o7 + 8, which is the address of the
next instruction to be executed in the main program
•
If a save instruction is executed at the beginning of the subroutine,
the contents of %o7 will become %i7, and the return will have to be to
%i7 + 8
Call Instruction
•
If the subroutine name is known at assembly time, the call instruction
may be used
•
call instruction has a target address label
•
It stores %pc contents to %o7
•
always followed by a delay slot instruction
jmpl Instruction
• Used when the address of the subroutine is computed and not known –
address is loaded into a register
• subroutine address is the sum of the source arguments, and the address
of the jmpl instruction is stored in the destination register
• always followed by a delay slot instruction
• to call a subroutine whose address is in register %o0 and to store the
return address into %o7, we would write:
jmpl %o0, %o7
18
Call vs jmpl
• The assembler recognizes
call
%o0
jmpl
%o0, %07
as
• The return from a subroutine also makes use of the jmpl instruction
• We need to return to %i7 + 8
• Assembler recognizes ret for:
jmpl
%i7 + 8, %g0
• The call to subroutine is:
call
subr
nop
• And at the entry of the subroutine
subr:
save
%sp, … %sp
with the return
ret
restore
• The restore instruction is normally used to fill the delay slot of the ret
instruction
The ret is expanded to: jmpl
%i7 + 8, %g0
restore
Arguments to Subroutines
• 1. Arguments follow in-line after the call instruction:
• For example, a Fortran routine to add two numbers, 3 and 4, together would
be called by:
• and handled by the following subroutine code:
•
Note that the return is to %i7 + 16 jumping over the arguments.
•
This type of argument passing is very efficient but is limited. Recursive calls are not
possible, nor is it possible to compute any of the arguments.
Return Values
• Functions are subroutines which return a value
• In SPARC, the return value is always returned in an “out” register, e.g. %o0,
i.e. %i0 of called program
• We have to put the return value in the corresponding “in”register before
executing restore instruction
Consider the .mul routine – we pass arguments to the routine using %o0 and
%o1 and then expect the result to be passed back into %o0 – this means the
routine places the result into %i0 before returning