0% found this document useful (0 votes)
6 views22 pages

Lecture 7 - ISA - J-Type Function Calls EECS 388

Uploaded by

usamog68
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views22 pages

Lecture 7 - ISA - J-Type Function Calls EECS 388

Uploaded by

usamog68
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

EECS 388: Embedded Systems

Lecture 7 – ISA j-type function calls


Fall 2024

Jacob Schoonover
Lecture notes based in part on slides created by Alex Fosdick,
Heechul Yun, Mohammad Alian, and Tamzidul Hoque

1
Agenda & Announcements
• Function calls with j-type
• Quiz

Monday, September 16: Last day to drop a full-term class and not
have it recorded on the transcript 'W'.
Monday, September 23: Last day to add a class with permission.
Last day for 50% refund

2
What is wrong with this code?

3
Lab 2 – Challenge Question

4
Context

Application Program

Operating
Compiler System

Machine Language (ISA)

Digital Logic

Electronic Circuits

Transistors

5
Register Naming in MIPS

6
7
Function call or Procedures
• A function commonly used in high level programs like C or Java
• Makes code readable
• Allows code reuse Callee function

int gcd(int m, int n) {


Caller function
int x = m;
int main () { int y = n;
int x, y; while(x != y) {
int a = 100; if(x > y) {
int b = 250; x = x – y;
x=gcd(a, b); } else{
x=y+1; y = y – x;
Y= gcd(x, }
a); }
return 0; return x;
} }

8
Memory Map of a Running
Program
A typical memory representation of a
C program consists of: Memory
1. Static Highest address
-Text/code segment
-Initialized data segment
-Uninitialized data segment Text segment of the memory
500
2. Stack
440
3. Heap Code of
GCD
400

Code of 200
Main
100

Lowest address 0

9
Memory Map of a Running
Program
Program Counter (PC): Memory
• A register that holds the address of Highest address
the next instruction to be executed
• Usually, the PC is incremented
after fetching an instruction Text segment of the memory
500
Example:
Code of …. 440
• Main() starts from address 100 GCD() Instruction 2
• PC=100 Instruction 1 400
• When instruction 1 is fetched, Code of …. 200
PC=PC+4=104, which is address of Main() Instruction 2
Instruction 1 100
instruction 2
Lowest address 0

10
Caller and Callee

• Let’s assume that main() is a caller void main(){


program and sum() is a callee m=1;
n=2;
• A caller needs to pass arguments to o=sum(m,n);
the called procedure, as well as get p=m+1;
results back from the called procedure
}

• A caller uses the same register set as


the called procedure Int sum (int a, int b){
return a+b;
}
Calling a function
• When a callee is executed, the flow of
execution jumps to a different segment of Text segment of the memory
the memory void main(){ 1000

• Performs jump instruction to a memory address m=1;


800
Code of
n=2;
sum()
o=sum(m,n); 700
• Main() starts from address 500
p=m+1;
600
• Sum() starts from address 700 q=sum(p,n); Code of
Main() 500
r=n+1;
} 0
• Questions:
1. What instruction to use to execute a jump to a
Int sum (int a, int b){
callee function
2. How can we return back to the caller function? return a+b;
}
Instruction to use to execute a jump

• Use jump and link instruction (jal):


• Written as: jal callee_Address void main(){
m=1;
• Link means that the link (address) to go back to the n=2;
caller is preserved
• In return address register $ra o=sum(m,n); ---Address 500
• Now we can go back to main() after execution of sum() p=m+1;
completes
}

• What exactly is being stored in $ra ?


• The address of next instruction, from where the procedure Int sum (int a, int b){
was called
return a+b;
• Example: Sum() was called from address 500
• Thus, $ra=Current PC+4=500+4 }
• After that, PC becomes the address of sum(), which is 700

13
How to return from the callee?
• We have the return address
void main(){
• Use jump register instruction: jr $ra
• Makes PC=$ra and starts executing m=1;
from where we left n=2;
o=sum(m,n); ---Address 500
p=m+1;
Question: }
• What is the value of PC after sum()
execution completes? Int sum (int a, int b){
• What instruction is in that address? return a+b;
}

14
Register Management during
function call
• Callee could overwrite registers that are currently in use by the caller program.
• Caller function main() stores variable m and n in register R1 and R3
• Assume that all other registers are occupied
void main(){
m=1;
Register Memory
n=2; Register
m=1
o=sum(m,n);
n=2
p=m+1;
}

Int sum (int a, int b){


return a+b;
}
Register Management during
Procedure
• After the function call, callee function sum() needs registers to store its return value
• But all the registers are occupied
• Assume that sum() uses register R1 to pass the return value, O=3
• Hence, value of m is corrupted
• This impacts the calculation for p=m+1 after the function call
void main(){
m=1;
O=3
n=2; N=2

o=sum(m,n);
p=m+1;
}

Int sum (int a, int b){


return a+b;
}
Register Management during
function call
• The CPU has a limited number of registers for use by all functions, and it’s possible that
several functions will need the same registers.
• We can keep important registers from being overwritten by a function call, by saving them
before the function executes, and restoring them after the function completes.
Store m to
memory before
function call
But there are two
m=1 important questions.
m=1 • Who is responsible for
saving registers—the
caller or the callee?
• Where exactly are the
register contents
saved?
Load m back to
R1 after return
to main()

17
Who saves the registers?
• Who is responsible for saving important registers across function
calls?
• The caller knows which registers are important to it and should be saved.
• The callee knows exactly which registers it will use and potentially
overwrite.

• However, in the typical “black box” programming approach, the


caller and callee do not know anything about each other’s
implementation.
• Different functions may be written by different people or companies.
• A function should be able to interface with any client, and different
implementations of the same function should be substitutable.

• So how can two functions cooperate and share registers when they
don’t know anything about each other?

18
Approach 1: Caller saves all
registers
• One possibility is for the caller to
save any important registers main: li $a0, 3
that it needs before making a li $a1, 1 Note: The li is a
function call, and to restore li $s0, 4 pseudo instruction
them after. li $s1, 1 that loads an
immediate value into
# Save registers a register.
• But the caller does not know # $a0, $a1, $s0, $s1
what registers are actually
written by the function, so it may jal func
save more registers than
necessary. # Restore registers
# $a0, $a1, $s0, $s1

add $v0, $a0, $a1


• In the example on the right,
add $v1, $s0, $s1
main wants to preserve $a0,
jr $ra
$a1, $s0 and $s1 from func, but
func may not even use those
registers.
• Slide taken and modified from CS232: Computer Architecture II. University of Illinois at Urbana-Champaign.

19
Approach 2: Callee saves all
registers
• Another possibility is if the callee
saves and restores any registers it func:
might overwrite. # Save registers
# $a0 $a2 $s0 $s2

• For instance, a func() function that li $a0, 2


uses registers $a0, $a2, $s0 and $s2 li $a2, 7
could save the original values first, li $s0, 1
and restore them before returning. li $s2, 8
...

• But the callee does not know what # Restore registers


registers are important to the caller, # $a0 $a2 $s0 $s2
so again it may save more registers
than necessary. jr $ra

• Slide taken and modified from CS232: Computer Architecture II. University of Illinois at Urbana-Champaign.

20
Best Approach: Caller and Calle
work together
• MIPS uses conventions again to split the register spilling chores.
• The caller is responsible for saving and restoring any of the following caller-saved registers
that it cares about.
$t0-$t9 $a0-$a3 $v0-$v1

In other words, the callee may freely modify these registers, under the assumption that the
caller already saved them if necessary.

• The callee is responsible for saving and restoring any of the following callee-saved
registers that it uses. (Remember that $ra is “used” by jal.)
$s0-$s7 $ra

Thus the caller may assume these registers are not changed by the callee.

• Be especially careful when writing nested functions, which act as both a caller and a
callee!
• •Slide$ra
takenis
andtricky; it isCS232:
modified from saved by aArchitecture
Computer callee II.who is also
University aatcaller.
of Illinois Urbana-Champaign.

21
Caller and Calle work together
• This convention ensures that the caller and callee together save all of the important
register
• main() only needs to save registers $a0 and $a1, while func() only has to save registers
$s0 and $s2.

main: li $a0, 3 func:


li $a1, 1 # Save registers
li $s0, 4 # $s0 and $s2
li $s1, 1
li $a0, 2
# Save registers li $a2, 7
# $a0, $a1 li $s0, 1
jal func li $s2, 8
...
# Restore registers
# $a0, $a1 # Restore registers
add $v0, $a0, $a1 # $s0 and $s2
add $v1, $s0, $s1
jr $ra jr $ra

• Slide taken and modified from CS232: Computer Architecture II. University of Illinois at Urbana-Champaign.

22

You might also like