This repository has been archived by the owner on Jul 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lecture7.tex
136 lines (115 loc) · 5.39 KB
/
lecture7.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
\chapter{RISC-V Instructions, Functions}
\section{Program Counter}
PC is a register that holds the byte address of the next instruction to be executed. To move to the next instruction, the processor default increments PC by 4 bytes.
\section{Jump}
What if we want PC to execute a function at a different location? Jump instructions need to do two things:
\begin{enumerate}
\item Store the return address
\item Update the value of the PC
\end{enumerate}
\begin{description}
\item[JAL:] \texttt{jal rd, label}
"Link" means forming an \emph{address} or \emph{link} that points to the calling site to allow function to return to proper address. "Jump" simultaneously goes to the desired function and saves the address of the following instruction in \texttt{rd}.
JAL is used to \underline{jump to functions} by jumping to a location based on offset from current PC.
\begin{itemize}
\item rd = PC + 4
\item PC = PC + offset
\end{itemize}
\item[J:] \texttt{jal x0, label} $\rightarrow$ \texttt{j label}
Return address not saved.
\begin{itemize}
\item PC = PC + offset
\end{itemize}
\item[JALR:] \texttt{jalr rd, rs, imm}
When returning from a function, the return address will be stored in a register.
JALR is used to \underline{return from function calls} by jumping to a location based on offset from source register.
\begin{itemize}
\item rd = PC + 4
\item PC = rs + imm
\end{itemize}
\item[JR:] \texttt{jalr x0, rd, 0} $\rightarrow$ \texttt{jr rd}
\begin{itemize}
\item PC = rd
\end{itemize}
\item[RET:] \texttt{jalr x0, ra, 0} $\rightarrow$ \texttt{jr ra} $\rightarrow$ \texttt{ret}
\begin{itemize}
\item PC = ra
\end{itemize}
\end{description}
\subsection{Return Address Register}
\begin{itemize}
\item Standard convention: Designate register \texttt{x1} (i.e. \texttt{ra}) to hold return address.
\item We need a return address when jumping to a function.
\item We don't need a return address when jumping in a loop or branch $\implies$ specify \texttt{x0} as destination register to avoid saving the return address.
\end{itemize}
\section{Six Fundamental Steps in Calling a Function}
\begin{enumerate}
\item Put arguments in registers where function can access them
\begin{itemize}
\item Put parameters in argument registers
\end{itemize}
\item Transfer control to function
\begin{itemize}
\item With a jump instruction
\end{itemize}
\item Acquire (local) storage needed for function
\begin{itemize}
\item Make room for local variables on stack
\end{itemize}
\item Perform function's desired task
\item Put return value in a place where calling code can access it and restore any registers used; release local storage
\begin{itemize}
\item \texttt{a0-a1} register
\end{itemize}
\item Return control to point of origin
\begin{itemize}
\item \texttt{ret}
\end{itemize}
\end{enumerate}
\section{Function Call Conventions}
(\emph{More on \href{https://inst.eecs.berkeley.edu/~cs61c/resources/RISCV_Calling_Convention.pdf}{RISC-V calling conventions}}.)
\medskip
RISC-V divides registers into two categories:
\begin{enumerate}
\item Preserved across function call (\emph{callee} must restore before returning):
\begin{itemize}
\item \texttt{sp} (\emph{stack pointer})
\item \texttt{gp} (\emph{global pointer})
\item \texttt{s0-11} (\emph{saved registers})
\end{itemize}
\item Not preserved across function call (\emph{caller} must save them for free usage):
\begin{itemize}
\item \texttt{a0-7} (\emph{argument/return registers})
\item \texttt{ra} (\emph{return address})
\item \texttt{t0-6} (\emph{temporary registers})
\end{itemize}
\end{enumerate}
\begin{tabular}{ |c|c|c|c| }
\hline
\textbf{Register} & \textbf{Name} & \textbf{Description} & \textbf{Saved By} \\
\hline
\texttt{x0} & \texttt{zero} & Always Zero & N/A \\
\texttt{x1} & \texttt{ra} & Return Address & Caller \\
\texttt{x2} & \texttt{sp} & Stack Pointer & Callee \\
\texttt{x3} & \texttt{gp} & Global Pointer & N/A \\
\texttt{x4} & \texttt{tp} & Thread Pointer & N/A \\
\texttt{x5-7} & \texttt{t0-2} & Temporaries & Caller \\
\texttt{x8-9} & \texttt{s0-1} & Saved Registers & Callee \\
\texttt{x10-17} & \texttt{a0-7} & Argument Registers & Caller \\
\texttt{x18-27} & \texttt{s2-11} & Saved Registers & Callee \\
\texttt{x28-31} & \texttt{t3-6} & Temporaries & Caller \\
\hline
\end{tabular}
\subsection{Registers}
\begin{enumerate}
\item Saved registers: preserved across function call, i.e. caller can rely on values being unchanged
\item Temporary registers: not preserved across function call
\end{enumerate}
\section{Stack}
When calling another function, the \emph{caller} saves automatic (local) variables onto the stack so the values don't get overwritten. Before returning from a function, the \emph{callee} restores such values.
\subsection{Stack Pointer}
The SP is a register that holds the memory address of the last item's location. Convention is to grow stack down from high to low addresses, i.e. when stack increases, SP address decreases.
\begin{itemize}
\item \texttt{PUSH}: Decrement the SP when placing an item.
\item \texttt{POP}: Increment the SP when taking an item off.
\end{itemize}