Skip to content

Commit 18f59ba

Browse files
authored
Merge pull request #427 from riscv-software-src/Zcmp
Add Zcmp spec instructions (encodings and descriptions).
2 parents b351e7e + 49c99f2 commit 18f59ba

File tree

7 files changed

+450
-0
lines changed

7 files changed

+450
-0
lines changed

arch/inst/Zcmp/cm.mva01s.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: cm.mva01s
6+
long_name: Move two s0-s7 registers into a0-a1
7+
description: |
8+
This instruction moves r1s' into a0 and r2s' into a1. The execution is atomic, so it is not possible to observe state where only one of a0 or a1 have been updated.
9+
The encoding uses sreg number specifiers instead of xreg number specifiers to save encoding space. The mapping between them is specified in the pseudo-code below.
10+
definedBy:
11+
anyOf:
12+
- Zcmp
13+
assembly: r1s, r2s
14+
encoding:
15+
match: 101011---11---10
16+
variables:
17+
- name: r1s
18+
location: 9-7
19+
- name: r2s
20+
location: 4-2
21+
access:
22+
s: always
23+
u: always
24+
vs: always
25+
vu: always
26+
operation(): |
27+
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
28+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
29+
}
30+
XReg xreg1 = (r1s[2:1]>0) ? {1,0,r1s[2:0]} : {0,1,r1s[2:0]};
31+
XReg xreg2 = (r2s[2:1]>0) ? {1,0,r2s[2:0]} : {0,1,r2s[2:0]};
32+
X[10] = X[xreg1];
33+
X[11] = X[xreg2];

arch/inst/Zcmp/cm.mvsa01.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: cm.mvsa01
6+
long_name: Move a0-a1 into two registers of s0-s7
7+
description: |
8+
This instruction moves a0 into r1s' and a1 into r2s'. r1s' and r2s' must be different.
9+
The execution is atomic, so it is not possible to observe state where only one of r1s' or r2s' has been updated.
10+
The encoding uses sreg number specifiers instead of xreg number specifiers to save encoding space.
11+
The mapping between them is specified in the pseudo-code below.
12+
definedBy:
13+
anyOf:
14+
- Zcmp
15+
assembly: r1s, r2s
16+
encoding:
17+
match: 101011---01---10
18+
variables:
19+
- name: r1s
20+
location: 9-7
21+
- name: r2s
22+
location: 4-2
23+
access:
24+
s: always
25+
u: always
26+
vs: always
27+
vu: always
28+
operation(): |
29+
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
30+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
31+
}
32+
XReg xreg1 = (r1s[2:1]>0) ? {1,0,r1s[2:0]} : {0,1,r1s[2:0]};
33+
XReg xreg2 = (r2s[2:1]>0) ? {1,0,r2s[2:0]} : {0,1,r2s[2:0]};
34+
X[xreg1] = X[10];
35+
X[xreg2] = X[11];

arch/inst/Zcmp/cm.pop.yaml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: cm.pop
6+
long_name: Destroy function call stack frame
7+
description: |
8+
Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame.
9+
This instruction pops (loads) the registers in `reg_list` from stack memory, and then adjusts the stack pointer by `stack_adj`.
10+
11+
Restrictions on stack_adj:
12+
13+
* it must be enough to store all of the listed registers
14+
* it must be a multiple of 16 (bytes):
15+
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
16+
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
17+
definedBy:
18+
anyOf:
19+
- Zcmp
20+
assembly: reg_list, stack_adj
21+
encoding:
22+
match: 10111010------10
23+
variables:
24+
- name: rlist
25+
location: 7-4
26+
not: [0, 1, 2, 3]
27+
- name: spimm
28+
location: 3-2
29+
left_shift: 4
30+
access:
31+
s: always
32+
u: always
33+
vs: always
34+
vu: always
35+
operation(): |
36+
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
37+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
38+
}
39+
40+
XReg size = xlen();
41+
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
42+
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
43+
XReg virtual_address_sp = X[2];
44+
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
45+
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);
46+
47+
X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
48+
if (nreg > 1) {
49+
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
50+
}
51+
if (nreg > 2) {
52+
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
53+
}
54+
if (nreg > 3) {
55+
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
56+
}
57+
if (nreg > 4) {
58+
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
59+
}
60+
if (nreg > 5) {
61+
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
62+
}
63+
if (nreg > 6) {
64+
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
65+
}
66+
if (nreg > 7) {
67+
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
68+
}
69+
if (nreg > 8) {
70+
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
71+
}
72+
if (nreg > 9) {
73+
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
74+
}
75+
if (nreg > 10) {
76+
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
77+
}
78+
if (nreg > 11) {
79+
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
80+
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
81+
}
82+
83+
X[2] = virtual_address_new_sp;

arch/inst/Zcmp/cm.popret.yaml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: cm.popret
6+
long_name: Destroy function call stack frame and return to `ra`.
7+
description: |
8+
Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame, return to `ra`.
9+
This instruction pops (loads) the registers in `reg_list` from stack memory, and then adjusts the stack pointer by `stack_adj` and then return to `ra`.
10+
11+
Restrictions on stack_adj:
12+
13+
* it must be enough to store all of the listed registers
14+
* it must be a multiple of 16 (bytes):
15+
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
16+
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
17+
definedBy:
18+
anyOf:
19+
- Zcmp
20+
assembly: reg_list, stack_adj
21+
encoding:
22+
match: 10111110------10
23+
variables:
24+
- name: rlist
25+
location: 7-4
26+
not: [0, 1, 2, 3]
27+
- name: spimm
28+
location: 3-2
29+
left_shift: 4
30+
access:
31+
s: always
32+
u: always
33+
vs: always
34+
vu: always
35+
operation(): |
36+
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
37+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
38+
}
39+
40+
XReg size = xlen();
41+
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
42+
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
43+
XReg virtual_address_sp = X[2];
44+
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
45+
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);
46+
47+
X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
48+
if (nreg > 1) {
49+
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
50+
}
51+
if (nreg > 2) {
52+
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
53+
}
54+
if (nreg > 3) {
55+
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
56+
}
57+
if (nreg > 4) {
58+
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
59+
}
60+
if (nreg > 5) {
61+
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
62+
}
63+
if (nreg > 6) {
64+
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
65+
}
66+
if (nreg > 7) {
67+
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
68+
}
69+
if (nreg > 8) {
70+
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
71+
}
72+
if (nreg > 9) {
73+
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
74+
}
75+
if (nreg > 10) {
76+
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
77+
}
78+
if (nreg > 11) {
79+
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
80+
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
81+
}
82+
83+
X[2] = virtual_address_new_sp;
84+
jump(X[1]);

arch/inst/Zcmp/cm.popretz.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# yaml-language-server: $schema=../../../schemas/inst_schema.json
2+
3+
$schema: "inst_schema.json#"
4+
kind: instruction
5+
name: cm.popretz
6+
long_name: Destroy function call stack frame, move zero to `a0` and return to `ra`.
7+
description: |
8+
Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame, move zero to `a0`, return to `ra`.
9+
This instruction pops (loads) the registers in `reg_list` from stack memory, and then adjusts the stack pointer by `stack_adj`, move zero to `a0` and then return to `ra`.
10+
11+
Restrictions on stack_adj:
12+
13+
* it must be enough to store all of the listed registers
14+
* it must be a multiple of 16 (bytes):
15+
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
16+
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
17+
definedBy:
18+
anyOf:
19+
- Zcmp
20+
assembly: reg_list, stack_adj
21+
encoding:
22+
match: 10111100------10
23+
variables:
24+
- name: rlist
25+
location: 7-4
26+
not: [0, 1, 2, 3]
27+
- name: spimm
28+
location: 3-2
29+
left_shift: 4
30+
access:
31+
s: always
32+
u: always
33+
vs: always
34+
vu: always
35+
operation(): |
36+
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
37+
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
38+
}
39+
40+
XReg size = xlen();
41+
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
42+
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
43+
XReg virtual_address_sp = X[2];
44+
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
45+
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);
46+
47+
X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
48+
if (nreg > 1) {
49+
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
50+
}
51+
if (nreg > 2) {
52+
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
53+
}
54+
if (nreg > 3) {
55+
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
56+
}
57+
if (nreg > 4) {
58+
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
59+
}
60+
if (nreg > 5) {
61+
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
62+
}
63+
if (nreg > 6) {
64+
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
65+
}
66+
if (nreg > 7) {
67+
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
68+
}
69+
if (nreg > 8) {
70+
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
71+
}
72+
if (nreg > 9) {
73+
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
74+
}
75+
if (nreg > 10) {
76+
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
77+
}
78+
if (nreg > 11) {
79+
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
80+
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
81+
}
82+
83+
X[2] = virtual_address_new_sp;
84+
X[10] = 0;
85+
jump(X[1]);

0 commit comments

Comments
 (0)