Skip to content

Commit 96c5339

Browse files
authored
Merge pull request #333 from riscv-software-src/Zcb
Zcb spec support initial add
2 parents 3f4ff44 + 8bbbd30 commit 96c5339

File tree

13 files changed

+679
-0
lines changed

13 files changed

+679
-0
lines changed

arch/ext/Zcb.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# yaml-language-server: $schema=../../schemas/ext_schema.json
2+
3+
$schema: "ext_schema.json#"
4+
kind: extension
5+
name: Zcb
6+
long_name: Simple code-size saving instructions
7+
description: |
8+
Zcb has simple code-size saving instructions which are easy to implement on all CPUs.
9+
All proposed encodings are currently reserved for all architectures, and have no conflicts with any existing extensions.
10+
11+
The Zcb extension depends on the Zca extension.
12+
13+
As shown on the individual instruction pages, many of the instructions in Zcb depend upon another extension being implemented.
14+
For example, c.mul is only implemented if M or Zmmul is implemented, and c.sext.b is only implemented if Zbb is implemented.
15+
16+
type: unprivileged
17+
company:
18+
name: RISC-V International
19+
url: https://riscv.org
20+
versions:
21+
- version: "1.0.0"
22+
state: ratified
23+
ratification_date: 2023-04
24+
repositories:
25+
- url: https://github.com/riscv/riscv-code-size-reduction
26+
branch: main
27+
contributors:
28+
- name: Tariq Kurd
29+
- name: Ibrahim Abu Kharmeh
30+
- name: Torbjørn Viem Ness
31+
- name: Matteo Perotti
32+
- name: Nidal Faour
33+
- name: Bill Traynor
34+
- name: Rafael Sene
35+
- name: Xinlong Wu
36+
- name: sinan
37+
- name: Jeremy Bennett
38+
- name: Heda Chen
39+
- name: Alasdair Armstrong
40+
- name: Graeme Smecher
41+
- name: Nicolas Brunie
42+
- name: Jiawei

arch/inst/Zcb/c.lbu.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.lbu
6+
long_name: Load unsigned byte, 16-bit encoding
7+
description: |
8+
Loads a 8-bit value from memory into register rd.
9+
It computes an effective address by adding the zero-extended offset, to the base address in register rs1.
10+
It expands to `lbu` `rd, offset(rs1)`.
11+
definedBy:
12+
anyOf:
13+
- Zcb
14+
- Zce
15+
assembly: xd, imm(xs1)
16+
encoding:
17+
match: 100000--------00
18+
variables:
19+
- name: imm
20+
location: 5|6
21+
- name: rd
22+
location: 4-2
23+
- name: rs1
24+
location: 9-7
25+
access:
26+
s: always
27+
u: always
28+
vs: always
29+
vu: always
30+
operation(): |
31+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
32+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
33+
}
34+
35+
XReg virtual_address = X[rs1+8] + imm;
36+
37+
X[rd+8] = zext(read_memory<8>(virtual_address, $encoding), 8);
38+
39+
sail(): |
40+
{
41+
let offset : xlenbits = zero_extend(imm);
42+
/* Get the address, X(rs1c) + offset.
43+
Some extensions perform additional checks on address validity. */
44+
match ext_data_get_addr(rs1c, offset, Read(Data), width) {
45+
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
46+
Ext_DataAddr_OK(vaddr) =>
47+
if check_misaligned(vaddr, width)
48+
then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL }
49+
else match translateAddr(vaddr, Read(Data)) {
50+
TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
51+
TR_Address(paddr, _) =>
52+
match (width) {
53+
BYTE =>
54+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
55+
HALF =>
56+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
57+
WORD =>
58+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
59+
DOUBLE if sizeof(xlen) >= 64 =>
60+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
61+
_ => report_invalid_width(__FILE__, __LINE__, width, "load")
62+
}
63+
}
64+
}
65+
}

arch/inst/Zcb/c.lh.yaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.lh
6+
long_name: Load signed halfword, 16-bit encoding
7+
description: |
8+
Loads a 16-bit value from memory into register rd.
9+
It computes an effective address by adding the zero-extended offset, to the base address in register rs1.
10+
It expands to `lh` `rd, offset(rs1)`.
11+
definedBy:
12+
anyOf:
13+
- Zcb
14+
- Zce
15+
assembly: xd, imm(xs1)
16+
encoding:
17+
match: 100001---1----00
18+
variables:
19+
- name: imm
20+
location: 5
21+
left_shift: 1
22+
- name: rd
23+
location: 4-2
24+
- name: rs1
25+
location: 9-7
26+
access:
27+
s: always
28+
u: always
29+
vs: always
30+
vu: always
31+
operation(): |
32+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
33+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
34+
}
35+
36+
XReg virtual_address = X[rs1+8] + imm;
37+
38+
X[rd+8] = sext(read_memory<16>(virtual_address, $encoding), 16);
39+
40+
sail(): |
41+
{
42+
let offset : xlenbits = zero_extend(imm);
43+
/* Get the address, X(rs1c) + offset.
44+
Some extensions perform additional checks on address validity. */
45+
match ext_data_get_addr(rs1c, offset, Read(Data), width) {
46+
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
47+
Ext_DataAddr_OK(vaddr) =>
48+
if check_misaligned(vaddr, width)
49+
then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL }
50+
else match translateAddr(vaddr, Read(Data)) {
51+
TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
52+
TR_Address(paddr, _) =>
53+
match (width) {
54+
BYTE =>
55+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
56+
HALF =>
57+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
58+
WORD =>
59+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
60+
DOUBLE if sizeof(xlen) >= 64 =>
61+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
62+
_ => report_invalid_width(__FILE__, __LINE__, width, "load")
63+
}
64+
}
65+
}
66+
}

arch/inst/Zcb/c.lhu.yaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.lhu
6+
long_name: Load unsigned halfword, 16-bit encoding
7+
description: |
8+
Loads a 16-bit value from memory into register rd.
9+
It computes an effective address by adding the zero-extended offset, to the base address in register rs1.
10+
It expands to `lhu` `rd, offset(rs1)`.
11+
definedBy:
12+
anyOf:
13+
- Zcb
14+
- Zce
15+
assembly: xd, imm(xs1)
16+
encoding:
17+
match: 100001---0----00
18+
variables:
19+
- name: imm
20+
location: 5
21+
left_shift: 1
22+
- name: rd
23+
location: 4-2
24+
- name: rs1
25+
location: 9-7
26+
access:
27+
s: always
28+
u: always
29+
vs: always
30+
vu: always
31+
operation(): |
32+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
33+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
34+
}
35+
36+
XReg virtual_address = X[rs1+8] + imm;
37+
38+
X[rd+8] = zext(read_memory<16>(virtual_address, $encoding), 16);
39+
40+
sail(): |
41+
{
42+
let offset : xlenbits = zero_extend(imm);
43+
/* Get the address, X(rs1c) + offset.
44+
Some extensions perform additional checks on address validity. */
45+
match ext_data_get_addr(rs1c, offset, Read(Data), width) {
46+
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
47+
Ext_DataAddr_OK(vaddr) =>
48+
if check_misaligned(vaddr, width)
49+
then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL }
50+
else match translateAddr(vaddr, Read(Data)) {
51+
TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
52+
TR_Address(paddr, _) =>
53+
match (width) {
54+
BYTE =>
55+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned),
56+
HALF =>
57+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned),
58+
WORD =>
59+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned),
60+
DOUBLE if sizeof(xlen) >= 64 =>
61+
process_load(rdc, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned),
62+
_ => report_invalid_width(__FILE__, __LINE__, width, "load")
63+
}
64+
}
65+
}
66+
}

arch/inst/Zcb/c.mul.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.mul
6+
long_name: Multiply, 16-bit encoding
7+
description: |
8+
This instruction multiplies XLEN bits of the source operands from rsd' and rs2' and writes the lowest XLEN bits of the result to rsd'.
9+
10+
definedBy:
11+
allOf:
12+
- Zcb
13+
- Zmmul
14+
assembly: xd, xs2
15+
encoding:
16+
match: 100111---10---01
17+
variables:
18+
- name: rd
19+
location: 9-7
20+
- name: rs2
21+
location: 4-2
22+
access:
23+
s: always
24+
u: always
25+
vs: always
26+
vu: always
27+
operation(): |
28+
29+
if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) {
30+
raise (ExceptionCode::IllegalInstruction, mode(), $encoding);
31+
}
32+
33+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
34+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
35+
}
36+
37+
X[rd+8] = X[rd+8] * X[rs2+8];
38+
39+
sail(): |
40+
{
41+
let result_wide = to_bits(2 * sizeof(xlen), signed(X(rsdc)) * signed(X(rs2c)));
42+
X(rsdc) = result_wide[(sizeof(xlen) - 1) .. 0];
43+
RETIRE_SUCCESS
44+
}
45+
46+
47+
48+

arch/inst/Zcb/c.not.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.not
6+
long_name: Bitwise not, 16-bit encoding
7+
description: |
8+
This instruction takes a single source/destination operand.
9+
This instruction takes the one’s complement of rd'/rs1' and writes the result to the same register.
10+
11+
definedBy:
12+
anyOf:
13+
- Zcb
14+
- Zce
15+
assembly: xd
16+
encoding:
17+
match: 100111---1110101
18+
variables:
19+
- name: rd
20+
location: 9-7
21+
access:
22+
s: always
23+
u: always
24+
vs: always
25+
vu: always
26+
operation(): |
27+
28+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
29+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
30+
}
31+
32+
X[rd+8] = ~X[rd+8];
33+
34+
sail(): |
35+
{
36+
X(rsdc) = X(rsdc) XOR -1;
37+
RETIRE_SUCCESS
38+
}
39+
40+
41+
42+

arch/inst/Zcb/c.sb.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: c.sb
6+
long_name: Store unsigned byte, 16-bit encoding
7+
description: |
8+
Stores a 8-bit value from register rs2 into memory.
9+
It computes an effective address by adding the zero-extended offset, to the base address in register rs1.
10+
It expands to `sb` `rs2, offset(rs1)`.
11+
definedBy:
12+
anyOf:
13+
- Zcb
14+
- Zce
15+
assembly: xs2, imm(xs1)
16+
encoding:
17+
match: 100010--------00
18+
variables:
19+
- name: imm
20+
location: 5|6
21+
- name: rs2
22+
location: 4-2
23+
- name: rs1
24+
location: 9-7
25+
access:
26+
s: always
27+
u: always
28+
vs: always
29+
vu: always
30+
operation(): |
31+
if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) {
32+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
33+
}
34+
35+
XReg virtual_address = X[rs1+8] + imm;
36+
37+
write_memory<8>(virtual_address, X[rs2+8][7:0], $encoding);

0 commit comments

Comments
 (0)