Skip to content

Commit 492f6e0

Browse files
authored
Merge pull request riscv#1767 from riscv/1766-integrate-loadstore-pair-for-rv32
Integrating load/store pair for RV32 with the main manual
2 parents 489e4bb + a2dd99d commit 492f6e0

File tree

4 files changed

+316
-5
lines changed

4 files changed

+316
-5
lines changed

src/colophon.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ h|Extension h|Version h|Status
3535
|*Zihintpause* |*2.0* |*Ratified*
3636
|*Zimop* | *1.0* | *Ratified*
3737
|*Zicond* | *1.0* |*Ratified*
38+
|*Zilsd* | *1.0* |*Ratified*
3839
|*M* |*2.0* |*Ratified*
3940
|*Zmmul* |*1.0* |*Ratified*
4041
|*A* |*2.1* |*Ratified*
@@ -56,6 +57,7 @@ h|Extension h|Version h|Status
5657
|*Zhinxmin* |*1.0* |*Ratified*
5758
|*C* |*2.0* |*Ratified*
5859
|*Zce* |*1.0* |*Ratified*
60+
|*Zclsd* |*1.0* |*Ratified*
5961
|*B* |*1.0* |*Ratified*
6062
|_P_ |_0.2_ |_Draft_
6163
|*V* |*1.0* |*Ratified*
@@ -78,7 +80,7 @@ h|Extension h|Version h|Status
7880

7981
The changes in this version of the document include:
8082

81-
* The inclusion of all ratified extensions through March 2024.
83+
* The inclusion of all ratified extensions through February 2025.
8284
* The draft Zam extension has been removed, in favor of the definition of a misaligned atomicity granule PMA.
8385
* The concept of vacant memory regions has been superseded by inaccessible memory or I/O regions.
8486

src/riscv-unprivileged.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Jan Gray,
8787
Gianluca Guida,
8888
Michael Hamburg,
8989
John Hauser,
90+
Christian Herber,
9091
John Ingalls,
9192
David Horner,
9293
Bruce Hoult,
@@ -190,6 +191,7 @@ include::v-st-ext.adoc[]
190191
include::scalar-crypto.adoc[]
191192
include::vector-crypto.adoc[]
192193
include::unpriv-cfi.adoc[]
194+
include::zilsd.adoc[]
193195
include::rv-32-64g.adoc[]
194196
include::extending.adoc[]
195197
include::naming.adoc[]

src/zfinx.adoc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,11 @@ operand is zero—i.e., `x1` is not accessed.
9797

9898
[NOTE]
9999
====
100-
Load-pair and store-pair instructions are not provided, so transferring
101-
double-precision operands in RV32Zdinx from or to memory requires two
102-
loads or stores. Register moves need only a single FSGNJ.D instruction,
103-
however.
100+
Load-pair and store-pair instructions are contained in a separate extension
101+
(see Section <<sec:zilsd,Extensions for Load/Store pair for RV32>>).
102+
In case this is not available, transferring double-precision operands in
103+
RV32Zdinx from or to memory requires two loads or stores. Register moves need
104+
only a single FSGNJ.D instruction, however.
104105
====
105106
=== Zhinx
106107

src/zilsd.adoc

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
[[sec:zilsd]]
2+
== "Zilsd", "Zclsd" Extensions for Load/Store pair for RV32, Version 1.0
3+
4+
The Zilsd & Zclsd extensions provide load/store pair instructions for RV32, reusing the existing RV64 doubleword load/store instruction encodings.
5+
6+
Operands containing `src` for store instructions and `dest` for load instructions are held in aligned `x`-register pairs, i.e., register numbers must be even. Use of misaligned (odd-numbered) registers for these operands is _reserved_.
7+
8+
Regardless of endianness, the lower-numbered register holds the
9+
low-order bits, and the higher-numbered register holds the high-order
10+
bits: e.g., bits 31:0 of an operand in Zilsd might be held in register `x14`, with bits 63:32 of that operand held in `x15`.
11+
12+
[[zilsd, Zilsd]]
13+
=== Load/Store pair instructions (Zilsd)
14+
15+
The Zilsd extension adds the following RV32-only instructions:
16+
17+
[%header,cols="^1,^1,4,8"]
18+
|===
19+
|RV32
20+
|RV64
21+
|Mnemonic
22+
|Instruction
23+
24+
|yes
25+
|no
26+
|ld rd, offset(rs1)
27+
|<<#insns-ld>>
28+
29+
|yes
30+
|no
31+
|sd rs2, offset(rs1)
32+
|<<#insns-sd>>
33+
34+
|===
35+
36+
As the access size is 64-bit, accesses are only considered naturally aligned for effective addresses that are a multiple of 8.
37+
In this case, these instructions are guaranteed to not raise an address-misaligned exception.
38+
Even if naturally aligned, the memory access might not be performed atomically.
39+
40+
If the effective address is a multiple of 4, then each word access is required to be performed atomically.
41+
42+
The following table summarizes the required behavior:
43+
44+
[%header]
45+
|===
46+
|Alignment |Word accesses guaranteed atomic? |Can cause misaligned trap?
47+
|8B |yes |no
48+
|4B not 8B |yes |yes
49+
|else |no | yes
50+
|===
51+
52+
To ensure resumable trap handling is possible for the load instructions, the base register must have its original value if a trap is taken. The other register in the pair can have been updated.
53+
This affects x2 for the stack pointer relative instruction and rs1 otherwise.
54+
55+
[NOTE]
56+
====
57+
If an implementation performs a doubleword load access atomically and the register file implements writeback for even/odd register pairs,
58+
the mentioned atomicity requirements are inherently fulfilled.
59+
Otherwise, an implementation either needs to delay the writeback until the write can be performed atomically,
60+
or order sequential writes to the registers to ensure the requirement above is satisfied.
61+
====
62+
63+
[[zclsd, Zclsd]]
64+
=== Compressed Load/Store pair instructions (Zclsd)
65+
66+
Zclsd depends on Zilsd and Zca. It has overlapping encodings with Zcf and is thus incompatible with Zcf.
67+
68+
Zclsd adds the following RV32-only instructions:
69+
70+
[%header,cols="^1,^1,4,8"]
71+
|===
72+
|RV32
73+
|RV64
74+
|Mnemonic
75+
|Instruction
76+
77+
|yes
78+
|no
79+
|c.ldsp rd, offset(sp)
80+
|<<#insns-cldsp>>
81+
82+
|yes
83+
|no
84+
|c.sdsp rs2, offset(sp)
85+
|<<#insns-csdsp>>
86+
87+
|yes
88+
|no
89+
|c.ld rd', offset(rs1')
90+
|<<#insns-cld>>
91+
92+
|yes
93+
|no
94+
|c.sd rs2', offset(rs1')
95+
|<<#insns-csd>>
96+
97+
|===
98+
99+
=== Use of x0 as operand
100+
101+
LD instructions with destination `x0` are processed as any other load, but the result is discarded entirely and x1 is not written.
102+
For C.LDSP, usage of `x0` as the destination is reserved.
103+
104+
If using `x0` as `src` of SD or C.SDSP, the entire 64-bit operand is zero — i.e., register `x1` is not accessed.
105+
106+
C.LD and C.SD instructions can only use `x8-15`.
107+
108+
=== Exception Handling
109+
110+
For the purposes of RVWMO and exception handling, LD and SD instructions are
111+
considered to be misaligned loads and stores, with one additional constraint:
112+
an LD or SD instruction whose effective address is a multiple of 4 gives rise
113+
to two 4-byte memory operations.
114+
115+
NOTE: This definition permits LD and SD instructions giving rise to exactly one
116+
memory access, regardless of alignment.
117+
If instructions with 4-byte-aligned effective address are decomposed
118+
into two 32b operations, there is no constraint on the order in which the
119+
operations are performed and each operation is guaranteed to be atomic.
120+
These decomposed sequences are interruptible.
121+
Exceptions might occur on subsequent operations, making the effects of previous
122+
operations within the same instruction visible.
123+
124+
NOTE: Software should make no assumptions about the number or order of
125+
accesses these instructions might give rise to, beyond the 4-byte constraint
126+
mentioned above.
127+
For example, an interrupted store might overwrite the same bytes upon return
128+
from the interrupt handler.
129+
130+
<<<
131+
132+
=== Instructions
133+
[#insns-ld,reftext="Load doubleword to register pair, 32-bit encoding"]
134+
==== ld
135+
136+
Synopsis::
137+
Load doubleword to even/odd register pair, 32-bit encoding
138+
139+
Mnemonic::
140+
ld rd, offset(rs1)
141+
142+
Encoding (RV32)::
143+
[wavedrom, ,svg]
144+
....
145+
{reg: [
146+
{bits: 7, name: 0x3, attr: ['LOAD'], type: 8},
147+
{bits: 5, name: 'rd', attr: ['dest, dest[0]=0'], type: 2},
148+
{bits: 3, name: 0x3, attr: ['width=D'], type: 8},
149+
{bits: 5, name: 'rs1', attr: ['base'], type: 4},
150+
{bits: 12, name: 'imm[11:0]', attr: ['offset[11:0]'], type: 3},
151+
]}
152+
....
153+
154+
Description::
155+
Loads a 64-bit value into registers `rd` and `rd+1`.
156+
The effective address is obtained by adding register rs1 to the
157+
sign-extended 12-bit offset.
158+
159+
Included in: <<zilsd>>
160+
161+
<<<
162+
163+
[#insns-sd,reftext="Store doubleword from register pair, 32-bit encoding"]
164+
==== sd
165+
166+
Synopsis::
167+
Store doubleword from even/odd register pair, 32-bit encoding
168+
169+
Mnemonic::
170+
sd rs2, offset(rs1)
171+
172+
Encoding (RV32)::
173+
[wavedrom, ,svg]
174+
....
175+
{reg: [
176+
{bits: 7, name: 0x23, attr: ['STORE'], type: 8},
177+
{bits: 5, name: 'imm[4:0]', attr: ['offset[4:0]'], type: 3},
178+
{bits: 3, name: 0x3, attr: ['width=D'], type: 8},
179+
{bits: 5, name: 'rs1', attr: ['base'], type: 4},
180+
{bits: 5, name: 'rs2', attr: ['src, src[0]=0'], type: 4},
181+
{bits: 7, name: 'imm[11:5]', attr: ['offset[11:5]'], type: 3},
182+
]}
183+
....
184+
185+
Description::
186+
Stores a 64-bit value from registers `rs2` and `rs2+1`.
187+
The effective address is obtained by adding register rs1 to the
188+
sign-extended 12-bit offset.
189+
190+
Included in: <<zilsd>>
191+
192+
<<<
193+
194+
[#insns-cldsp,reftext="Stack-pointer based load doubleword to register pair, 16-bit encoding"]
195+
==== c.ldsp
196+
197+
Synopsis::
198+
Stack-pointer based load doubleword to even/odd register pair, 16-bit encoding
199+
200+
Mnemonic::
201+
c.ldsp rd, offset(sp)
202+
203+
Encoding (RV32)::
204+
[wavedrom, ,svg]
205+
....
206+
{reg: [
207+
{bits: 2, name: 0x2, type: 8, attr: ['C2']},
208+
{bits: 5, name: 'imm', type: 3, attr: ['offset[4:3|8:6]']},
209+
{bits: 5, name: 'rd', type: 2, attr: ['dest≠0, dest[0]=0']},
210+
{bits: 1, name: 'imm', type: 3, attr: ['offset[5]']},
211+
{bits: 3, name: 0x3, type: 8, attr: ['C.LDSP']},
212+
], config: {bits: 16}}
213+
....
214+
215+
Description::
216+
Loads stack-pointer relative 64-bit value into registers `rd'` and `rd'+1`. It computes its effective address by adding the zero-extended offset, scaled by 8, to the stack pointer, `x2`. It expands to `ld rd, offset(x2)`. C.LDSP is only valid when _rd_&#x2260;x0; the code points with _rd_=x0 are reserved.
217+
218+
Included in: <<zclsd>>
219+
220+
<<<
221+
222+
[#insns-csdsp,reftext="Stack-pointer based store doubleword from register pair, 16-bit encoding"]
223+
==== c.sdsp
224+
225+
Synopsis::
226+
Stack-pointer based store doubleword from even/odd register pair, 16-bit encoding
227+
228+
Mnemonic::
229+
c.sdsp rs2, offset(sp)
230+
231+
Encoding (RV32)::
232+
[wavedrom, ,svg]
233+
....
234+
{reg: [
235+
{bits: 2, name: 0x2, type: 8, attr: ['C2']},
236+
{bits: 5, name: 'rs2', type: 4, attr: ['src, src[0]=0']},
237+
{bits: 6, name: 'imm', type: 3, attr: ['offset[5:3|8:6]']},
238+
{bits: 3, name: 0x7, type: 8, attr: ['C.SDSP']},
239+
], config: {bits: 16}}
240+
....
241+
242+
Description::
243+
Stores a stack-pointer relative 64-bit value from registers `rs2'` and `rs2'+1`. It computes an effective address by adding the _zero_-extended offset, scaled by 8, to the stack pointer, `x2`. It expands to `sd rs2, offset(x2)`.
244+
245+
Included in: <<zclsd>>
246+
247+
<<<
248+
249+
[#insns-cld,reftext="Load doubleword to register pair, 16-bit encoding"]
250+
==== c.ld
251+
252+
Synopsis::
253+
Load doubleword to even/odd register pair, 16-bit encoding
254+
255+
Mnemonic::
256+
c.ld rd', offset(rs1')
257+
258+
Encoding (RV32)::
259+
[wavedrom, ,svg]
260+
....
261+
{reg: [
262+
{bits: 2, name: 0x0, type: 8, attr: ['C0']},
263+
{bits: 3, name: 'rd`', type: 2, attr: ['dest, dest[0]=0']},
264+
{bits: 2, name: 'imm', type: 3, attr: ['offset[7:6]']},
265+
{bits: 3, name: 'rs1`', type: 4, attr: ['base']},
266+
{bits: 3, name: 'imm', type: 3, attr: ['offset[5:3]']},
267+
{bits: 3, name: 0x3, type: 8, attr: ['C.LD']},
268+
], config: {bits: 16}}
269+
....
270+
271+
Description::
272+
Loads a 64-bit value into registers `rd'` and `rd'+1`.
273+
It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1'.
274+
275+
Included in: <<zclsd>>
276+
277+
<<<
278+
279+
[#insns-csd,reftext="Store doubleword from register pair, 16-bit encoding"]
280+
==== c.sd
281+
282+
Synopsis::
283+
Store doubleword from even/odd register pair, 16-bit encoding
284+
285+
Mnemonic::
286+
c.sd rs2', offset(rs1')
287+
288+
Encoding (RV32)::
289+
[wavedrom, ,svg]
290+
....
291+
{reg: [
292+
{bits: 2, name: 0x0, type: 8, attr: ['C0']},
293+
{bits: 3, name: 'rs2`', type: 4, attr: ['src, src[0]=0']},
294+
{bits: 2, name: 'imm', type: 3, attr: ['offset[7:6]']},
295+
{bits: 3, name: 'rs1`', type: 4, attr: ['base']},
296+
{bits: 3, name: 'imm', type: 3, attr: ['offset[5:3]']},
297+
{bits: 3, name: 0x7, type: 8, attr: ['C.SD']},
298+
], config: {bits: 16}}
299+
....
300+
301+
Description::
302+
Stores a 64-bit value from registers `rs2'` and `rs2'+1`.
303+
It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1'.
304+
It expands to `sd rs2', offset(rs1')`.
305+
306+
Included in: <<zclsd>>

0 commit comments

Comments
 (0)