Skip to content

Commit 825cc5e

Browse files
Add Zclsd extension YAML (#577)
This PR adds the Zclsd extension to the database. Zclsd introduces compressed load/store pair instructions for RV32 by reusing RV64-only instruction encodings, which helps improve code density and performance when leveraging a wider than XLEN memory interface. It defines 16-bit instruction encodings and utilizes the same even-odd register pairing as the Zdinx extension. Additionally, Zclsd depends on the Zilsd and Zca extensions, and it is incompatible with Zcf due to overlapping encodings Closes #572 --------- Signed-off-by: Shehroz Kashif <131602772+Shehrozkashif@users.noreply.github.com> Co-authored-by: Paul Clarke <ThinkOpenly@gmail.com>
1 parent 805159a commit 825cc5e

File tree

6 files changed

+262
-77
lines changed

6 files changed

+262
-77
lines changed

arch/ext/Zclsd.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
$schema: "ext_schema.json#"
2+
kind: extension
3+
name: Zclsd
4+
conflicts: Zcf
5+
long_name: Compressed Load/Store Pair for RV32
6+
description: |
7+
This extension adds load and store instructions using register pairs. It does so by reusing existing instruction encodings which are RV64-only. The specification defines 16-bit encodings.
8+
Load and store instructions will use the same definition of even-odd pairs as defined by the Zdinx extension.
9+
The extension improves static code density, by replacing two separate load or store instructions with a single one. In addition, it can provide a performance improvement for implementations that can make use of a wider than XLEN memory interface.
10+
type: unprivileged
11+
versions:
12+
- version: "1.0"
13+
state: ratified
14+
ratification_date: "2025-02"
15+
requires:
16+
allOf: [ Zilsd, Zca ]

arch/inst/C/c.ld.yaml

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,39 @@ kind: instruction
55
name: c.ld
66
long_name: Load double
77
description: |
8-
Loads a 64-bit value from memory into register rd.
8+
Loads a 64-bit value from memory into register xd.
99
It computes an effective address by adding the zero-extended offset, scaled by 8,
10-
to the base address in register rs1.
11-
It expands to `ld` `rd, offset(rs1)`.
10+
to the base address in register xs1.
11+
It expands to `ld` `xd, offset(xs1)`.
12+
For RV32, if the Zclsd extension is enabled, this instruction loads a 64-bit value into registers xd and xd+1. It computes an effective address by adding the zero-extended imm, scaled by 8, to the base address in register xs1.
1213
definedBy:
1314
anyOf:
1415
- C
1516
- Zca
16-
base: 64
17+
- Zclsd
1718
assembly: xd, imm(xs1)
1819
encoding:
19-
match: 011-----------00
20-
variables:
21-
- name: imm
22-
location: 6-5|12-10
23-
left_shift: 3
24-
- name: rd
25-
location: 4-2
26-
- name: rs1
27-
location: 9-7
20+
RV32:
21+
match: 011-----------00
22+
variables:
23+
- name: imm
24+
location: 6-5|12-10
25+
left_shift: 3
26+
- name: xd
27+
location: 4-2
28+
not: [1, 3, 5, 7]
29+
- name: xs1
30+
location: 9-7
31+
RV64:
32+
match: 011-----------00
33+
variables:
34+
- name: imm
35+
location: 6-5|12-10
36+
left_shift: 3
37+
- name: xd
38+
location: 4-2
39+
- name: xs1
40+
location: 9-7
2841
access:
2942
s: always
3043
u: always
@@ -35,9 +48,18 @@ operation(): |
3548
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
3649
}
3750
38-
XReg virtual_address = X[creg2reg(rs1)] + imm;
39-
40-
X[creg2reg(rd)] = sext(read_memory<64>(virtual_address, $encoding), 64);
51+
if (xlen() == 32) {
52+
if (implemented?(ExtensionName::Zclsd)) {
53+
Bits<64> val = read_memory<64>(X[creg2reg(xs1)] + imm, $encoding);
54+
X[creg2reg(xd)] = val[31:0];
55+
X[creg2reg(xd + 1)] = val[63:32];
56+
} else {
57+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
58+
}
59+
} else {
60+
XReg virtual_address = X[creg2reg(xs1)] + imm;
61+
X[creg2reg(xd)] = sext(read_memory<64>(virtual_address, $encoding), 64);
62+
}
4163
4264
# SPDX-SnippetBegin
4365
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>
@@ -57,13 +79,13 @@ sail(): |
5779
TR_Address(paddr, _) =>
5880
match (width) {
5981
BYTE =>
60-
process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
82+
process_load(xd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
6183
HALF =>
62-
process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
63-
WORD =>
64-
process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
84+
process_load(xd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
85+
WOxD =>
86+
process_load(xd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
6587
DOUBLE if sizeof(xlen) >= 64 =>
66-
process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
88+
process_load(xd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
6789
_ => report_invalid_width(__FILE__, __LINE__, width, "load")
6890
}
6991
}

arch/inst/C/c.ldsp.yaml

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,34 @@ name: c.ldsp
66
long_name: Load doubleword from stack pointer
77
description: |
88
C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from memory
9-
into register rd.
9+
into register xd.
1010
It computes its effective address by adding the zero-extended offset, scaled by 8,
1111
to the stack pointer, x2.
12-
It expands to `ld` `rd, offset(x2)`.
13-
C.LDSP is only valid when rd &ne; x0 the code points with rd=x0 are reserved.
12+
It expands to `ld xd, offset(x2)`.
13+
C.LDSP is only valid when xd ≠ x0; code points with xd=x0 are reserved.
1414
definedBy:
1515
anyOf:
1616
- C
1717
- Zca
18-
base: 64
1918
assembly: xd, imm(sp)
2019
encoding:
21-
match: 011-----------10
22-
variables:
23-
- name: imm
24-
location: 4-2|12|6-5
25-
left_shift: 3
26-
- name: rd
27-
location: 11-7
28-
not: 0
20+
RV32:
21+
match: 011-----------10
22+
variables:
23+
- name: imm
24+
location: 4-2|12|6-5
25+
left_shift: 3
26+
- name: xd
27+
location: 11-7
28+
not: [0, 1, 3, 5, 7]
29+
RV64:
30+
match: 011-----------10
31+
variables:
32+
- name: imm
33+
location: 4-2|12|6-5
34+
left_shift: 3
35+
- name: xd
36+
location: 11-7
2937
access:
3038
s: always
3139
u: always
@@ -37,5 +45,11 @@ operation(): |
3745
}
3846
3947
XReg virtual_address = X[2] + imm;
48+
Bits<64> value = read_memory<64>(virtual_address, $encoding);
4049
41-
X[rd] = read_memory<64>(virtual_address, $encoding);
50+
if (xlen()== 64) {
51+
X[creg2reg(xd)] = value;
52+
} else if (xlen() == 32) {
53+
X[creg2reg(xd)] = value[31:0];
54+
X[creg2reg(xd) + 1] = value[63:32];
55+
}

arch/inst/C/c.sd.yaml

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,38 @@ kind: instruction
55
name: c.sd
66
long_name: Store double
77
description: |
8-
Stores a 64-bit value in register rs2 to memory.
8+
For RV64, store a 64-bit value in register xs2 to memory. For RV32 with Zclsd extension, store a 64-bit value from the combined values in register pair [xs2, xs2+1] to memory.
99
It computes an effective address by adding the zero-extended offset, scaled by 8,
10-
to the base address in register rs1.
11-
It expands to `sd` `rs2, offset(rs1)`.
10+
to the base address in register xs1.
11+
It expands to `sd` `xs2, offset(xs1)`.
1212
definedBy:
1313
anyOf:
1414
- C
1515
- Zca
16-
base: 64
16+
- Zclsd
1717
assembly: xs2, imm(xs1)
1818
encoding:
19-
match: 111-----------00
20-
variables:
21-
- name: imm
22-
location: 6-5|12-10
23-
left_shift: 3
24-
- name: rs2
25-
location: 4-2
26-
- name: rs1
27-
location: 9-7
19+
RV32:
20+
match: 111-----------00
21+
variables:
22+
- name: imm
23+
location: 6-5|12-10
24+
left_shift: 3
25+
- name: xs2
26+
location: 4-2
27+
not: [1, 3, 5, 7]
28+
- name: xs1
29+
location: 9-7
30+
RV64:
31+
match: 111-----------00
32+
variables:
33+
- name: imm
34+
location: 6-5|12-10
35+
left_shift: 3
36+
- name: xs2
37+
location: 4-2
38+
- name: xs1
39+
location: 9-7
2840
access:
2941
s: always
3042
u: always
@@ -35,6 +47,15 @@ operation(): |
3547
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
3648
}
3749
38-
XReg virtual_address = X[creg2reg(rs1)] + imm;
50+
XReg virtual_address = X[creg2reg(xs1)] + imm;
3951
40-
write_memory<64>(virtual_address, X[creg2reg(rs2)], $encoding);
52+
if (xlen() == 32) {
53+
if (implemented?(ExtensionName::Zclsd)) {
54+
Bits<64> data = {X[creg2reg(xs2) + 1], X[creg2reg(xs2)]};
55+
write_memory<64>(virtual_address, data, $encoding);
56+
} else {
57+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
58+
}
59+
} else {
60+
write_memory<64>(virtual_address, X[creg2reg(xs2)], $encoding);
61+
}

arch/inst/C/c.sdsp.yaml

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,26 @@ definedBy:
1313
anyOf:
1414
- C
1515
- Zca
16-
base: 64
16+
- Zclsd
1717
assembly: xs2, imm(sp)
1818
encoding:
19-
match: 111-----------10
20-
variables:
21-
- name: imm
22-
location: 9-7|12-10
23-
left_shift: 3
24-
- name: rs2
25-
location: 6-2
19+
RV32:
20+
match: 111-----------10
21+
variables:
22+
- name: xs2
23+
location: 6-2
24+
not: [1, 3, 5, 7]
25+
- name: imm
26+
location: 9-7|12-10
27+
left_shift: 3
28+
RV64:
29+
match: 111-----------10
30+
variables:
31+
- name: xs2
32+
location: 6-2
33+
- name: imm
34+
location: 9-7|12-10
35+
left_shift: 3
2636
access:
2737
s: always
2838
u: always
@@ -35,4 +45,13 @@ operation(): |
3545
3646
XReg virtual_address = X[2] + imm;
3747
38-
write_memory<64>(virtual_address, X[rs2], $encoding);
48+
if (xlen() == 32) {
49+
if (implemented?(ExtensionName::Zclsd)) {
50+
Bits<64> data = {X[creg2reg(xs2) + 1], X[creg2reg(xs2)]};
51+
write_memory<64>(virtual_address, data, $encoding);
52+
} else {
53+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
54+
}
55+
} else {
56+
write_memory<64>(virtual_address, X[creg2reg(xs2)], $encoding);
57+
}

0 commit comments

Comments
 (0)