Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Zcmp spec instructions (encodings and descriptions). #427

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
33 changes: 33 additions & 0 deletions arch/inst/Zcmp/cm.mva01s.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# yaml-language-server: $schema=../../../schemas/inst_schema.json

$schema: "inst_schema.json#"
kind: instruction
name: cm.mva01s
long_name: Move two s0-s7 registers into a0-a1
description: |
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.
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.
definedBy:
anyOf:
- Zcmp
ayosher marked this conversation as resolved.
Show resolved Hide resolved
assembly: r1s, r2s
ayosher marked this conversation as resolved.
Show resolved Hide resolved
encoding:
match: 101011---11---10
variables:
- name: r1s
location: 9-7
- name: r2s
ayosher marked this conversation as resolved.
Show resolved Hide resolved
location: 4-2
access:
s: always
u: always
vs: always
vu: always
operation(): |
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
XReg xreg1 = (r1s[2:1]>0) ? {1,0,r1s[2:0]} : {0,1,r1s[2:0]};
XReg xreg2 = (r2s[2:1]>0) ? {1,0,r2s[2:0]} : {0,1,r2s[2:0]};
X[10] = X[xreg1];
X[11] = X[xreg2];
35 changes: 35 additions & 0 deletions arch/inst/Zcmp/cm.mvsa01.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# yaml-language-server: $schema=../../../schemas/inst_schema.json

$schema: "inst_schema.json#"
kind: instruction
name: cm.mvsa01
long_name: Move a0-a1 into two registers of s0-s7
description: |
This instruction moves a0 into r1s' and a1 into r2s'. r1s' and r2s' must be different.
The execution is atomic, so it is not possible to observe state where only one of r1s' or r2s' has been updated.
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.
definedBy:
anyOf:
- Zcmp
assembly: r1s, r2s
encoding:
match: 101011---01---10
variables:
- name: r1s
location: 9-7
- name: r2s
location: 4-2
access:
s: always
u: always
vs: always
vu: always
operation(): |
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
XReg xreg1 = (r1s[2:1]>0) ? {1,0,r1s[2:0]} : {0,1,r1s[2:0]};
XReg xreg2 = (r2s[2:1]>0) ? {1,0,r2s[2:0]} : {0,1,r2s[2:0]};
X[xreg1] = X[10];
X[xreg2] = X[11];
83 changes: 83 additions & 0 deletions arch/inst/Zcmp/cm.pop.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# yaml-language-server: $schema=../../../schemas/inst_schema.json

$schema: "inst_schema.json#"
kind: instruction
name: cm.pop
long_name: Destroy function call stack frame
description: |
Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame.
This instruction pops (loads) the registers in `reg_list` from stack memory, and then adjusts the stack pointer by `stack_adj`.

Restrictions on stack_adj:

* it must be enough to store all of the listed registers
* it must be a multiple of 16 (bytes):
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
definedBy:
anyOf:
- Zcmp
assembly: reg_list, stack_adj
ayosher marked this conversation as resolved.
Show resolved Hide resolved
encoding:
match: 10111010------10
variables:
- name: rlist
location: 7-4
not: [0, 1, 2, 3]
- name: spimm
location: 3-2
ayosher marked this conversation as resolved.
Show resolved Hide resolved
left_shift: 4
access:
s: always
u: always
vs: always
vu: always
operation(): |
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}

XReg size = xlen();
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
XReg virtual_address_sp = X[2];
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);

X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
if (nreg > 1) {
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
}
if (nreg > 2) {
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
}
if (nreg > 3) {
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
}
if (nreg > 4) {
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
}
if (nreg > 5) {
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
}
if (nreg > 6) {
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
}
if (nreg > 7) {
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
}
if (nreg > 8) {
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
}
if (nreg > 9) {
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
}
if (nreg > 10) {
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
}
if (nreg > 11) {
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
}

X[2] = virtual_address_new_sp;
84 changes: 84 additions & 0 deletions arch/inst/Zcmp/cm.popret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# yaml-language-server: $schema=../../../schemas/inst_schema.json

$schema: "inst_schema.json#"
kind: instruction
name: cm.popret
long_name: Destroy function call stack frame and return to `ra`.
description: |
Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame, return to `ra`.
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`.

Restrictions on stack_adj:

* it must be enough to store all of the listed registers
* it must be a multiple of 16 (bytes):
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
definedBy:
anyOf:
- Zcmp
assembly: reg_list, stack_adj
encoding:
match: 10111110------10
variables:
- name: rlist
location: 7-4
not: [0, 1, 2, 3]
- name: spimm
location: 3-2
left_shift: 4
access:
s: always
u: always
vs: always
vu: always
operation(): |
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}

XReg size = xlen();
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
XReg virtual_address_sp = X[2];
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);

X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
if (nreg > 1) {
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
}
if (nreg > 2) {
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
}
if (nreg > 3) {
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
}
if (nreg > 4) {
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
}
if (nreg > 5) {
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
}
if (nreg > 6) {
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
}
if (nreg > 7) {
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
}
if (nreg > 8) {
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
}
if (nreg > 9) {
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
}
if (nreg > 10) {
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
}
if (nreg > 11) {
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
}

X[2] = virtual_address_new_sp;
jump(X[1]);
85 changes: 85 additions & 0 deletions arch/inst/Zcmp/cm.popretz.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# yaml-language-server: $schema=../../../schemas/inst_schema.json

$schema: "inst_schema.json#"
kind: instruction
name: cm.popretz
long_name: Destroy function call stack frame, move zero to `a0` and return to `ra`.
description: |
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`.
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`.

Restrictions on stack_adj:

* it must be enough to store all of the listed registers
* it must be a multiple of 16 (bytes):
** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112
** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160
definedBy:
anyOf:
- Zcmp
assembly: reg_list, stack_adj
encoding:
match: 10111100------10
variables:
- name: rlist
location: 7-4
not: [0, 1, 2, 3]
- name: spimm
location: 3-2
left_shift: 4
access:
s: always
u: always
vs: always
vu: always
operation(): |
if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}

XReg size = xlen();
XReg nreg = (rlist == 15) ? 13 : (rlist - 3);
XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF;
XReg virtual_address_sp = X[2];
XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm;
XReg virtual_address_base = virtual_address_new_sp - (nreg * size);

X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding);
if (nreg > 1) {
X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding);
}
if (nreg > 2) {
X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding);
}
if (nreg > 3) {
X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding);
}
if (nreg > 4) {
X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding);
}
if (nreg > 5) {
X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding);
}
if (nreg > 6) {
X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding);
}
if (nreg > 7) {
X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding);
}
if (nreg > 8) {
X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding);
}
if (nreg > 9) {
X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding);
}
if (nreg > 10) {
X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding);
}
if (nreg > 11) {
X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding);
X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding);
}

X[2] = virtual_address_new_sp;
X[10] = 0;
jump(X[1]);
Loading
Loading