Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions arch/ext/Zclsd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
$schema: "ext_schema.json#"
kind: extension
name: Zclsd
conflicts: Zcf
long_name: Compressed Load/Store Pair for RV32
description: |
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.
Load and store instructions will use the same definition of even-odd pairs as defined by the Zdinx extension.
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.
type: unprivileged
versions:
- version: "1.0"
state: ratified
ratification_date: "2025-02"
requires:
allOf: [ Zilsd, Zca ]
64 changes: 43 additions & 21 deletions arch/inst/C/c.ld.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,39 @@ kind: instruction
name: c.ld
long_name: Load double
description: |
Loads a 64-bit value from memory into register rd.
Loads a 64-bit value from memory into register xd.
It computes an effective address by adding the zero-extended offset, scaled by 8,
to the base address in register rs1.
It expands to `ld` `rd, offset(rs1)`.
to the base address in register xs1.
It expands to `ld` `xd, offset(xs1)`.
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.
definedBy:
anyOf:
- C
- Zca
base: 64
- Zclsd
assembly: xd, imm(xs1)
encoding:
match: 011-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: rd
location: 4-2
- name: rs1
location: 9-7
RV32:
match: 011-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: xd
location: 4-2
not: [1, 3, 5, 7]
- name: xs1
location: 9-7
RV64:
match: 011-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: xd
location: 4-2
- name: xs1
location: 9-7
access:
s: always
u: always
Expand All @@ -35,9 +48,18 @@ operation(): |
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}

XReg virtual_address = X[creg2reg(rs1)] + imm;

X[creg2reg(rd)] = sext(read_memory<64>(virtual_address, $encoding), 64);
if (xlen() == 32) {
if (implemented?(ExtensionName::Zclsd)) {
Bits<64> val = read_memory<64>(X[creg2reg(xs1)] + imm, $encoding);
X[creg2reg(xd)] = val[31:0];
X[creg2reg(xd + 1)] = val[63:32];
} else {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
} else {
XReg virtual_address = X[creg2reg(xs1)] + imm;
X[creg2reg(xd)] = sext(read_memory<64>(virtual_address, $encoding), 64);
}

# SPDX-SnippetBegin
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>
Expand All @@ -57,13 +79,13 @@ sail(): |
TR_Address(paddr, _) =>
match (width) {
BYTE =>
process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
process_load(xd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
HALF =>
process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
WORD =>
process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
process_load(xd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
WOxD =>
process_load(xd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
DOUBLE if sizeof(xlen) >= 64 =>
process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
process_load(xd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
_ => report_invalid_width(__FILE__, __LINE__, width, "load")
}
}
Expand Down
40 changes: 27 additions & 13 deletions arch/inst/C/c.ldsp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,34 @@ name: c.ldsp
long_name: Load doubleword from stack pointer
description: |
C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from memory
into register rd.
into register xd.
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 &ne; x0 the code points with rd=x0 are reserved.
It expands to `ld xd, offset(x2)`.
C.LDSP is only valid when xd ≠ x0; code points with xd=x0 are reserved.
definedBy:
anyOf:
- C
- Zca
base: 64
assembly: xd, imm
encoding:
match: 011-----------10
variables:
- name: imm
location: 4-2|12|6-5
left_shift: 3
- name: rd
location: 11-7
not: 0
RV32:
match: 011-----------10
variables:
- name: imm
location: 4-2|12|6-5
left_shift: 3
- name: xd
location: 11-7
not: [0, 1, 3, 5, 7]
RV64:
match: 011-----------10
variables:
- name: imm
location: 4-2|12|6-5
left_shift: 3
- name: xd
location: 11-7
access:
s: always
u: always
Expand All @@ -37,5 +45,11 @@ operation(): |
}

XReg virtual_address = X[2] + imm;
Bits<64> value = read_memory<64>(virtual_address, $encoding);

X[rd] = read_memory<64>(virtual_address, $encoding);
if (xlen()== 64) {
X[creg2reg(xd)] = value;
} else if (xlen() == 32) {
X[creg2reg(xd)] = value[31:0];
X[creg2reg(xd) + 1] = value[63:32];
}
51 changes: 36 additions & 15 deletions arch/inst/C/c.sd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,38 @@ kind: instruction
name: c.sd
long_name: Store double
description: |
Stores a 64-bit value in register rs2 to memory.
Stores a 64-bit value in register xs2 to memory.
It computes an effective address by adding the zero-extended offset, scaled by 8,
to the base address in register rs1.
It expands to `sd` `rs2, offset(rs1)`.
to the base address in register xs1.
It expands to `sd` `xs2, offset(xs1)`.
definedBy:
anyOf:
- C
- Zca
base: 64
- Zclsd
assembly: xs2, imm(xs1)
encoding:
match: 111-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: rs2
location: 4-2
- name: rs1
location: 9-7
RV32:
match: 111-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: xs2
location: 4-2
not: [1, 3, 5, 7]
- name: xs1
location: 9-7
RV64:
match: 111-----------00
variables:
- name: imm
location: 6-5|12-10
left_shift: 3
- name: xs2
location: 4-2
- name: xs1
location: 9-7
access:
s: always
u: always
Expand All @@ -35,6 +47,15 @@ operation(): |
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}

XReg virtual_address = X[creg2reg(rs1)] + imm;
XReg virtual_address = X[creg2reg(xs1)] + imm;

write_memory<64>(virtual_address, X[creg2reg(rs2)], $encoding);
if (xlen() == 32) {
if (implemented?(ExtensionName::Zclsd)) {
Bits<64> data = {X[creg2reg(xs2) + 1], X[creg2reg(xs2)]};
write_memory<64>(virtual_address, data, $encoding);
} else {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
} else {
write_memory<64>(virtual_address, X[creg2reg(xs2)], $encoding);
}
36 changes: 28 additions & 8 deletions arch/inst/C/c.sdsp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,27 @@ definedBy:
anyOf:
- C
- Zca
- Zclsd
base: 64
assembly: xs2, imm
encoding:
match: 111-----------10
variables:
- name: imm
location: 9-7|12-10
left_shift: 3
- name: rs2
location: 6-2
RV32:
match: 111-----------10
variables:
- name: xs2
location: 6-2
not: [1, 3, 5, 7]
- name: imm
location: 9-7|12-10
left_shift: 3
RV64:
match: 111-----------10
variables:
- name: xs2
location: 6-2
- name: imm
location: 9-7|12-10
left_shift: 3
access:
s: always
u: always
Expand All @@ -35,4 +46,13 @@ operation(): |

XReg virtual_address = X[2] + imm;

write_memory<64>(virtual_address, X[rs2], $encoding);
if (xlen() == 32) {
if (implemented?(ExtensionName::Zclsd)) {
Bits<64> data = {X[creg2reg(xs2) + 1], X[creg2reg(xs2)]};
write_memory<64>(virtual_address, data, $encoding);
} else {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
} else {
write_memory<64>(virtual_address, X[creg2reg(xs2)], $encoding);
}
Loading
Loading