4.1 Y86-64 指令集体系结构
通过 Y86——一个模仿 X86 的体系结构学习 CPU 构造
程序员可见状态
去掉了 %r15,用 F 代表无寄存器。
Y86-64 指令
只反对 64 位。
mov:
分成 irmovq,rrmovq,mrmovq,rmmovq。不反对第二变址寄存器,和伸缩。即 rrmovq (%rdi,%rsi,4) %rdx
这样的格局。
算数运算:
addq, subq, andq, xorq, 这些指令会设置条件码。
残余:跳转,条件传送,call&ret,push&pop,halt
指令编码
与 x86 相似。第一个字节前四位指明指令大类,后四位指明具体行为,比方 addq=0x60。第二个字节指明 REGIS A,B。
4.2 逻辑设计和硬件管制语言 HCL
逻辑门
[逻辑门类型和图形示意]
组合电路和 HCL 布尔表达式
HCL 布尔表达式都可能被转化成电路设计。比方位相等 bool eq = (a && b) || (!a && !b)
就能够用下图示意。
而多路复用器电路bool out = (s && a) || (!s && b);
(用 S 管制输入 a /b)能够用下图示意。
字节级别
将 64 个小电路做 AND 运算即可。
能够形象成一个大单元。
存储器和时钟
作者先提出了两类寄存器的区别。这是在前面才会学到的。硬件寄存器,是用于字传送的,程序员不可见。程序寄存器,程序员可见,就是汇编用到的那些。
寄存器在电压回升是载入新值,输入原址(保留的值)。时钟管制着寄存器的加载。
4.3 Y86-64 的 SEQ 实现
SEQ 硬件实现
在程序实现中,一个时钟周期被分为 5 片(2 和 5 常常在一起说):1.fetch 2. decode 3.execute 4.memory 5.write back 6.pc update
fetch
从 M[PC]中拿到指令,rA,rB,valC,valP(+ 8 的)。检测简略谬误。
decode
从寄存器失去 valA,valB。
execute
依据 icode,决定 ALU 的性能,输入 valE。
memory
依据 memo_addr,memo_data, 从内存中读取 / 写入数据 / 产出谬误。他们的值从 HCL 中来。
write back
依据 dstE,valE(execute 失去的),dstM,valM(memory 失去的)更新指标寄存器。
SEQ 的实现
这个局部把下面的图拆成 5 个局部,每个局部用小图和 HCL 的形式形容进去。残缺 HCL 如下
fetch
#SEQ
bool need_regids =icode in {IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, IIRMOVQ, IRMMOVQ, IMRMOVQ};
bool need_valC = icode in {IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL};
decode&writeback
word srcA = [icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ icode in { IPOPQ, IRET} : RRSP; 1 : RNONE; # Don’t need register ];
word srcB = [icode in { IOPQ, IRMMOVQ, IMRMOVQ} : rB; icode in {IPUSHQ, IPOPQ, ICALL, IRET} : RRSP; 1 : RNONE; # Don’t need register ];
# WARNING: Conditional move not implemented correctly here word
dstE = [icode in { IRRMOVQ} : rB; icode in {IIRMOVQ, IOPQ} : rB; icode in {IPUSHQ, IPOPQ, ICALL, IRET} : RRSP; 1 : RNONE; # Don’t write any register ];
word dstM = [icode in { IMRMOVQ, IPOPQ} : rA; 1 : RNONE; # Don’t write any register ];
word dstE = [icode in { IRRMOVQ} && Cnd : rB; icode in {IIRMOVQ, IOPQ} : rB; icode in {IPUSHQ, IPOPQ, ICALL, IRET} : RRSP; 1 : RNONE; # Don’t write any register ];
execute
word aluA = [icode in { IRRMOVQ, IOPQ} : valA; icode in {IIRMOVQ, IRMMOVQ, IMRMOVQ} : valC;
word aluB = [icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL, IPUSHQ, IRET, IPOPQ} : valB;
icode in {IRRMOVQ, IIRMOVQ} : 0;
# Other instructions don’t need ALU
];
word alufun = [icode == IOPQ : ifun; 1 : ALUADD;];
bool set_cc = icode in {IOPQ};
memory
word mem_addr = [icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ} : valE; icode in {IPOPQ, IRET} : valA;
# Other instructions don’t need address
];
word mem_data = [# Value from register icode in { IRMMOVQ, IPUSHQ} : valA; # Return PC icode == ICALL : valP;
# Default: Don’t write anything
];
bool mem_read = icode in {IMRMOVQ, IPOPQ, IRET};
bool mem_write = icode in {IRMMOVQ, IPUSHQ, ICALL};
update pc
word new_pc = [
# Call. Use instruction constant
icode == ICALL : valC;
# Taken branch. Use instruction constant
icode == IJXX && Cnd : valC;
# Completion of RET instruction. Use value from stack
icode == IRET : valM;
# Default: Use incremented
1 : valP;
];
# Determine instruction status
word Stat = [imem_error || dmem_error : SADR; !instr_valid: SINS; icode == IHALT : SHLT; 1 : SAOK;];