CS61C Lec 2 - RISC-V
0 Introduction
To command a computer’s hardware, you must speak its language. The words of a computer’s language are called instructions, and its vocabulary is called an
instruction set (指令集).
The basic job of a CPU is to execute lots of instructions. Instructions are the primitive operations that the CPU may execute.
You might think that the languages of computers would be as diverse as those of people, but in reality, computer languages are quite similar, more like regional dialects than independent languages. Hence, once you learn one, it is easy to pick up others.
Different CPUs implement different sets of instructions. The set of instructions a particular CPU implements is an Instruction Set Architecture (ISA). For example, ARM(cell phones), Intel x86, RISC-V, …
Early trend was to add more and more instructions to new CPUs to do elaborate operations.
RISC philosophy (Cocke IBM, Patterson, Hennessy, 1980s) - Reduced Instruction Set Computing
- Keep the instruction set small and simple, makes it easier to build fast hardware.
- Let software do complicated operations by composing simpler ones.
- This went against the convention wisdom of the time.
RISC-V started in summer 2010 to support open research and teaching at UC Berkeley. It’s a new open-source, license-free ISA spec supported by growing shared software ecosystem and appropriate for all levels of computing system.
1 Add/Sub Instructions
The syntax of instructions is rigid: 1 operator and 3 operands
1 | add x1, x2, x3 # x1 = x2 + x3 |
The compiler translates from C to RISC-V assembly language instructions. How to do the C statement a = b + c + d - e; ?
1 | add x10, x1, x2 |
2 Operands of the Computer Hardware
2.1 Registers
Unlike programs in high-level languages, the operands of arithmetic instructions are restricted; they must be from a limited number of special locations built directly in hardware called registers (寄存器).
Registers are primitives used in hardware design that
are also visible to the programmer when the computer is completed, so you can think of registers as the bricks of computer construction. The size of a register in the RISC-V architecture is 64 bits; groups of 64 bits occur so frequently that they are given the name doubleword in the RISC-V architecture. (Another popular size is a group of 32 bits, called a word in the RISC-V architecture.)
Instruction set for a particular architecture (e.g. RISC-V) is represented by the assembly language.
Each line of assembly code represents one instruction for the computer.
Assembly can’t use variables. Assembly operands are registers, which are limited number of special locations, built directly into the hardware. Register contents are just bits.

Each ISA has a predetermined number of registers because registers are built into hardware. There are 32 registers in RISC-V. Each RISC-V register is 32 bits wide in RV32 variant. Groups of 32 bits is called a word in RV32. The width of a word is associated with a variant of the architecture.
Registers are numbered from 0 to 31 (x0 to x31)
x0 is special, always holds value zero.
2.2 Memory Operands
Programming languages have simple variables that contain single data elements, as in these examples, but they also have more complex data structures—arrays and structures. These composite data structures can contain many more data elements than there are registers in a computer. How can a computer represent and access such large structures?
The processor can keep only a small amount of data in registers, but computer memory contains billions of data elements. Hence, data structures (arrays and structures) are kept in memory.
As explained above, arithmetic operations occur only on registers in RISC-V instructions; thus, RISC-V must include instructions that transfer data between
memory and registers. Such instructions are called data transfer instructions.
To access a word or doubleword in memory, the instruction must supply the memory address. Memory is just a large, single-dimensional array, with the
address acting as the index to that array, starting at 0.
The data transfer instruction that copies data from memory to a register is called load. The format of the load instruction is the name of the operation followed by the register to be loaded, then register and a constant used to access memory. The sum of the constant portion of the instruction and the contents
of the second register forms the memory address. The real RISC-V name for this instruction is ld, standing for load doubleword.
Since 8-bit bytes are useful in many programs, virtually all architectures today address individual bytes. Therefore, the address of a doubleword matches the address of one of the 8 bytes within the doubleword.
Computers divide into those that use the address of the leftmost or “big end” byte as the doubleword address versus those that use the rightmost or “little end” byte. RISC-V belongs to the latter camp, referred to as little-endian.

Byte addressing also affects the array index. To get the proper byte address in the code above, the offset to be added to the base register x22 must be 8 × 8, or 64.
The instruction complementary to load is traditionally called store; it copies data from a register to memory. The format of a store is similar to that of a load: the name of the operation, followed by the register to be stored, then the base register, and finally the offset to select the array element.
Many programs have more variables than computers have registers. Consequently, the compiler tries to keep the most frequently used variables in registers and places the rest in memory, using loads and stores to move variables between registers and memory. The process of putting less frequently used variables (or those needed later) into memory is called spilling registers (寄存器换出).
Registers take less time to access and have higher throughput than memory, making data in registers both considerably faster to access and simpler to use. Accessing registers also uses much less energy than accessing memory. To achieve the highest performance and conserve energy, an instruction set architecture must have enough registers, and compilers must use registers efficiently.
2.3 RISC-V Immediates
Immediates are numerical constants
1 | # Add Immediate instruction |
3 Instructions for Making Decisions
What distinguishes a computer from a simple calculator is its ability to make decisions. Based on the input data and the values created during computation,
different instructions execute.
1 | beq rs1, rs2, L1 |
This instruction means go to the statement labeled L1 if the value in register rs1 equals the value in register rs2. The mnemonic beq stands for branch if equal.
1 | bne rs1, rs2, L1 |
It means go to the statement labeled L1 if the value in register rs1 does not equal the value in register rs2. These two instructions are traditionally called conditional branches.
1 | beq x5, x6, Equal # 如果 x5 == x6,跳到 Equal |
无条件的分支更简单,j Label即可
例如
1 | if (i == j) { |
1 | bne x13, x14, Else |
1 | blt reg1, reg2, Label # if (reg1 < reg2) goto Label |
对于循环
1 | double save[5]; |
1 | # x22寄存器对应i,x25保存数组的基地址 |



