open source

clearest concise summary of major opcodes is in tables at the end of

younger than (2010) and claims to have learned from SPARC V8 (1994) and OpenRISC? (2000). (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)

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 , 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]

Risc-V Compressed (16-bit encoding) opcodes

From [13] (Draft version 1.9):

Summary of Risc-V Compressed (16-bit encoding) opcodes

MOVs and loads and stores and LOADK:

Jumps and branches:

Other stack-pointer-related:

Arithmetic and boolean logic:


Details of Risc-V Compressed (16-bit encoding) opcodes

Variants are bit-width and integer vs. floating-point (there are (optional) floating-point registers in RISC-V).


DQ)SP: Load value from stack (stack-pointer + 6-bit offset) into register. (there is no FLQSP though)
DQ)SP: Store value from register to stack (stack-pointer + 6-bit offset). (there is no FSQSP though)
DQ): Load value from memory (memory address in a register, plus a 5-bit immediate offset) into register (there is no FLQ though)
DQ): 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".


R)(LA)I (logicalarithmetic) (leftright)-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.


SUB)(W) addssubtracts 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.EBREAK breaks into the debugging environment.

Base instructions (32-bit encoding)

from ; see also or although they have an older version of the ISA:

Multiply-divide extension ('M') instructions

from or :

(note: the Epiphany guy thought the 'upper half' multiply variants could have been left out)

(mul, mulh, mulhsu, mulhu, div, divu, rem, remu)

Floating-point extension ('F') instructions

from or :

Load and store:



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):



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)

Atomicity extension opcodes

from :

suggested register usage

-- [14]

RISC-V interrupts

" 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]

RISC-V variants

DarkRiscV subset

I think it contains:

Note that it does not contain the fence*, e*, and csr* instructions (memory fences, privilege levels and configuration registers). I believe that it also omits the SCALL, SBREAK, and the counter (RD*) instructions. The above instructions are all of the RV32I instructions except for these omissions.

RISC-V links

RISC-V discussion


Lack of execute-only/read-only memory

" tropo 51 days ago [-]


It still won't do execute-only and true read-only memory. We've had true read-only for ages now on x86, and just got execute-only. You need these: rw- r-- --x

It still has poor support for ASLR, especially the limited-MMU variants. Even the most limited version should be able to require that the uppermost address bits be something randomish, even if it's only a per-priv-level random cookie. " -- [16]

Lack of overflow checks

" pizlonator 51 days ago [-]

"We did not include special instruction set support for overflow checks on integer arithmetic operations, as many overflow checks can be cheaply implemented using RISC-V branches."

False. For example, JavaScript? add/sub will require 3x more instructions on RISC-V than x86 or ARM. Same will be true for any other language requires (either implicitly, like JS, or explicitly, like .NET) overflow checking. Good luck with that, lol.

__s 50 days ago [-]

Many overflow checks can be removed with optimization. RISC-V's compressed encoding has shown to be ~70-80% more compact, so it has room for overflow checks. The efficiency of the architecture can always compile it out by time it hits microcode

pizlonator 50 days ago [-]

I pioneered most of WebKit?'s overflow check optimizations, and our compiler is bleeding-edge when it comes to eliminating them. Still, the overwhelming majority of the checks remain, because most integer values are not friendly to analysis (because they came from some heap location, or they came from some hard math, etc).

I doubt that the architecture will compile out signed integer addition overflow checks, which are the most common. They are brutal to express correctly without an overflow bit, and the architecture will have a hard time with this.

zxcdw 50 days ago [-]

Why do you suppose they left it out? Is it merely a matter of "cheap implementation" being purely subjective, and hence they might have thought it as cheap, while you seem to disagree? Or could there be a more pressing reason, but "Oh well, its cheap enough anyway" is more of an excuse?

pizlonator 50 days ago [-]

I don't think they knew that modern languages rely on overflow checks so heavily and that the perf of overflow checks dominates perf overall. " -- [17]