• RSS 订阅

Computer Organization and Design 第二章学习笔记

《Computer Organization and Design RISC-V Edition: The Hardware/Software Interface (2nd Edition)》第二章 “Instructions: Language of the Computer” 的学习笔记。

主要是在讲 RISC-V。可以参考 Specifications – RISC-V International(比 x86 短多了)。

(P.S. 其他书我是认真看了第一章但懒得写,这本(如果看过 CS:APP 的话)建议直接跳过第一章(

Registers

RISC-V (RV32) 的 register 是 32-bit 的,而 32-bit 称作一个 word(与 x86 不同)。

有 32 个 register,用 x0~x31 来标识,每个 register 根据其功能还有一个(或多个)别名。

x0 / zero 的值固定为 0,能起到很多作用,例如在 sub 中作为被减数来取负、作为 destination 来丢弃结果、在 conditional branch(不接受 immediate)中作为比较的参数。

其他寄存器在硬件层面上没有区别,但有用于 procedure 的 convention:

  • x1 / ra 是 return address(call 是 jal x1, foo,return 是 jalr x0, 0(x1))。

  • x2 / sp 是 stack pointer。

  • x3 / gp 是 global pointer(指向 static variable 的位置)。

  • x4 / tp 是 thread pointer。

  • x8 / fp 可以用作 frame pointer。

  • x10-x17 (a0-a7) 用来存放前 8 个参数或返回值(一般单个返回值就是 x10)。

  • x8-x9 (s0-s1), x18-x27 (s2-s11) 是 (callee-)saved。

  • x5-x7 (t0-t2), x28-x31 (t3-t6) 是 temporary (caller-saved)。

Basic Instructions

op1 = op2 op op3

add, sub, addi, and, or, xor, andi, ori, xori, sll, srl, sra, slli, srli, srai, slt, sltu, slti, sltiu

  • add x5, x6, x7: x5 = x6 + x7
  • addi x5, x6, 20: x5 = x6 + 20,其中 immediate 是 12-bit signed integer。
  • slt x5, x6, x7: x5 = x6 < x7 ? 1 : 0

Data Transfer

load word: lw x5, 40(x6): x5 = Memory[x6 + 40]

store word: sw x5, 40(x6): Memory[x6 + 40] = x5

half word、byte: lh, lhu, sh, lb, lbu, sb,其中 u 用来决定高位补零还是符号位。

Conditional Branch

beq, bne, blt, bltu, bge, bgeu

blt x5, x6, 100: if (x5 < x6) goto PC+100

Unconditional Branch

jal x1, 100: x1 = PC+4; goto PC+100

jalr x1, 100(x5): x1 = PC+4; goto x5+100

Instruction Format

RISC-V 的 instruction 都是 32 bits 长,有若干种不同的 instruction format。

其中 “rs” 是 register source,“rd” 是 register destination,“funct” 用作 additional opcode。

R-type:

I-type:

S-type:

可以看出,在不同的 format 中,会尽量保留 rs、rd、opcode、funct3 的位置不变,以简化电路(其中保持 opcode 位置不变对于识别 instruction format 是必要的)。

Wide Immediates and Addresses

Wide Immediates

超过 12 bits 的 immediate 可以通过两条 instruction lui (load upper immediate) 和 addi load 到 register,其中 lui 是 U-type:

auipc 可以用来进行更大范围的 PC-relative branch,和 lui 类似,会将 PC 加上一个只有高位的 immediate 存于 register。

Addressing in Branches

branch 使用的 address 必须是偶数,而且 branch instruction 使用了特殊的编码格式。

unconditional branch 使用 B-type,和 S-type 类似:

jal 使用 J-type,和 U-type 类似:

jalr 使用 I-type。

通过对 immediate 的重排:

  • 所有格式中 immediate 的符号位都在同一位。
  • I、S、B、U 中 imm[10:5] 位置相同。
  • S、B 中 imm[4:1] 位置相同。
  • I、J 中 imm[4:1] 位置相同,U、J 中 imm[19:12] 位置相同。

Synchronization in Parallelism

在 parallel execution 中,需要 processor 支持 atomic operation 来实现各种 synchronization,例如 lock。

RISC-V 提供一对命令 lr.w (load-reserved word) 和 sc.w (store-conditional word) 来实现 “atomically read and modify a memory location”:

  1. lr.w 接受两个 register 作为 operand,分别是 destination 和 address,它单独一个命令自身的效果和 lw 类似;
  2. sc.w 接受三个 register 作为 operand,后两个是 source 和 address,若在 lr.w 和 sc.w 之间 address 处被修改过则 store 会失败。第一个 operand 用来存放结果(0 表示成功,非零表示失败)、。

实现 atomic swap:(交换 (x20) 和 x23)

again:
    lr.w x10, (x20)
    sc.w x11, x23, (x20)
    bne  x11, x0, again
    addi x23, x10, 0

实现 lock:((x20) 为 0/1 表示 lock free/acquired)

acquire:
    addi x12, x0, 1
again:
    lr.w x10, (x20)
    bne  x10, x0, again
    sc.w x11, x12, (x20)
    bne  x11, x0, again

release:
    sw   x0, 0(x20)

Pseudoinstructions

为了方便编写汇编,汇编中可以使用一些在 hardware 上不存在的 pseudoinstruction。例如:

  • nop: addi x0, x0, 0
  • mv rd, rs: addi rd, rs, 0
  • not rd, rs: xori rd, rs, -1
  • neg rd, rs: sub rd, x0, rs
  • bgt rs, rt, offset: blt rt, rs, offset
  • bnez rs, offset: bne rs, x0, offset
  • ble rs, rt, offset: bge rt, rs, offset
  • jal offset: jal x1, offset
  • ret: jalr x0, 0(x1)

详见《The RISC-V Instruction Set Manual Volume I: Unprivileged ISA》Chapter 25 RISC-V Assembly Programmer’s Handbook。

Footnotes

  1. 《The RISC-V Instruction Set Manual Volume I: Unprivileged ISA (20191213)》2.5 Control Transfer Instructions ↩

  2. 《The RISC-V Instruction Set Manual Volume I: Unprivileged ISA (20191213)》1.5 Base Instruction-Length Encoding ↩