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
#SEQbool 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; ];