經過Y86——一個模擬X86的體系結構學習CPU結構
去掉了%r15,用F表明無寄存器。程序員
只支持64位。學習
分紅irmovq,rrmovq,mrmovq,rmmovq。不支持第二變址寄存器,和伸縮。即rrmovq (%rdi,%rsi,4) %rdx
這樣的格式。fetch
addq, subq, andq, xorq,這些指令會設置條件碼。編碼
與x86相似。第一個字節前四位指明指令大類,後四位指明具體行爲,好比 addq=0x60。第二個字節指明REGIS A,B。spa
[邏輯門類型和圖形表示]設計
HCL布爾表達式都可以被轉化成電路設計。好比位相等bool eq = (a && b) || (!a && !b)
就能夠用下圖表示。
而多路複用器電路bool out = (s && a) || (!s && b);
(用S控制輸出a/b)能夠用下圖表示。code
將64個小電路作AND運算便可。
能夠抽象成一個大單元。blog
做者先提出了兩類寄存器的區別。這是在後面纔會學到的。硬件寄存器,是用於字傳送的,程序員不可見。程序寄存器,程序員可見,就是彙編用到的那些。
寄存器在電壓上升是載入新值,輸出舊址(保存的值)。時鐘控制着寄存器的加載。內存
在順序實現中,一個時鐘週期被分爲5片(2和5常常在一塊兒說):1.fetch 2. decode 3.execute 4.memory 5.write back 6.pc updaterem
從M[PC]中拿到指令,rA,rB,valC,valP(+8的)。檢測簡單錯誤。
從寄存器獲得valA,valB。
根據icode,決定ALU的功能,輸出valE。
根據memo_addr,memo_data,從內存中讀取/寫入數據/產出錯誤。他們的值從HCL中來。
根據dstE,valE(execute獲得的),dstM,valM(memory獲得的)更新目標寄存器。
這個部分把上面的圖拆成5個部分,每一個部分用小圖和HCL的方式描述出來。完整HCL以下
#SEQ bool need_regids =icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ, IIRMOVQ, IRMMOVQ, IMRMOVQ }; bool need_valC = icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL };
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 ];
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 };
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 };
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; ];