乐趣区

关于csapp:CPU体系结构笔记

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

4.4 流水线通用原理

退出移动版