aboutsummaryrefslogtreecommitdiff
path: root/src/rv64.tex
blob: 5de9ea2a8c7f5ff76a092a419b77bfc5822fe172 (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
\chapter{RV64I Base Integer Instruction Set, Version 2.0}
\label{rv64}

This chapter describes the RV64I base integer instruction set, which
builds upon the RV32I variant described in Chapter~\ref{rv32}.  This
chapter presents only the differences with RV32I, so should be read in
conjunction with the earlier chapter.

\section{Register State}

RV64I widens the integer registers and supported user address space to
64 bits (XLEN=64 in Figure~\ref{gprs}).

\section{Integer Computational Instructions}

Additional instruction variants are provided to manipulate 32-bit
values in RV64I, indicated by a `W' suffix to the opcode.  These
``*W'' instructions ignore the upper 32 bits of their inputs and
always produce 32-bit signed values, i.e. bits XLEN-1 through 31 are
equal.  They cause an illegal instruction exception in RV32I.

\begin{commentary}
The compiler and calling convention maintain an invariant that all 32-bit
values are held in a sign-extended format in 64-bit registers.  Even 32-bit
unsigned integers extend bit 31 into bits 63 through 32.  Consequently,
conversion between unsigned and signed 32-bit integers is a no-op,
as is conversion from a signed 32-bit integer to a signed 64-bit
integer.  Existing 64-bit wide SLTU and unsigned branch compares still operate
correctly on unsigned 32-bit integers under this invariant.  Similarly,
existing 64-bit wide logical operations on 32-bit sign-extended integers
preserve the sign-extension property.  A few new instructions
(ADD[I]W/SUBW/SxxW) are required for addition and shifts to ensure reasonable
performance for 32-bit values.
\end{commentary}

\newpage
\subsubsection*{Integer Register-Immediate Instructions}
\vspace{-0.4in}
\begin{center}
\begin{tabular}{M@{}R@{}S@{}R@{}O}
\\
\instbitrange{31}{20} &
\instbitrange{19}{15} &
\instbitrange{14}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{imm[11:0]} &
\multicolumn{1}{c|}{rs1} &
\multicolumn{1}{c|}{funct3} &
\multicolumn{1}{c|}{rd} &
\multicolumn{1}{c|}{opcode} \\
\hline
12 & 5 & 3 & 5 & 7 \\
I-immediate[11:0] & src & ADDIW  & dest & OP-IMM-32 \\
\end{tabular}
\end{center}

ADDIW is an RV64I-only instruction that adds the sign-extended 12-bit
immediate to register {\em rs1} and produces the proper sign-extension
of a 32-bit result in {\em rd}.  Overflows are ignored and the result
is the low 32 bits of the result sign-extended to 64 bits.  Note,
ADDIW {\em rd, rs1, 0} writes the sign-extension of the lower 32 bits
of register {\em rs1} into register {\em rd} (assembler pseudo-op
SEXT.W).

\vspace{-0.2in}
\begin{center}
\begin{tabular}{R@{}W@{}R@{}R@{}R@{}R@{}O}
\\
\instbitrange{31}{26} &
\multicolumn{1}{c}{\instbit{25}} &
\instbitrange{24}{20} &
\instbitrange{19}{15} &
\instbitrange{14}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{imm[11:6]} &
\multicolumn{1}{|c|}{imm[5]} &
\multicolumn{1}{|c|}{imm[4:0]} &
\multicolumn{1}{c|}{rs1} &
\multicolumn{1}{c|}{funct3} &
\multicolumn{1}{c|}{rd} &
\multicolumn{1}{c|}{opcode} \\
\hline
6 & \multicolumn{1}{c}{1} & 5 & 5 & 3 & 5 & 7 \\
000000 & shamt[5] & shamt[4:0]  & src & SLLI & dest & OP-IMM \\
000000 & shamt[5] & shamt[4:0]  & src & SRLI & dest & OP-IMM \\
010000 & shamt[5] & shamt[4:0]  & src & SRAI & dest & OP-IMM \\
000000 &       0  & shamt[4:0]  & src & SLLIW & dest & OP-IMM-32 \\
000000 &       0  & shamt[4:0]  & src & SRLIW & dest & OP-IMM-32 \\
010000 &       0  & shamt[4:0]  & src & SRAIW & dest & OP-IMM-32 \\
\end{tabular}
\end{center}

Shifts by a constant are encoded as a specialization of the I-type
format using the same instruction opcode as RV32I.  The operand to be
shifted is in {\em rs1}, and the shift amount is encoded in the lower
6 bits of the I-immediate field for RV64I.  The right shift type is
encoded in bit 30.  SLLI is a logical left shift (zeros are shifted
into the lower bits); SRLI is a logical right shift (zeros are shifted
into the upper bits); and SRAI is an arithmetic right shift (the
original sign bit is copied into the vacated upper bits).  For RV32I,
SLLI, SRLI, and SRAI generate an illegal instruction exception if
$imm[5] \neq 0$.

SLLIW, SRLIW, and SRAIW are RV64I-only instructions that are
analogously defined but operate on 32-bit values and produce
signed 32-bit results.  SLLIW, SRLIW, and SRAIW generate an illegal
instruction exception if $imm[5] \neq 0$.

\vspace{-0.2in}
\begin{center}
\begin{tabular}{U@{}R@{}O}
\\
\instbitrange{31}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{imm[31:12]} &
\multicolumn{1}{c|}{rd} &
\multicolumn{1}{c|}{opcode} \\
\hline
20 & 5 & 7 \\
U-immediate[31:12] & dest & LUI \\
U-immediate[31:12] & dest & AUIPC
\end{tabular}
\end{center}


LUI (load upper immediate) uses the same opcode as RV32I.  LUI places
the 20-bit U-immediate into bits 31--12 of register {\em rd} and
places zero in the lowest 12 bits.  The 32-bit result is
sign-extended to 64 bits.

AUIPC (add upper immediate to {\tt pc}) uses the same opcode as RV32I.
AUIPC (add upper immediate to {\tt pc}) is used to build {\tt
  pc}-relative addresses and uses the U-type format.  AUIPC appends 12
low-order zero bits to the 20-bit U-immediate, sign-extends the result
to 64 bits, then adds it to the {\tt pc} and places the result in
register {\em rd}.

\subsubsection*{Integer Register-Register Operations}

\vspace{-0.2in}
\begin{center}
\begin{tabular}{S@{}R@{}R@{}S@{}R@{}O}
\\
\instbitrange{31}{25} &
\instbitrange{24}{20} &
\instbitrange{19}{15} &
\instbitrange{14}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{funct7} &
\multicolumn{1}{c|}{rs2} &
\multicolumn{1}{c|}{rs1} &
\multicolumn{1}{c|}{funct3} &
\multicolumn{1}{c|}{rd} &
\multicolumn{1}{c|}{opcode} \\
\hline
7 & 5 & 5 & 3 & 5 & 7 \\
0000000 & src2 & src1 & SLL/SRL     & dest & OP    \\
0100000 & src2 & src1 & SRA         & dest & OP    \\
0000000 & src2 & src1 & ADDW        & dest & OP-32    \\
0000000 & src2 & src1 & SLLW/SRLW   & dest & OP-32    \\
0100000 & src2 & src1 & SUBW/SRAW   & dest & OP-32    \\
\end{tabular}
\end{center}

ADDW and SUBW are RV64I-only instructions that are defined analogously
to ADD and SUB but operate on 32-bit values and produce signed 32-bit
results.  Overflows are ignored, and the low 32-bits of the result is
sign-extended to 64-bits and written to the destination register.

SLL, SRL, and SRA perform logical left, logical right, and arithmetic
right shifts on the value in register {\em rs1} by the shift amount
held in register {\em rs2}.  In RV64I, only the low 6 bits of {\em
  rs2} are considered for the shift amount.

SLLW, SRLW, and SRAW are RV64I-only instructions that are analogously
defined but operate on 32-bit values and produce signed 32-bit
results.  The shift amount is given by {\em rs2[4:0]}.

\section{Load and Store Instructions}

RV64I extends the address space to 64 bits.  The execution environment
will define what portions of the address space are legal to access.

\vspace{-0.4in}
\begin{center}
\begin{tabular}{M@{}R@{}S@{}R@{}O}
\\
\instbitrange{31}{20} &
\instbitrange{19}{15} &
\instbitrange{14}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{imm[11:0]} &
\multicolumn{1}{c|}{rs1} &
\multicolumn{1}{c|}{funct3} &
\multicolumn{1}{c|}{rd} &
\multicolumn{1}{c|}{opcode} \\
\hline
12 & 5 & 3 & 5 & 7 \\
offset[11:0] & base & width & dest & LOAD \\
\end{tabular}
\end{center}

\vspace{-0.2in}
\begin{center}
\begin{tabular}{O@{}R@{}R@{}S@{}R@{}O}
\\
\instbitrange{31}{25} &
\instbitrange{24}{20} &
\instbitrange{19}{15} &
\instbitrange{14}{12} &
\instbitrange{11}{7} &
\instbitrange{6}{0} \\
\hline
\multicolumn{1}{|c|}{imm[11:5]} &
\multicolumn{1}{c|}{rs2} &
\multicolumn{1}{c|}{rs1} &
\multicolumn{1}{c|}{funct3} &
\multicolumn{1}{c|}{imm[4:0]} &
\multicolumn{1}{c|}{opcode} \\
\hline
7 & 5 & 5 & 3 & 5 & 7 \\
offset[11:5] & src & base & width & offset[4:0] & STORE \\
\end{tabular}
\end{center}

The LD instruction loads a 64-bit value from memory into register {\em
  rd} for RV64I.

The LW instruction loads a 32-bit value from memory and sign-extends
this to 64 bits before storing it in register {\em rd} for RV64I.  The
LWU instruction, on the other hand, zero-extends the 32-bit value from
memory for RV64I.  LH and LHU are defined analogously for 16-bit
values, as are LB and LBU for 8-bit values.  The SD, SW, SH, and SB
instructions store 64-bit, 32-bit, 16-bit, and 8-bit values from the
low bits of register {\em rs2} to memory respectively.

\section{System Instructions}

In RV64I, the CSR instructions can manipulate 64-bit CSRs.  In particular, the
RDCYCLE, RDTIME, and RDINSTRET pseudo-instructions read the full 64 bits of
the {\tt cycle}, {\tt time}, and {\tt instret} counters.  Hence, the RDCYCLEH,
RDTIMEH, and RDINSTRETH instructions are not necessary and are illegal in
RV64I.