L06 RISCV Functions
L06 RISCV Functions
04/25/2024 2
Outline
• RISC-V ISA and C-to-RISC-V Review
• Program Execution Overview
• Function Call
• Function Call Example
• And in Conclusion …
04/25/2024 3
Levels of Representation/Interpretation
High-Level Language temp = v[k];
Program (e.g., C) v[k] = v[k+1];
v[k+1] = temp;
Compiler lw x10, 0(x12)
Anything can be represented
Assembly Language lw x11, 4(x12)
Program
Datapath
Address
PC Bytes
Registers Write
Data
Arithmetic & Logic Unit Data
Read Output
(ALU)
Data
04/25/2024 10
Peer Instruction
Which of the following is TRUE?
RED: add x10,x11,4(x12)is valid in RV32
GREEN: can byte address 8GB of memory with an RV32 word
ORANGE: imm must be multiple of 4 for lw x10,imm(x10)
to be valid
YELLOW: None of the above
04/25/2024 11
Outline
• RISC-V ISA and C-to-RISC-V Review
• Program Execution Overview
• Function Call
• Function Call Example
• And in Conclusion …
04/25/2024 12
Assembler to Machine Code
(more later in course)
foo.S bar.S Assembler source files (text)
Assembler converts human-
Assembler Assembler readable assembly code to
instruction bit patterns
foo.o bar.o Machine code object files
Program
Bytes
One RISC-V Instruction = 32 bits
Data
04/25/2024 14
Program Execution
Memory
Processor Read
Control Instruction
Bits
Program
Datapath
PC Instruction Bytes
Address
Registers
Arithmetic & Logic Unit Data
(ALU)
• PC (program counter) is internal register inside processor holding byte address
of next instruction to be executed
• Instruction is fetched from memory, then control unit executes instruction using
datapath and memory system, and updates program counter (default is add +4
bytes to PC, to move to next sequential instruction)
04/25/2024 15
In the News: Why fast computers matter
04/25/2024 17
Helpful RISC-V Assembler Features
• Symbolic register names
– E.g., a0-a7 for argument registers (x10-x17)
– E.g., zero for x0
• Pseudo-instructions
– Shorthand syntax for common assembly idioms
– E.g., mv rd, rs = addi rd, rs, 0
– E.g.2, li rd, 13 = addi rd, x0, 13
18
RISC-V Symbolic Register Names
Numbers
hardware
understands
Human-friendly
symbolic names
in assembly
code
19
Outline
• RISC-V ISA and C-to-RISC-V Review
• Program Execution Overview
• Function Call
• Function Call Example
• And in Conclusion …
04/25/2024 20
Six Fundamental Steps in
Calling a Function
1. Put parameters in a place where function can access them
2. Transfer control to function
3. Acquire (local) storage resources needed for function
4. Perform desired task of the function
5. Put result value in a place where calling code can access it
and restore any registers you used
6. Return control to point of origin, since a function can be
called from several points in a program
04/25/2024 21
RISC-V Function Call Conventions
• Registers faster than memory, so use them
• a0–a7 (x10-x17): eight argument registers to
pass parameters and two return values (a0-a1)
• ra: one return address register to return to the point
of origin (x1)
04/25/2024 22
Instruction Support for Functions (1/4)
... sum(a,b);... /* a,b:s0,s1 */
}
C
1004
1008 stored in memory just like data. So here we
1012 show the addresses of where the programs
1016 are stored.
…
2000
2004
04/25/2024 23
Instruction Support for Functions (2/4)
... sum(a,b);... /* a,b:s0,s1 */
}
C
1004 mv a1,s1# y = b
1008 addi ra,zero,1016 #ra=1016
1012 j sum #jump to sum
1016 … # next instruction
…
2000 sum: add a0,a0,a1
2004 jr ra
04/25/2024 # new instr. “jump register” 24
Instruction Support for Functions (3/4)
... sum(a,b);... /* a,b:s0,s1 */
}
C
04/25/2024 26
RISC-V Function Call Instructions
• Invoke function: jump and link instruction (jal)
(really should be laj “link and jump”)
– “link” means form an address or link that points to
calling site to allow function to return to proper address
– Jumps to address and simultaneously saves the address of the following
instruction in register ra
jal FunctionLabel
04/25/2024 28
Example
int Leaf
(int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
• Parameter variables g, h, i, and j in argument registers a0, a1, a2, and
a3, and f in s0
• Assume need one temporary register s1
04/25/2024 29
Where Are Old Register Values Saved
to Restore Them After Function Call?
• Need a place to save old values before call function, restore them
when return, and delete
• Ideal is stack: last-in-first-out queue
(e.g., stack of plates)
– Push: placing data onto stack
– Pop: removing data from stack
• Stack in memory, so need register to point to it
• sp is the stack pointer in RISC-V (x2)
• Convention is grow stack down from high to low addresses
– Push decrements sp, Pop increments sp
04/25/2024 30
RISC-V Code for Leaf()
Leaf: addi sp,sp,-8 # adjust stack for 2 items
sw s1, 4(sp) # save s1 for use afterwards
sw s0, 0(sp) # save s0 for use afterwards
add s0,a0,a1 # f = g + h
add s1,a2,a3 # s1 = i + j
sub a0,s0,s1 # return value (g + h) – (i + j)
sp sp
Saved s1 Saved s1
sp Saved s0 Saved s0
04/25/2024 33
New RISC-V book!
• “The RISC-V Reader”, David Patterson,
Andrew Waterman
• Available at
• https://www.createspace.com/7439283
• Early print edition $9.99
• Kindle edition to follow at some point
04/25/2024 35
What If a Function Calls a Function? Recursive
Function Calls?
04/25/2024 36
Nested Procedures (1/2)
int sumSquare(int x, int y) {
return mult(x,x)+ y;
}
• Something called sumSquare, now sumSquare is calling
mult
• So there’s a value in ra that sumSquare wants to jump back
to, but this will be overwritten by the call to mult
04/25/2024 40
Peer Instruction
• Which statement is FALSE?
• RED: RISC-V uses jal to invoke a function and
jr to return from a function
• GREEN: jal saves PC+1 in ra
• ORANGE: The callee can use temporary registers (ti) without
saving and restoring them
• YELLOW: The caller can rely on save registers (si) without fear
of callee changing them
04/25/2024 41
Allocating Space on Stack
• C has two storage classes: automatic and static
– Automatic variables are local to function and discarded when
function exits
– Static variables exist across exits from and entries to procedures
• Use stack for automatic (local) variables that don’t fit in
registers
• Procedure frame or activation record: segment of stack
with saved registers and local variables
04/25/2024 42
Stack Before, During, After Function
sp sp
Saved return
address (if needed)
Saved argument
registers (if any)
Saved saved
registers (if any)
Local variables
sp (if any)
04/25/2024 44
Using the Stack (2/2)
int sumSquare(int x, int y) {
sumSquare: return mult(x,x)+ y; }
addi sp,sp,-8 # space on stack
“push” sw ra, 4(sp) # save ret addr
sw a1, 0(sp) # save y
mv a1,a0 # mult(x,x)
jal mult # call mult
lw a1, 0(sp) # restore y
add a0,a0,a1 # mult()+y
lw ra, 4(sp) # get ret addr
“pop” addi sp,sp,8 # restore stack
jr ra
mult: ...
04/25/2024 45
Where is the Stack in Memory?
• RV32 convention (RV64 and RV128 have different memory layouts)
• Stack starts in high memory and grows down
– Hexadecimal (base 16) : bfff_fff0hex
– Stack must be aligned on 16-byte boundary (not true in examples above)
• RV32 programs (text segment) in low end
– 0001_0000hex
• static data segment (constants and other static variables) above text for static variables
– RISC-V convention global pointer (gp) points to static
– RV32 gp = 1000_0000hex
• Heap above static for data structures that grow and shrink ; grows up to high addresses
04/25/2024 46
RV32 Memory Allocation
04/25/2024 47
Outline
• RISC-V ISA and C-to-RISC-V Review
• Program Execution Overview
• Function Call
• Function Call Example
• And in Conclusion …
04/25/2024 48
And in Conclusion …
• Functions called with jal, return with jr ra.
• The stack is your friend: Use it to save anything you need. Just leave it the way you found it!
• Instructions we know so far…
Arithmetic: add, addi, sub
Memory: lw, sw, lb, lbu, sb
Decision: beq, bne, blt, bge
Unconditional Branches (Jumps): j, jal, jr
• Registers we know so far
– All of them!
– a0-a7 for function arguments, a0-a1 for return values
– sp, stack pointer, ra return address
– s0-s11 saved registers
– t0-t6 temporaries
– zero
04/25/2024 49