blob: 7567ca776f81f3c30b943eca6c5898d8c027bfff [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# Definitions for the big number group of instructions. See insns.yml
# for the detailed format.
- mnemonic: bn.add
synopsis: Add
operands: &bn-add-operands
- name: wrd
doc: Name of the destination WDR
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- &bn-shift-type-operand
name: shift_type
abbrev: st
type: enum(<<, >>)
doc: |
The direction of an optional shift applied to `<wrs2>`.
- &bn-shift-bits-operand
name: shift_bits
abbrev: sb
type: uimm5<<3
doc: |
Number of bits by which to shift `<wrs2>`. Defaults to 0.
- &bn-flag-group-operand
name: flag_group
abbrev: fg
type: uimm1
doc: Flag group to use. Defaults to 0.
syntax: &bn-add-syntax |
<wrd>, <wrs1>, <wrs2>[ <shift_type> <shift_bits>][, FG<flag_group>]
doc: |
Adds two WDR values, writes the result to the destination WDR and updates
flags. The content of the second source WDR can be shifted by an unsigned
immediate before it is consumed by the operation.
errs: []
iflow:
- to: [wrd, flags-all]
from: [wrs1, wrs2]
encoding:
scheme: bnaf
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b000
wrd: wrd
- mnemonic: bn.addc
synopsis: Add with Carry
operands: *bn-add-operands
syntax: *bn-add-syntax
doc: |
Adds two WDR values and the Carry flag value, writes the result to the
destination WDR, and updates the flags. The content of the second source
WDR can be shifted by an unsigned immediate before it is consumed by the
operation.
errs: []
iflow:
- to: [wrd, flags-all]
from: [wrs1, wrs2, flags-c]
encoding:
scheme: bnaf
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b010
wrd: wrd
- mnemonic: bn.addi
synopsis: Add Immediate
operands:
- name: wrd
doc: Name of the destination WDR
- name: wrs
doc: Name of the source WDR
- name: imm
type: uimm
doc: Immediate value
- *bn-flag-group-operand
syntax: |
<wrd>, <wrs>, <imm>[, FG<flag_group>]
doc: |
Adds a zero-extended unsigned immediate to the value of a WDR, writes the
result to the destination WDR, and updates the flags.
errs: []
iflow:
- to: [wrd, flags-all]
from: [wrs]
encoding:
scheme: bnai
mapping:
fg: flag_group
sub: b0
imm: imm
wrs: wrs
funct3: b100
wrd: wrd
- mnemonic: bn.addm
synopsis: Pseudo-Modulo Add
operands: [wrd, wrs1, wrs2]
doc: |
Add two WDR values, modulo the MOD WSR.
The values in `<wrs1>` and `<wrs2>` are summed to get an intermediate result (of width `WLEN + 1`).
If this result is greater than MOD then MOD is subtracted from it.
The result is then truncated to 256 bits and stored in `<wrd>`.
This operation correctly implements addition modulo MOD, providing that the intermediate result is less than `2 * MOD`.
The intermediate result is small enough if both inputs are less than `MOD`.
Flags are not used or saved.
errs: []
iflow:
- to: [wrd]
from: [wrs1, wrs2, mod]
encoding:
scheme: bnam
mapping:
sub: b0
wrs2: wrs2
wrs1: wrs1
funct3: b101
wrd: wrd
- mnemonic: bn.mulqacc
synopsis: Quarter-word Multiply and Accumulate
operands:
- &mulqacc-zero-acc
name: zero_acc
abbrev: za
type: option(.Z)
doc: Zero the accumulator before accumulating the multiply result.
- &mulqacc-wrs1
name: wrs1
doc: First source WDR
- &mulqacc-wrs1-qwsel
name: wrs1_qwsel
abbrev: q1
type: uimm2
doc: |
Quarter-word select for `<wrs1>`.
Valid values:
- `0`: Select `wrs1[WLEN/4-1:0]` (least significant quarter-word)
- `1`: Select `wrs1[WLEN/2:WLEN/4]`
- `2`: Select `wrs1[WLEN/4*3-1:WLEN/2]`
- `3`: Select `wrs1[WLEN-1:WLEN/4*3]` (most significant quarter-word)
- &mulqacc-wrs2
name: wrs2
doc: Second source WDR
- &mulqacc-wrs2-qwsel
name: wrs2_qwsel
abbrev: q2
type: uimm2
doc: |
Quarter-word select for `<wrs2>`.
Valid values:
- `0`: Select `wrs1[WLEN/4-1:0]` (least significant quarter-word)
- `1`: Select `wrs1[WLEN/2:WLEN/4]`
- `2`: Select `wrs1[WLEN/4*3-1:WLEN/2]`
- `3`: Select `wrs1[WLEN-1:WLEN/4*3]` (most significant quarter-word)
- &mulqacc-acc-shift-imm
name: acc_shift_imm
abbrev: shift
type: uimm2<<6
doc: |
The number of bits to shift the `WLEN/2`-bit multiply result before accumulating.
syntax: |
[<zero_acc>] <wrs1>.<wrs1_qwsel>, <wrs2>.<wrs2_qwsel>, <acc_shift_imm>
glued-ops: true
doc: |
Multiplies two `WLEN/4` WDR values, shifts the product by `acc_shift_imm` bits, and adds the result to the accumulator.
For versions of the instruction with writeback, see `BN.MULQACC.WO` and `BN.MULQACC.SO`.
errs: []
iflow:
- to: [acc]
from: [wrs1, wrs2]
- test:
- zero_acc == 0
to: [acc]
from: [acc]
encoding:
scheme: bnaq
mapping:
fg: bx
so: b0
wb0: b0
qs2: wrs2_qwsel
qs1: wrs1_qwsel
wrs2: wrs2
wrs1: wrs1
shift: acc_shift_imm
z: zero_acc
wrd: bxxxxx
- mnemonic: bn.mulqacc.wo
synopsis: Quarter-word Multiply and Accumulate with full-word writeback
operands:
- *mulqacc-zero-acc
- &mulqacc-wrd
name: wrd
doc: Destination WDR.
- *mulqacc-wrs1
- *mulqacc-wrs1-qwsel
- *mulqacc-wrs2
- *mulqacc-wrs2-qwsel
- *mulqacc-acc-shift-imm
- *bn-flag-group-operand
syntax: |
[<zero_acc>] <wrd>, <wrs1>.<wrs1_qwsel>, <wrs2>.<wrs2_qwsel>, <acc_shift_imm>[, FG<flag_group>]
glued-ops: true
doc: |
Multiplies two `WLEN/4` WDR values, shifts the product by `acc_shift_imm` bits, and adds the result to the accumulator.
Writes the resulting accumulator to `wrd`.
errs: []
iflow:
- to: [acc, wrd, flags-m, flags-l, flags-z]
from: [wrs1, wrs2]
- test:
- zero_acc == 0
to: [acc, wrd, flags-m, flags-l, flags-z]
from: [acc]
encoding:
scheme: bnaq
mapping:
fg: flag_group
so: b0
wb0: b1
qs2: wrs2_qwsel
qs1: wrs1_qwsel
wrs2: wrs2
wrs1: wrs1
shift: acc_shift_imm
z: zero_acc
wrd: wrd
- mnemonic: bn.mulqacc.so
synopsis: Quarter-word Multiply and Accumulate with half-word writeback
operands:
- *mulqacc-zero-acc
- name: wrd
doc: Updated WDR.
type: wrb
- name: wrd_hwsel
abbrev: dh
type: enum(L,U)
doc: |
Half-word select for `<wrd>`.
A value of `L` means the less significant half-word; `U` means the more significant half-word.
- *mulqacc-wrs1
- *mulqacc-wrs1-qwsel
- *mulqacc-wrs2
- *mulqacc-wrs2-qwsel
- *mulqacc-acc-shift-imm
- *bn-flag-group-operand
syntax: |
[<zero_acc>] <wrd>.<wrd_hwsel>,
<wrs1>.<wrs1_qwsel>, <wrs2>.<wrs2_qwsel>, <acc_shift_imm>[, FG<flag_group>]
glued-ops: true
doc: |
Multiplies two `WLEN/4` WDR values, shifts the product by `acc_shift_imm` bits and adds the result to the accumulator.
Next, shifts the resulting accumulator right by half a word (128 bits).
The bits that are shifted out are written to a half-word of `wrd`, selected with `wrd_hwsel`.
This instruction never changes the `C` flag.
If `wrd_hwsel` is zero (so the instruction is updating the lower half-word of `wrd`), it updates the `L` and `Z` flags and leaves `M` unchanged.
The `L` flag is set iff the bottom bit of the shifted-out result is zero.
The `Z` flag is set iff the shifted-out result is zero.
If `wrd_hwsel` is one (so the instruction is updating the upper half-word of `wrd`), it updates the `M` and `Z` flags and leaves `L` unchanged.
The `M` flag is set iff the top bit of the shifted-out result is zero.
The `Z` flag is left unchanged if the shifted-out result is zero and cleared if not.
errs: []
iflow:
- to: [acc, wrd]
from: [wrs1, wrs2]
- test:
- zero_acc == 0
- wrd_hwsel == 0
to: [acc, wrd, flags-l, flags-z]
from: [acc, wrs1, wrs2]
- test:
- zero_acc == 0
- wrd_hwsel == 1
to: [acc, wrd, flags-m, flags-z]
from: [acc, wrs1, wrs2]
- test:
- zero_acc == 1
- wrd_hwsel == 0
to: [flags-l, flags-z]
from: [wrs1, wrs2]
- test:
- zero_acc == 1
- wrd_hwsel == 1
to: [flags-m, flags-z]
from: [wrs1, wrs2]
- test:
- wrd_hwsel == 1
to: [flags-z]
from: [flags-z]
encoding:
scheme: bnaq
mapping:
fg: flag_group
so: b1
wb0: wrd_hwsel
qs2: wrs2_qwsel
qs1: wrs1_qwsel
wrs2: wrs2
wrs1: wrs1
shift: acc_shift_imm
z: zero_acc
wrd: wrd
- mnemonic: bn.sub
synopsis: Subtraction
operands: &bn-sub-operands
- name: wrd
doc: Name of the destination WDR
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- *bn-shift-type-operand
- *bn-shift-bits-operand
- *bn-flag-group-operand
syntax: *bn-add-syntax
doc: |
Subtracts the second WDR value from the first one, writes the result to the destination WDR and updates flags.
The content of the second source WDR can be shifted by an unsigned immediate before it is consumed by the operation.
errs: []
iflow:
- to: [wrd, flags-all]
from: [wrs1, wrs2]
encoding:
scheme: bnaf
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b001
wrd: wrd
- mnemonic: bn.subb
synopsis: Subtract with borrow
operands: *bn-sub-operands
syntax: *bn-add-syntax
doc: |
Subtracts the second WDR value and the Carry from the first one, writes the result to the destination WDR, and updates the flags.
The content of the second source WDR can be shifted by an unsigned immediate before it is consumed by the operation.
iflow:
- to: [wrd, flags-all]
from: [wrs1, wrs2, flags-c]
encoding:
scheme: bnaf
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b011
wrd: wrd
- mnemonic: bn.subi
synopsis: Subtract Immediate
operands:
- name: wrd
doc: Name of the destination WDR
- name: wrs
doc: Name of the source WDR
- name: imm
type: uimm
doc: Immediate value
- *bn-flag-group-operand
syntax: <wrd>, <wrs>, <imm>[, FG<flag_group>]
doc: |
Subtracts a zero-extended unsigned immediate from the value of a WDR,
writes the result to the destination WDR, and updates the flags.
errs: []
iflow:
- to: [wrd, flags-all]
from: [wrs]
encoding:
scheme: bnai
mapping:
fg: flag_group
sub: b1
imm: imm
wrs: wrs
funct3: b100
wrd: wrd
- mnemonic: bn.subm
synopsis: Pseudo-modulo subtraction
operands: [wrd, wrs1, wrs2]
doc: |
Subtract `<wrs2>` from `<wrs1>`, modulo the `MOD` WSR.
The intermediate result is treated as a signed number (of width `WLEN + 1`).
If it is negative, `MOD` is added to it.
The 2's-complement result is then truncated to 256 bits and stored in `<wrd>`.
This operation correctly implements subtraction modulo `MOD`, providing that the intermediate result at least `-MOD` and at most `MOD - 1`.
This is guaranteed if both inputs are less than `MOD`.
Flags are not used or saved.
errs: []
iflow:
- to: [wrd]
from: [wrs1, wrs2, mod]
encoding:
scheme: bnam
mapping:
sub: b1
wrs2: wrs2
wrs1: wrs1
funct3: b101
wrd: wrd
- mnemonic: bn.and
synopsis: Bitwise AND
operands: &bn-and-operands
- name: wrd
doc: Name of the destination WDR
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- *bn-shift-type-operand
- *bn-shift-bits-operand
- *bn-flag-group-operand
syntax: &bn-and-syntax |
<wrd>, <wrs1>, <wrs2>[ <shift_type> <shift_bits>][, FG<flag_group>]
doc: |
Performs a bitwise and operation.
Takes the values stored in registers referenced by `wrs1` and `wrs2` and stores the result in the register referenced by `wrd`.
The content of the second source register can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
errs: []
iflow: &bn-and-iflow
- to: [wrd, flags-m, flags-l, flags-z]
from: [wrs1, wrs2]
encoding:
scheme: bna
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b010
wrd: wrd
- mnemonic: bn.or
synopsis: Bitwise OR
operands: *bn-and-operands
syntax: *bn-and-syntax
doc: |
Performs a bitwise or operation.
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
errs: []
iflow: *bn-and-iflow
encoding:
scheme: bna
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b100
wrd: wrd
- mnemonic: bn.not
synopsis: Bitwise NOT
operands:
- name: wrd
doc: Name of the destination WDR
- name: wrs
doc: Name of the source WDR
- *bn-shift-type-operand
- *bn-shift-bits-operand
- *bn-flag-group-operand
syntax: |
<wrd>, <wrs>[ <shift_type> <shift_bits>][, FG<flag_group>]
doc: |
Negates the value in `wrs` and stores the result in the register referenced by `wrd`.
The source value can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
errs: []
iflow:
- to: [wrd, flags-m, flags-l, flags-z]
from: [wrs]
encoding:
scheme: bnan
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs1: wrs
funct3: b101
wrd: wrd
- mnemonic: bn.xor
synopsis: Bitwise XOR
operands: *bn-and-operands
syntax: *bn-and-syntax
doc: |
Performs a bitwise xor operation.
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
errs: []
iflow: *bn-and-iflow
encoding:
scheme: bna
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b110
wrd: wrd
- mnemonic: bn.rshi
synopsis: Concatenate and right shift immediate
operands:
- name: wrd
doc: Name of the destination WDR
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- name: imm
type: uimm
doc: |
Number of bits to shift the second source register by. Valid range: 0..(WLEN-1).
syntax: |
<wrd>, <wrs1>, <wrs2> >> <imm>
doc: |
Concatenates the content of WDRs referenced by `wrs1` and `wrs2` (`wrs1` forms the upper part), shifts it right by an immediate value and truncates to WLEN bit.
The result is stored in the WDR referenced by `wrd`.
errs: []
encoding:
scheme: bnr
mapping:
imm: imm
wrs2: wrs2
wrs1: wrs1
funct2: b11
wrd: wrd
- mnemonic: bn.sel
synopsis: Flag Select
operands:
- name: wrd
doc: Name of the destination WDR
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- *bn-flag-group-operand
- name: flag
type: enum(C, M, L, Z)
doc: |
Flag to check. Valid values:
- C: Carry flag
- M: MSB flag
- L: LSB flag
- Z: Zero flag
syntax: |
<wrd>, <wrs1>, <wrs2>, [FG<flag_group>.]<flag>
doc: |
Returns in the destination WDR the value of the first source WDR if the flag in the chosen flag group is set, otherwise returns the value of the second source WDR.
errs: []
iflow:
- to: [wrd]
from: [wrs1, wrs2]
- test:
- flag == 0
to: [wrd]
from: [flags-c]
- test:
- flag == 1
to: [wrd]
from: [flags-m]
- test:
- flag == 2
to: [wrd]
from: [flags-l]
- test:
- flag == 3
to: [wrd]
from: [flags-z]
encoding:
scheme: bns
mapping:
fg: flag_group
flag: flag
wrs2: wrs2
wrs1: wrs1
wrd: wrd
- mnemonic: bn.cmp
synopsis: Compare
operands: &bn-cmp-operands
- name: wrs1
doc: Name of the first source WDR
- name: wrs2
doc: Name of the second source WDR
- *bn-shift-type-operand
- *bn-shift-bits-operand
- *bn-flag-group-operand
syntax: &bn-cmp-syntax |
<wrs1>, <wrs2>[ <shift_type> <shift_bits>][, FG<flag_group>]
doc: |
Subtracts the second WDR value from the first one and updates flags.
This instruction is identical to BN.SUB, except that no result register is written.
errs: []
iflow:
- to: [flags-all]
from: [wrs1, wrs2]
encoding:
scheme: bnc
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b001
- mnemonic: bn.cmpb
synopsis: Compare with Borrow
operands: *bn-cmp-operands
syntax: *bn-cmp-syntax
doc: |
Subtracts the second WDR value from the first one and updates flags.
This instruction is identical to BN.SUBB, except that no result register is written.
errs: []
iflow:
- to: [flags-all]
from: [wrs1, wrs2, flags-c]
encoding:
scheme: bnc
mapping:
fg: flag_group
shift_type: shift_type
shift_bits: shift_bits
wrs2: wrs2
wrs1: wrs1
funct3: b011
- mnemonic: bn.lid
synopsis: Load Word (indirect source, indirect destination)
operands:
- name: grd
# The grd register is read to pick the WDR that should be written, so
# it's sort of logically a destination (hence the name) but should be
# treated as a source by tools like the random instruction generator.
type: grs
doc: Name of the GPR referencing the destination WDR
- name: grs1
doc: |
Name of the GPR containing the memory byte address.
The value contained in the referenced GPR must be WLEN-aligned.
- name: offset
abbrev: "off"
doc: |
Offset value.
Must be WLEN-aligned.
type: simm<<5
- name: grs1_inc
abbrev: inc1
type: option(++)
doc: |
Increment the value in `<grs1>` by WLEN/8 (one word).
Cannot be specified together with `grd_inc`.
- name: grd_inc
abbrev: incd
type: option(++)
doc: |
Increment the value in `<grd>` by one.
Cannot be specified together with `grs1_inc`.
syntax: |
<grd>[<grd_inc>], <offset>(<grs1>[<grs1_inc>])
doc: |
Load a WLEN-bit little-endian value from data memory.
The load address is `offset` plus the value in the GPR `grs1`.
The loaded value is stored into the WDR given by the bottom 5 bits of the GPR `grd`.
After the operation, either the value in the GPR `grs1`, or the value in `grd` can be optionally incremented.
Specifying both `grd_inc` and `grs1_inc` results in an error (with error code `ErrCodeIllegalInsn`).
- If `grd_inc` is set, `grd` is updated to be `*grd + 1`.
- If `grs1_inc` is set, the value in `grs1` is incremented by value WLEN/8 (one word).
The memory address must be aligned to WLEN bits.
Any address that is unaligned or is above the top of memory results in an error (setting bit `bad_data_addr` in `ERR_BITS`).
Any `*grd` value greater than 31 before executing the instruction results in an error (setting bit `illegal_insn` in `ERR_BITS`) and no load or optional increment occurring.
This instruction takes 2 cycles.
lsu:
type: mem-load
target: [offset, grs1]
bytes: 32
errs:
- A `CALL_STACK` error from using `x1` as `grs1` or `grd` when the call stack is empty.
- An `ILLEGAL_INSN` error if both `grd_inc` and `grs1_inc` are set.
- An `ILLEGAL_INSN` error if the value in GPR `grd` is greater than 31.
- &data-addr A `BAD_DATA_ADDR` error if the computed address is not a valid DMEM address aligned to WLEN bits.
iflow:
- to: [wref-grd]
from: [dmem]
- test:
- grd_inc == 1
to: [grd]
from: [grd]
- test:
- grs1_inc == 1
to: [grs1]
from: [grs1]
encoding:
scheme: bnxid
mapping:
imm: offset
rs2: grd
rs1: grs1
spp: grs1_inc
dpp: grd_inc
funct3: b100
- mnemonic: bn.sid
synopsis: Store Word (indirect source, indirect destination)
operands:
- name: grs1
doc: |
Name of the GPR containing the memory byte address.
The value contained in the referenced GPR must be WLEN-aligned.
- name: grs2
doc: Name of the GPR referencing the source WDR.
- name: offset
abbrev: "off"
doc: |
Offset value.
Must be WLEN-aligned.
type: simm<<5
- name: grs1_inc
type: option(++)
abbrev: inc1
doc: |
Increment the value in `<grs1>` by WLEN/8 (one word).
Cannot be specified together with `grs2_inc`.
- name: grs2_inc
type: option(++)
abbrev: inc2
doc: |
Increment the value in `<grs2>` by one.
Cannot be specified together with `grs1_inc`.
syntax: |
<grs2>[<grs2_inc>], <offset>(<grs1>[<grs1_inc>])
doc: |
Store a WDR to memory as a WLEN-bit little-endian value.
The store address is `offset` plus the value in the GPR `grs1`.
The value to store is taken from the WDR given by the bottom 5 bits of the GPR `grs2`.
After the operation, either the value in the GPR `grs1`, or the value in `grs2` can be optionally incremented.
Specifying both `grs1_inc` and `grs2_inc` results in an error (with error code `ErrCodeIllegalInsn`).
- If `grs1_inc` is set, the value in `grs1` is incremented by the value WLEN/8 (one word).
- If `grs2_inc` is set, the value in `grs2` is updated to be `*grs2 + 1`.
The memory address must be aligned to WLEN bits.
Any address that is unaligned or is above the top of memory results in an error (setting bit `bad_data_addr` in `ERR_BITS`).
Any `*grs2` value greater than 31 before executing the instruction results in an error (setting bit `illegal_insn` in `ERR_BITS`) and no store or optional increment occurring.
errs:
- A `CALL_STACK` error from using `x1` as `grs1` or `grs2` when the call stack is empty.
- An `ILLEGAL_INSN` error if both `grs1_inc` and `grs2_inc` are set.
- An `ILLEGAL_INSN` error if the value in GPR `grs2` is greater than 31.
- *data-addr
lsu:
type: mem-store
target: [offset, grs1]
bytes: 32
iflow:
- to: [dmem]
from: [wref-grs2]
- test:
- grs1_inc == 1
to: [grs1]
from: [grs1]
- test:
- grs2_inc == 1
to: [grs2]
from: [grs2]
encoding:
scheme: bnxid
mapping:
imm: offset
rs2: grs2
rs1: grs1
spp: grs1_inc
dpp: grs2_inc
funct3: b101
- mnemonic: bn.mov
synopsis: Copy content between WDRs (direct addressing)
operands: [wrd, wrs]
encoding:
scheme: bnmov
mapping:
src: wrs
dst: wrd
errs: []
- mnemonic: bn.movr
synopsis: Copy content between WDRs (register-indirect addressing)
operands:
- name: grd
doc: Name of the GPR containing the destination WDR.
# The grd register is read to pick the WDR that should be written, so
# it's sort of logically a destination (hence the name) but should be
# treated as a source by tools like the random instruction generator.
type: grs
- name: grs
doc: Name of the GPR referencing the source WDR.
- name: grd_inc
type: option(++)
doc: |
Increment the value in `<grd>` by one.
Cannot be specified together with `grs_inc`.
- name: grs_inc
type: option(++)
doc: |
Increment the value in `<grs>` by one.
Cannot be specified together with `grd_inc`.
syntax: |
<grd>[<grd_inc>], <grs>[<grs_inc>]
doc: |
Copies WDR contents between registers with indirect addressing.
After the operation, either the value in the GPR `grd`, or the value in `grs` can be optionally incremented.
Specifying both `grd_inc` and `grs_inc` results in an error (with error code `ErrCodeIllegalInsn`).
- If `grd_inc` is set, `grd` is updated to be `*grd + 1`.
- If `grs_inc` is set, `grs` is updated to be `*grs + 1`.
Any `*grd` or `*grs` value greater than 31 results in an error (setting bit `illegal_insn` in `ERR_BITS`)
errs:
- A `CALL_STACK` error from using `x1` as `grs` or `grd` when the call stack is empty.
- An `ILLEGAL_INSN` error if either the value in GPR `grd` or the value in GPR `grs` is greater than 31.
- An `ILLEGAL_INSN` error if both `grs_inc` and `grd_inc` are set.
iflow:
- to: [wref-grd]
from: [wref-grs]
- test:
- grd_inc == 1
to: [grd]
from: [grd]
- test:
- grs_inc == 1
to: [grs]
from: [grs]
encoding:
scheme: bnmovr
mapping:
dst: grd
src: grs
spp: grs_inc
dpp: grd_inc
- mnemonic: bn.wsrr
synopsis: Read WSR to register
operands:
- name: wrd
doc: Destination WDR
- name: wsr
doc: The WSR to read
doc: |
Reads a WSR to a WDR.
If `wsr` isn't the index of a valid WSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
errs:
- &bad-wsr An `ILLEGAL_INSN` error if `wsr` doesn't name a valid WSR.
iflow:
- to: [wrd]
from: []
- test:
- wsr == 0x0
to: [wrd]
from: [mod]
- test:
- wsr == 0x3
to: [wrd]
from: [acc]
encoding:
scheme: wcsr
mapping:
write: b0
wcsr: wsr
wrs: bxxxxx
wrd: wrd
lsu:
type: wsr-load
target: [wsr]
- mnemonic: bn.wsrw
synopsis: Write WSR from register
operands: [wsr, wrs]
operands:
- name: wsr
doc: The WSR to read
- name: wrs
doc: Source WDR
doc: |
Writes a WDR to a WSR.
If `wsr` isn't the index of a valid WSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
errs:
- *bad-wsr
iflow:
- to: []
from: []
- test:
- wsr == 0x0
to: [mod]
from: [wrs]
- test:
- wsr == 0x3
to: [acc]
from: [wrs]
encoding:
scheme: wcsr
mapping:
write: b1
wcsr: wsr
wrs: wrs
wrd: bxxxxx
lsu:
type: wsr-store
target: [wsr]