open source
clearest concise summary of major opcodes is in tables at the end of http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf
younger than (2010) and claims to have learned from SPARC V8 (1994) and OpenRISC? (2000).
http://riscv.org/download.html#tab_isaspec (base opcode listing in Chapter 8)
I'm not sure what addressing modes are supported, but i'm guessing it's non-uniform, with different opcodes for different modes, and mostly register, except for the 'immediate' opcodes which have an 'immediate' component, and loads and stores which have a base+offset mode, with base address in register rs1. Unconditional jumps have PC-relative addressing.
interesting comparison of RISC-V with Epiphany (the one used in Parallella) http://www.adapteva.com/andreas-blog/analyzing-the-risc-v-instruction-set-architecture/
note: RISC-V instructions that the Epiphany guy thought maybe could have been left out:
AUIPC (but in the comments a RISC-V guy says AUIPC was important for relocatable code), SLT/SLTI/STLU/SLTIU (compare: set-less-than, with unsigned and immediate and unsigned immediate variants), XORI/ORI/ANDI (boolean logic with immediate values), FENCE (mb; sync threads), MULH/MULHSU/MULHU (multiply variants with the 'upper half' variant), FSGNJ/FSGNJN/FSGNJX (Sign Inject: Sign source), FCLASS (Categorization: Classify Type). Then there was a bunch for which he said "Not needed for epiphany", which i dunno if he means 'this is good but since Epiphany had a restricted use case target (DSP) we didn't include it'. These are: FLW/FSW (load/store 'W'; i didn't note this below), FMV.X/FMV.S (move from/to integer), FRSCSR (typo? read status regs? i didn't note this below), FSRM/FSRMI (swap rounding mode; i didn't note this below), FSFLAGS (swap flags; i didn't note this below). Then there are some for which he said and 'Needed?', these are: FNMSUB (Negative Multiply-SUBtract), FMIN/FMAX (min/max), FCMP (i can't find this in the table in http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf , so i didn't note this below).
Epiphany instructions that the Epiphany said RISC-V left out that are good: LDRD (load/store double), LDR and STR with the POSTMOD addressing mode (postincrement).
RISC-V has a choice of 16 or 32 integer registers (32 is more typical, i think?) and also optionally, 32 additional floating point registers. Memory is addressed as 8-bit bytes. The instruction encoding is 32-bit, but the 'Compressed' instruction encoding has 16-bit instructions. Instructions tend to have 32-bit, 64-bit, and 128-bit variants; arithmetic is done in at least 32-bit width ("RISC-V can load and store 8 and 16-bit items, but it lacks 8 and 16-bit arithmetic, including comparison-and-branch instructions." [7] ). Register 0 is constant 0.
RISC; no indirect or memory-memory addr modes, but instead there are LOAD and STORE instructions. No autoincrement addr modes. Some opcodes indicate immediate addr mode, others indicate register direct. Little-endian. Branching is compare-and-branch. Variable-length encoding.
"The RISC-V ISA has been designed to include small, fast, and low-power real-world implementations,[2][3] but without over-architecting for a particular microarchitecture style." [8]
"the RISC-V instruction set is designed for practicality of implementation, with features to increase a computer's speed, while reducing its cost and power use. These include placing most-significant bits at a fixed location to speed sign-extension, and a bit-arrangement designed to reduce the number of multiplexers in a CPU." [9]
"RISC-V intentionally lacks condition codes, and even a carry bit.[3] The designers claim that this can simplify CPU designs by minimizing interactions between instructions.[3] Instead RISC-V builds comparison operations into its conditional-jumps.[3] Use of comparisons may slightly increase its power use in some applications. The lack of a carry bit complicates multiple-precision arithmetic. RISC-V does not detect or flag most arithmetic errors, including overflow, underflow, and divide by zero.[3] RISC-V also lacks the "count leading zero" and bit-field operations normally used to speed software floating-point in a pure-integer processor." [10]
" A load or store can add a twelve-bit signed offset to a register that contains an address. A further 20 bits (yielding a 32-bit address) can be generated at an absolute address.[3]
RISC-V was designed to permit position-independent code. It has a special instruction to generate 20 upper address bits that are relative to the program counter. The lower twelve bits are provided by normal loads, stores and jumps.[3] " [11]
" RISC-V does define a special set of integer multiplication instructions. This includes a recommended sequence of instructions that a compiler can generate and a CPU can interpret to perform a fused multiply-accumulate operation. Multiply-accumulate is a core primitive of numerical linear algebra, and so is incorporated as part of a common benchmark, Coremark.[3][15] " [12]
Tutorials:
From [13] (Draft version 1.9):
MOVs and loads and stores and LOADK:
Jumps and branches:
Other stack-pointer-related:
Arithmetic and boolean logic:
Misc:
Variants are bit-width and integer vs. floating-point (there are (optional) floating-point registers in RISC-V).
C.(F)L(W
D | Q)SP: Load value from stack (stack-pointer + 6-bit offset) into register. (there is no FLQSP though) |
D | Q)SP: Store value from register to stack (stack-pointer + 6-bit offset). (there is no FSQSP though) |
D | Q): Load value from memory (memory address in a register, plus a 5-bit immediate offset) into register (there is no FLQ though) |
D | Q): Store value from register into memory (memory address in a register, plus a 5-bit immediate offset) (there is no FSQ though) |
C.J: Jump to offset given as an immediate constant (PC-relative, signed 11-bit, +-2k range (so +-1k instructions) C.JAL: Like C.J but also writes the current PC (plus 1 instruction) to the link register. C.JR: Jump to PC-relative offset given by register. C.JALR: Like C.JR but also writes the current PC (plus 1 instruction) to the link register.
C.BEQZ: Branch if the value in the given register zero. Offset is signed 8-bit, +-256 (so +-128 instructions). C.BNEQZ: Like C.BEQZ but branch if NOT zero.
C.LI: Load 6-bit immediate into register. C.LUI: Load 6-bit immediate into bits 17-12 of register.
C.ADDI(W): Add 6-bit immediate to register (mutating the register) C.ADDI16SP: Scale 6-bit immediate by 16 then add to stack-pointer (mutating the stack pointer). "used to adjust the stack pointer in procedure prologues and epilogues". C.ADDI4SPN: Scale 8-bit immediate by 4, add to stack pointer, and write the result to register. "used to generate pointers to stack-allocated variables".
C.S(L
R)(L | A)I (logical | arithmetic) (left | right)-shifts a register (mutating it) (6-bit immediate shift amount). These variants have a non-uniform scheme for interpreting the immediate to allow it to be most useful. (there is no SLAI though) |
C.ANDI is bitwise AND of a register and a 6-bit immediate (mutating the register).
C.MV is register-register MOV.
C.(ADD
SUB)(W) adds | subtracts two registers and writes the result over one of the input registers. |
C.AND, C.OR, C.XOR is bitwise AND of two registers, writing the result over one of the input registers.
C.BAD, the all-zero instruction, is illegal (not mnemonic is given, i made up 'BAD')
C.NOP is NOP
C.EBREAK breaks into the debugging environment.
from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf ; see also http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf or https://www.cl.cam.ac.uk/teaching/1617/ECAD+Arch/files/docs/RISCVGreenCardv8-20151013.pdf although they have an older version of the ISA:
from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf or http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :
(note: the Epiphany guy thought the 'upper half' multiply variants could have been left out)
(mul, mulh, mulhsu, mulhu, div, divu, rem, remu)
from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf or http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :
Load and store:
Arithmetic
Mul-Add:
Move (note: the Epiphany guy thought these could have been left out):
Sign Inject (note: the Epiphany guy thought these could have been left out):
Min/Max (note: the Epiphany guy thought these could have been left out):
Compare:
Convert:
Categorization (note: the Epiphany guy thought these could have been left out):
Configuration instructions (read/write the Floating-Point Control and Status Register, fcsr):
Configuration pseudo-op instructions:
(flw fsw fadd fsub fmul fdiv fsqrt fmadd fmsub fnmsub fnmadd fmv.w.x fmv.x.w fsgnj fsgnjn fsgnjx fmin fmax feq flt fle fcvt.s.w fcvt.s.wu fcvt.w.s fcvt.wu.s fclass frcsr fscsr frrm fsrm fsrmi frflags fsflags fsflagsi)
from http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :
-- [14]
" In this second RISC-V article I talk about its interrupt and exception system and about SiFiveās? FE310G, the first commercial silicon implementation of a RISC-V ...
RISC-V ISA defines two major interrupt types: global and local. Basically, global interrupts are designed for multicore environments, while local interrupts are always associated with one specific core. Local interrupts suffer less overhead as there is no need for arbitration (which is the case of global interrupts on multicore systems).
...
Local interrupt system is responsible for processing a limited (and usually small) number of interrupt sources. The CLINT (Coreplex Local Interrupts) module has three basic interrupt sources: software interrupt (SI), timer interrupt (TI) and external interrupt (EI). RISC-V ISA also defines sixteen other optional local interrupt sources (which are not present on E31). One important note: all global interrupts from PLIC (Platform-level Interrupt Controller) are applied to the external interrupt input within CLINT!
RISC-V interrupt system will suspend execution flow and branch to an ISR if a local interrupt source (as long as it is previously enabled) sets its pending interrupt flag. There is also a global interrupt enable bit (MIE/SIE/UIE according to the current mode) available on MSTATUS register. This register also controls interrupt nesting, memory access privileges, etc. For further information regarding take a look at the RISC-V privileged instructions manual.
There are two ways to deal with interrupts on RISC-V: by using a single vector or multiple vectors. On the single vector mode, register MTVEC (CSR number 0x305) points to the ISR base address, that is, MTVEC points to the single/unique entry point for all ISR code. On the multiple vector mode, on the other hand, MTVEC works as a pointer to the vector table base address and the index for that table is taken from the MCAUSE register (CSR number 0x342). " [15]