If you don't save the values in the registers, the program will not be able to find its original value when the program restarts....
Run the above program in EGTAPI. You will see the following strange phenomenon:
Explanation: The Operating System is saving the registers to the stack
%sp --------> +-----------------------+ | save %l0 | 8 local registers %sp + 4 ----> +-----------------------+ | save %l1 | (parameters to subroutine) %sp + 8 ----> +-----------------------+ | ......... | | ......... | | ......... | %sp + 32 ---> +-----------------------+ | save %i0 | 8 input registers %sp + 36 ---> +-----------------------+ | save %i1 | (local variables of subroutine) %sp + 40 ---> +-----------------------+ | ......... | | ......... | | ......... | %sp + 64 ---> +-----------------------+ | structure pointer !! | for a function that returns struct %sp + 68 ---> +-----------------------+ | save %o0 | 6 output registers: o0 - o5 %sp + 72 ---> +-----------------------+ | save %o1 | %sp + 76 ---> +-----------------------+ | ......... | | ......... | %sp + 88 ---> +-----------------------+ | save %o5 | %sp + 92 ---> +-----------------------+ 92 is NOT divisible by 8 | ???????? | Will be explained later... %sp + 96 ---> +-----------------------+ 96 is divisible by 8 |
The right part of the figure shows the stack in memory
CPU's registers: Memory: ^ +-------------------+ +--------------------+ C | | input registers | | | u | | | | | r | | (function's | | | r | | parameters) | | | e | +-------------------+ | | n | | local registers | | | t | | | | | | | (function's | | | W | | local vars) | | | i | +-------------------+ | | n | | output registers | | | d | | | | | o | | o6 (stack pointer)|---+ | | w | | o7 | | | | v +-------------------+ | | | | | | | | | | | | | | unused | | | unused space | | | +------>|--------------------| +-------------------+ | | | | | area to save | | unused | | function's | | | | window registers | | | | | +-------------------+ | |
|
|
CPU's registers: Memory: ^ +-------------------+ +--------------------+ | | i0 - i5 | | | C | | (A's parameters) | | | u | | | | | r | | i6 (frame pointer)| | | r | | i7 (return addr) | | | e | +-------------------+ | | n | | local registers | | | t | | | | | | | | | | W | | ( A 's | | | i | | local vars) | | | n | +-------------------+ | | d | | output registers | | | o | | | | | w | | | | | | | o6 (stack pointer)|---+ | | | | o7 | | | | v +-------------------+ | | | | | | | | | | | | | | unused | | | unused space | | | +------>|--------------------| | | | | +-------------------+ | area to save | | | | function's | | | | window registers | | unused | | | | | | | | | +-------------------+
(For now, we assume callee function has <= 6 parameters)
CPU's registers: Memory: ^ +-------------------+ +--------------------+ | | i0 - i5 | | | C | | (A's parameters) | | | u | | | | | r | | i6 (frame pointer)| | | r | | i7 (return addr) | | | e | +-------------------+ | | n | | local registers | | | t | | | | | | | | | | W | | ( A 's | | | i | | local vars) | | | n | +-------------------+ | | d | | output registers | | | o | | ( B 's | | | w | | parameters) | | | | | o6 (stack pointer)|---+ | | | | o7 | | | | v +-------------------+ | | | | | | | | | | | | | | unused | | | unused space | | | +------>|--------------------| | | | | +-------------------+ | area to save | | | | function's | | | | window registers | | unused | | | | | | | | | +-------------------+
(Recall call will save return address in o7)
CPU's registers: Memory: ^ +-------------------+ +--------------------+ | | i0 - i5 | | | C | | (A's parameters) | | | u | | | | | r | | i6 (frame pointer)| | | r | | i7 (return addr) | | | e | +-------------------+ | | n | | local registers | | | t | | | | | | | | | | W | | ( A 's | | | i | | local vars) | | | n | +-------------------+ | | d | | output registers | | | o | | ( B 's | | | w | | parameters) | | | | | o6 (stack pointer)|---+ | | | | o7 (ret addr to A)| | | | v +-------------------+ | | | | | | | | | | | | | | unused | | | unused space | | | +------>|--------------------| | | | | +-------------------+ | area to save | | | | function's | | | | window registers | | unused | | | | | | | | | +-------------------+
CPU's registers: Memory: +-------------------+ +--------------------+ | old i0 - i5 | | | | (A's parameters) | | | | | | | | i6 (frame pointer)| | | | i7 (return addr) | | | +-------------------+ | | | old local regs | | | | | | | | | | | | ( A 's | | | | local vars) | | | +-------------------+ | | ^ | input registers | | | | | ( B 's | | | C | | parameters) | | | u | | i6 (FRAME pointer)|---+ | | r | | i7 (ret addr to A)| | | | r | +-------------------+ | | | e | | B 's | | | | n | | local variables | | | | t | | | | | unused space | | | | +------>|--------------------| W | | | | | i | +-------------------+ | area to save | n | | Output registers | | function's | d | | | | window registers | o | | | | | w | | o6 = ??? | | | | | | V +-------------------+
(Remember from the program above: windows registers are saved when the program is stopped by the Operating System. The stack so far only has space to save A's window registers. So we must allocate space to save B's window registers.)
Run program in EGTAPI. Check stack to see effect: B's input and local registers' values OVERWRITE A's input and local registers' values.
Now we have the necessary information to comprehend why the save instruction does what it does....
save %r1, constant, %r3 or: save %r1, %r2, %r3 Effect: 1. Temp <- r1 + constant (or r1 + r2) 2. CWP <- CWP - 1 (NOTE: this will move the window down !!!) 2. r3 <- Temp |
save %sp, -96, %sp (i.e.: save %06, -96, %o6) |
First, recall that the register window looked like this when the callee ( B starts running:
CPU's registers: Memory: ^ +-------------------+ +--------------------+ | | i0 - i5 | | | C | | (A's parameters) | | | u | | | | | r | | i6 (frame pointer)| | | r | | i7 (return addr) | | | e | +-------------------+ | | n | | local registers | | | t | | | | | | | | | | W | | ( A 's | | | i | | local vars) | | | n | +-------------------+ | | d | | output registers | | | o | | ( B 's | | | w | | parameters) | | | | | o6 (stack pointer)|---+ | | | | o7 (ret addr to A)| | | | v +-------------------+ | | | | | | | | | | | | | | unused | | | unused space | | | +------>|--------------------| | | | | +-------------------+ | area to save | | | | function's | | | | window registers | | unused | | | | | | | | | +-------------------+
The instruction:
save %sp, -96, %sp (or: save %o6, -96, %o6)
will do:
The result is then:
CPU's registers: Memory: +-------------------+ +--------------------+ | old i0 - i5 | | | | (A's parameters) | | | | | | | | i6 (frame pointer)| | | | i7 (return addr) | | | +-------------------+ | | | old local regs | | | | | | | | | | | | ( A 's | | | | local vars) | +-------->+--------------------+ +-------------------+ | | area on stack to | ^ | input registers | | | save B's | | | ( B 's | | | window registers | C | | parameters) | | | | u | | i6 (FRAME pointer)|---+ | | r | | i7 (ret addr to A)| | | | | r | +-------------------+ | | | | e | | B 's | | | | | n | | local variables | | | | | t | | | | | | reserved 96 bytes | | | | | +------>|--------------------| W | | | | | | i | +-------------------+ | | area to save | n | | Output registers | | | A's | d | | | | | window registers | o | | | | | | w | | o6 = i6 - 96 -----|-+ | | | | | V +-------------------+
Run program in EGTAPI. Check stack to see effect: B's input and local registers' values DO NOT overwrite A's input and local registers' values.
Syntax: restore %r1, constant, %r3 or: restore %r1, %r2, %r3 Effect: 1. Temp <- r1 + constant (or r1 + r2) 2. CWP <- CWP + 1 (NOTE: this will push the window up !!!) 2. r3 <- Temp
restore %g0, %g0, %g0 (you get this when you write "restore")
The effect of this instruction is simply:
CWP <- CWP + 1In other words: simply push the window up...