1COSC2200: Hardware Systems MIPS Calling Convention 44 Outline • So far we have learnt: – Basic arithmetic and logic operation instructions – Conditional and unconditional jumps • if … else • loops • switches – Transfers between memory and registers • Today – Ra register – Procedure call 45 2Register Usage • a0 – a3: arguments (reg’s 4 – 7) • v0, v1: result values (reg’s 2 and 3) • t0 – t9: temporaries – Can be overwritten by callee • s0 – s7: saved – Must be saved/restored by callee • gp: global pointer for static data (reg 28) • sp: stack pointer (reg 29) • fp: frame pointer (reg 30) • ra: return address (reg 31) 47 Instruction Support for Functions ... sum(a,b);... /* a, b: s0,s1 */ } int sum(int x, int y) { return x+y; } address 1000 add a0,s0,zero # x = a 1004 add a1,s1,zero # y = b 1008 addi ra,zero,1016 #ra=1016 1012 b sum #jump to sum 1016 ... 2000 sum: add v0,a0,a1 2004 jr ra # new instruction HLL M I P S 348 Instruction Support for Functions • Single instruction to jump and save return address: jump and link (jal) • Before: 1008 addi ra,zero,1016 #ra=1016 1012 b sum #go to sum • After 1012 jal sum # ra=1016,go to sum • Why have a jal? Make the common case fast: functions are very common. 49 Instruction Support for Functions • Syntax for jr (jump register): jr register • Instead of providing a label to jump to, the jr instruction provides a register which contains an address to jump to. • Very useful for function calls: –jal stores return address in register (ra) –jr jumps back to that address 450 0 sp gp 0040 0000 hex 1000 0000 hex Text Static data Dynamic data Stack7fff ffff hex 1000 8000 hex pc Reserved MIPS Address Space Layout Program instructions Variables allocated once per program (global, C static) Explicitly allocated space, (C malloc()library proc) sp stack pointer global pointer gp 0 Local data in functions, stack frames 51 MIPS Address Space Layout 0 Address Code Program Static Variables declared once per program Heap Explicitly created space, e.g., malloc(); C pointers Stack Space for saved procedure informationsp stack pointer 5MIPS Stack Frame • The stack grows downward, • Stack top at the bottom • Possibly 5 regions: – Argument – Saved registers – Return address – Padding – Local data storage • The argument region is reserved by caller, written by callee • The size of the frame is a multiple of 8 Stack Frame 52 53 Steps for Making a Procedure Call 1) Save necessary values onto stack. 1) Argument registers 2) Return address 3) Saved registers 4) Local arrays and structures 2) Assign argument(s), if any. 3) jal call 4) Restore values from stack. 6Leaf Procedure Example • HLL code: int leaf_example (int g, h, i, j) { int f; f = (g + h) - (i + j); return f; } – Arguments g, …, j in a0, …, a3 – f in s0 • (hence, need to save s0 on stack) – Result in v0 Leaf Procedure Example • MIPS code: leaf_example: addi sp, sp, -32 sw s0, 0(sp) add t0, a0, a1 add t1, a2, a3 sub s0, t0, t1 add v0, s0, zero lw s0, 0(sp) addi sp, sp, 32 jr ra Push the frame Save s0 on stack Procedure body Restore s0 Pop the frame Result Return Draw the frame/activation stack 756 Leaf Procedure Example • Notes: – no jal calls are made from leaf_example, so we don’t need to save ra’s value and restore it before jump back to caller – Use 1 saved register (s0), so we need to save s0’s value before we use it and restore it after we use it • Alternative way is to use temp registers, so that we don’t have to save them. If caller uses t registers but didn’t save them before call me, that is caller’s fault. – result is put into v0 before returning – No need to have the argument region because the leaf procedure doesn’t have a callee Non-Leaf Procedures • Caller: the procedure that calls another procedure • Callee: the procedure that is called • Non-Leaf procedures: procedures that call other procedures • For nested call, caller needs to save on the stack: – Its return address – Any arguments and temporaries needed after the call • Restore from the stack after the call 858 Non-Leaf Procedure Example • So, how do we compile sumSquare? int sumSquare(int x, int y) { return multiply(x,x)+ y; ° } ° Local variables in sumSquare: ° Reg a0: x ° Reg a1: y ° Arguments needed to pass by sumSquare to multiply ° Reg a0: x ° Reg a1: x 59 Non-Leaf Example °Compile by hand sumSquare: # the caller addi sp, sp, -32 # push the frame sw ra, 16(sp) # save ret addr sw a1, 36(sp) # save y add a1, a0, zero # multiply(x,x) jal multiply # call multiply lw a1, 36(sp) # restore y add v0, v0, a1 # multiply()+ y lw ra, 16(sp) # get ret addr addi sp, sp, 32 # pop the frame jr ra Draw the stack frame 960 Rules for Procedures • Called with a jal instruction, returns with a jr ra • Accepts up to 4 arguments in a0, a1, a2 and a3 • Return value is always in v0 (and if necessary in v1) • Must follow register conventions (even in functions that only you will call)! So what are they? Return address ra Arguments a0, a1, a2, a3 Return value v0, v1 Local variables s0, s1, , s7 Recursive Procedure Example • HLL code: int fact (int n) { if (n < 1) return 1; else return n * fact(n - 1); } – Argument n in a0 – Result in v0 10 Recursive Procedure Example • MIPS code: fact: addi sp, sp, -32 # push stack sw ra, 16(sp) # save return address sw a0, 32(sp) # save argument li t1, 1 # test for n < 1 bge a0, t1, L1 addi v0, zero, 1 # if so, result is 1 addi sp, sp, 32 # pop stack jr ra # and return L1: addi a0, a0, -1 # else decrement n jal fact # recursive call lw a0, 32(sp) # restore original n lw ra, 16(sp) # and return address addi sp, sp, 32 # pop 2 items from stack mul v0, a0, v0 # multiply to get result jr ra # and return Draw the stack info for fact(2). 63 Recursive Procedure Example • Notes: – jal calls are made, so we must save my own ra’s value before call jal, and restore it before jump back to my caller • Because jal call overwrites ra’s value. If I don’t save it, then I lose my ra info. – Did not use saved registers, so we don’t need to save their values on stack. – Used temp registers. Callers are supposed to save their values if necessary. If callers used t registers but didn’t save them before call me, that is callers’ fault. – a0’s value are saved before it is overwritten by jal. – result is put into v0 before returning 11 Key Regions and Steps for a Call 5 possible regions 1) Argument registers 2) Saved registers 3) Return address 4) Pad 5) Local arrays and structures Steps 1. push stack frame 2. Save necessary values onto stack. 3. Assign argument(s), if any. 4. jal call 5. Restore values from stack. 6. Set return value 7. Pop stack frame 8. Jump to Ra 64