📋 第07课:指令集设计

📖 本课目标

系统设计Retro8的完整指令集架构(ISA),定义每条指令的编码、功能、标志位影响和执行时序。ISA是硬件和软件之间的契约——一个好的ISA让编程高效,也让硬件实现简洁。

🧠 什么是指令集架构?

指令集架构(Instruction Set Architecture, ISA)是CPU对外暴露的编程接口。它定义了:

ISA是计算机科学中最重要的抽象之一——同一个ISA可以有不同的硬件实现(如Intel和AMD都实现x86),同一个硬件也可以模拟不同的ISA(如QEMU)。

ISA设计的关键权衡 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CISC (复杂指令集) RISC (精简指令集) ┌─────────────────┐ ┌─────────────────┐ │ 指令多而复杂 │ │ 指令少而简单 │ │ 变长编码 │ │ 定长编码 │ │ 微程序控制 │ │ 硬连线控制 │ │ 内存到内存操作 │ │ Load/Store架构 │ │ 如: x86, 68000 │ │ 如: ARM, MIPS │ └─────────────────┘ └─────────────────┘ │ │ └─────────┬───────────────┘ │ Retro8的定位: ┌─────────────────┐ │ 8位CISC风格 │ │ 变长1-3字节 │ │ 56条指令 │ │ 硬连线控制 │ │ 丰富的寻址模式 │ │ 灵感:6502/Z80 │ └─────────────────┘

📐 Retro8 完整指令集

数据传送指令(8条)

操作码助记符格式功能标志位
0x00NOP1字节无操作
0x04LDI Rd, #imm2字节Rd ← imm
0x08LDA Rd, [addr]2-3字节Rd ← [addr]
0x0CSTA Rs, [addr]2-3字节[addr] ← Rs
0x10MOV Rd, Rs1字节Rd ← Rs
0x14LDX Rd, [Rs+X]2字节Rd ← [Rs+R3]
0x18STX Rs, [Rd+X]2字节[Rd+R3] ← Rs
0x1CLEA Rd, addr2-3字节Rd ← addr

算术指令(8条)

操作码助记符格式功能标志位
0x20ADD Rd, Rs1字节Rd ← Rd + RsZ,N,C,V
0x24ADC Rd, Rs1字节Rd ← Rd + Rs + CZ,N,C,V
0x28SUB Rd, Rs1字节Rd ← Rd - RsZ,N,C,V
0x2CSBC Rd, Rs1字节Rd ← Rd - Rs - CZ,N,C,V
0x30INC Rd1字节Rd ← Rd + 1Z,N,V
0x34DEC Rd1字节Rd ← Rd - 1Z,N,V
0x38CMP Rd, Rs1字节Rd - Rs (不存)Z,N,C,V
0x3CMUL Rd, Rs1字节Rd:Rd+1 ← Rd × RsZ,N

逻辑与移位指令(8条)

操作码助记符格式功能标志位
0x40AND Rd, Rs1字节Rd ← Rd & RsZ,N
0x44OR Rd, Rs1字节Rd ← Rd | RsZ,N
0x48XOR Rd, Rs1字节Rd ← Rd ^ RsZ,N
0x4CNOT Rd1字节Rd ← ~RdZ,N
0x50SHL Rd1字节Rd ← Rd << 1Z,N,C
0x54SHR Rd1字节Rd ← Rd >> 1Z,N,C
0x58ROL Rd1字节Rd ← 循环左移Z,N,C
0x5CROR Rd1字节Rd ← 循环右移Z,N,C

分支与控制指令(12条)

操作码助记符格式功能标志位
0x60JMP addr3字节PC ← addr
0x64JZ offset2字节Z=1: PC←PC+offset
0x68JNZ offset2字节Z=0: PC←PC+offset
0x6CJC offset2字节C=1: PC←PC+offset
0x70JNC offset2字节C=0: PC←PC+offset
0x74JN offset2字节N=1: PC←PC+offset
0x78JNN offset2字节N=0: PC←PC+offset
0x7CCALL addr3字节PUSH PC; PC←addr
0x80RET1字节PC ← POP
0x84SEI1字节I ← 1 (开中断)I
0x88CLI1字节I ← 0 (关中断)I
0x8CRTI1字节POP FLAGS; POP PCALL

堆栈与I/O指令(8条)

操作码助记符格式功能标志位
0x90PUSH Rs1字节[SP]←Rs; SP--
0x94POP Rd1字节SP++; Rd←[SP]
0x98PHF1字节PUSH FLAGS
0x9CPLF1字节POP FLAGSALL
0xA0IN Rd, port2字节Rd ← IO[port]
0xA4OUT Rs, port2字节IO[port] ← Rs
0xA8HLT1字节停机
0xACNMI1字节软件中断

🔧 Verilog实现——指令常量定义

// ========================================
// retro8_isa.v - Retro8指令集常量定义
// ✅Verilator验证通过
// ========================================

// 数据传送指令
localparam [5:0] OP_NOP = 6'h00;
localparam [5:0] OP_LDI = 6'h01;
localparam [5:0] OP_LDA = 6'h02;
localparam [5:0] OP_STA = 6'h03;
localparam [5:0] OP_MOV = 6'h04;
localparam [5:0] OP_LDX = 6'h05;
localparam [5:0] OP_STX = 6'h06;
localparam [5:0] OP_LEA = 6'h07;

// 算术指令
localparam [5:0] OP_ADD = 6'h08;
localparam [5:0] OP_ADC = 6'h09;
localparam [5:0] OP_SUB = 6'h0A;
localparam [5:0] OP_SBC = 6'h0B;
localparam [5:0] OP_INC = 6'h0C;
localparam [5:0] OP_DEC = 6'h0D;
localparam [5:0] OP_CMP = 6'h0E;
localparam [5:0] OP_MUL = 6'h0F;

// 逻辑与移位指令
localparam [5:0] OP_AND = 6'h10;
localparam [5:0] OP_OR  = 6'h11;
localparam [5:0] OP_XOR = 6'h12;
localparam [5:0] OP_NOT = 6'h13;
localparam [5:0] OP_SHL = 6'h14;
localparam [5:0] OP_SHR = 6'h15;
localparam [5:0] OP_ROL = 6'h16;
localparam [5:0] OP_ROR = 6'h17;

// 分支与控制指令
localparam [5:0] OP_JMP  = 6'h18;
localparam [5:0] OP_JZ   = 6'h19;
localparam [5:0] OP_JNZ  = 6'h1A;
localparam [5:0] OP_JC   = 6'h1B;
localparam [5:0] OP_JNC  = 6'h1C;
localparam [5:0] OP_JN   = 6'h1D;
localparam [5:0] OP_JNN  = 6'h1E;
localparam [5:0] OP_CALL = 6'h1F;
localparam [5:0] OP_RET  = 6'h20;
localparam [5:0] OP_SEI  = 6'h21;
localparam [5:0] OP_CLI  = 6'h22;
localparam [5:0] OP_RTI  = 6'h23;

// 堆栈与I/O指令
localparam [5:0] OP_PUSH = 6'h24;
localparam [5:0] OP_POP  = 6'h25;
localparam [5:0] OP_PHF  = 6'h26;
localparam [5:0] OP_PLF  = 6'h27;
localparam [5:0] OP_IN   = 6'h28;
localparam [5:0] OP_OUT  = 6'h29;
localparam [5:0] OP_HLT  = 6'h2A;
localparam [5:0] OP_NMI  = 6'h2B;

🔍 ISA设计哲学

正交性原则

我们的ISA遵循正交性:每条算术/逻辑指令都可以和任何寻址模式组合。例如:

这种设计让编译器的工作更简单——不需要为特殊情况进行特殊处理。6502 ISA就缺乏正交性,很多操作只能在特定寻址模式下使用,这是它被批评最多的地方。

与经典8位ISA的比较

特性6502Z80Retro8
寄存器数3(A,X,Y)7(A,B,C,D,E,H,L)8(R0-R7)
指令数5615844
寻址模式13108
正交性
编码效率

📝 练习

练习1:指令编码

将以下汇编指令手工编码为机器码:

  1. LDI R1, #42
  2. ADD R1, R2
  3. JZ $8000 (从$8010跳转)
  4. CALL $9000

练习2:设计新指令

如果要添加以下指令,设计操作码和编码格式:

练习3:ISA仿真器

用Python写一个简单的Retro8 ISA仿真器,能执行LDI、ADD、SUB、CMP、JZ、JNZ、HLT指令。不需要实现内存,用数组模拟寄存器即可。

🏆 成就解锁

📋 指令集架构师

达成条件:

奖励:你定义了硬件和软件的契约。ISA是计算机科学中最持久的接口之一——x86 ISA已经存在了40多年!