The "Conditional" operations extension provides a simple solution that provides most of the benefit and all of the flexibility one would desire to support conditional arithmetic and conditional-select/move operations, while remaining true to the RISC-V design philosophy. The instructions follow the format for R-type instructions with 3 operands (i.e., 2 source operands and 1 destination operand). Using these instructions, branchless sequences can be implemented (typically in two-instruction sequences) without the need for instruction fusion, special provisions during the decoding of architectural instructions, or other microarchitectural provisions.
The following instructions comprise the Zicond extension:
RV32 | RV64 | Mnemonic | Instruction |
---|---|---|---|
✓ |
✓ |
czero.eqz rd, rs1, rs2 |
|
✓ |
✓ |
czero.nez rd, rs1, rs2 |
Note
|
Architecture Comment: defining additional comparisons, in addition to equal-to-zero and not-equal-to-zero, does not offer a benefit due to the lack of immediates or an additional register operand that the comparison takes place against. |
Based on these two instructions, synthetic instructions (i.e., short instruction sequences) for the following conditional arithmetic operations are supported:
-
conditional add, if zero
-
conditional add, if non-zero
-
conditional subtract, if zero
-
conditional subtract, if non-zero
-
conditional bitwise-and, if zero
-
conditional bitwise-and, if non-zero
-
conditional bitwise-or, if zero
-
conditional bitwise-or, if non-zero
-
conditional bitwise-xor, if zero
-
conditional bitwise-xor, if non-zero
Additionally, the following conditional select instructions are supported:
-
conditional-select, if zero
-
conditional-select, if non-zero
More complex conditions, such as comparisons against immediates, registers, single-bit tests, comparisons against ranges, etc. can be realized by composing these new instructions with existing instructions.
- Synopsis
-
Moves zero to a register rd, if the condition rs2 is equal to zero, otherwise moves rs1 to rd.
- Mnemonic
-
czero.eqz rd, rs1, rs2
- Encoding
{reg:[ { bits: 7, name: 0x33, attr: ['OP'] }, { bits: 5, name: 'rd' }, { bits: 3, name: 0x5, attr: ['CZERO.EQZ']}, { bits: 5, name: 'rs1', attr: ['value'] }, { bits: 5, name: 'rs2', attr: ['condition'] }, { bits: 7, name: 0x7, attr: ['CZERO'] }, ]}
- Description
-
If rs2 contains the value zero, this instruction writes the value zero to rd. Otherwise, this instruction copies the contents of rs1 to rd.
This instruction carries a syntactic dependency from both rs1 and rs2 to rd. Furthermore, if the Zkt extension is implemented, this instruction’s timing is independent of the data values in rs1 and rs2.
- SAIL code
let condition = X(rs2);
result : xlenbits = if (condition == zeros()) then zeros()
else X(rs1);
X(rd) = result;
- Synopsis
-
Moves zero to a register rd, if the condition rs2 is nonzero, otherwise moves rs1 to rd.
- Mnemonic
-
czero.nez rd, rs1, rs2
- Encoding
{reg:[ { bits: 7, name: 0x33, attr: ['OP'] }, { bits: 5, name: 'rd' }, { bits: 3, name: 0x7, attr: ['CZERO.NEZ']}, { bits: 5, name: 'rs1', attr: ['value'] }, { bits: 5, name: 'rs2', attr: ['condition'] }, { bits: 7, name: 0x7, attr: ['CZERO'] }, ]}
- Description
-
If rs2 contains a nonzero value, this instruction writes the value zero to rd. Otherwise, this instruction copies the contents of rs1 to rd.
This instruction carries a syntactic dependency from both rs1 and rs2 to rd. Furthermore, if the Zkt extension is implemented, this instruction’s timing is independent of the data values in rs1 and rs2.
- SAIL code
let condition = X(rs2);
result : xlenbits = if (condition != zeros()) then zeros()
else X(rs1);
X(rd) = result;
The instructions from this extension can be used to construct sequences that perform conditional-arithmetic, conditional-bitwise-logical, and conditional-select operations.
Operation | Instruction sequence | Length |
---|---|---|
Conditional add, if zero |
czero.nez rd, rs2, rc add rd, rs1, rd |
2 insns |
Conditional add, if non-zero |
czero.eqz rd, rs2, rc add rd, rs1, rd |
|
Conditional subtract, if zero |
czero.nez rd, rs2, rc sub rd, rs1, rd |
|
Conditional subtract, if non-zero |
czero.eqz rd, rs2, rc sub rd, rs1, rd |
|
Conditional bitwise-or, if zero |
czero.nez rd, rs2, rc or rd, rs1, rd |
|
Conditional bitwise-or, if non-zero |
czero.eqz rd, rs2, rc or rd, rs1, rd |
|
Conditional bitwise-xor, if zero |
czero.nez rd, rs2, rc xor rd, rs1, rd |
|
Conditional bitwise-xor, if non-zero |
czero.eqz rd, rs2, rc xor rd, rs1, rd |
|
Conditional bitwise-and, if zero |
and rd, rs1, rs2 czero.eqz rtmp, rs1, rc or rd, rd, rtmp |
3 insns |
Conditional bitwise-and, if non-zero |
and rd, rs1, rs2 czero.nez rtmp, rs1, rc or rd, rd, rtmp |
|
Conditional select, if zero |
czero.nez rd, rs1, rc czero.eqz rtmp, rs2, rc or rd, rd, rtmp |
|
Conditional select, if non-zero |
czero.eqz rd, rs1, rc czero.nez rtmp, rs2, rc or rd, rd, rtmp |