2010年11月16日 星期二

Add new instruction to SimpleScalar (1) - Modify Simple Scalar

這份教學主要包含三個部份

1. 加指令到 SimpleScalar  (實驗中採用該版本 http://www4.ncsu.edu/~hhashem/mase-alphalinux.htm)
2. 加指令到 gas (Binutils 2.20)
3. 加指令到 gcc (GCC 4.4.3)

不過著重在前兩項, 第三項沒背景知識一時半刻也弄不來

教學範例是為 Alpha 加上整數除法!

(Alpha真他媽的畸形 有浮點數除法沒整數除法)


為你的SimpleScalar增加新的指令!

雖然這鬼東西已經夠老了, 不過可怕的是中文資源幾乎都只教怎麼安裝

沒教怎麼改

而增加指令只有首頁那該死的 def file format 可以參考

去年面對的時候選擇了逃避

沒想到其實沒有想像中的難...

就進入正題吧

http://www.simplescalar.com/docs/README-def.txt

有空還是請記得讀一下官方文件



1. 加指令到 SimpleScalar

為了達到增加指令的裡面,我們必須要先了解 SimpleScalar 是怎麼 decode 的

首先 SimpleScalar 採用一種名為 Decode Tree 的鬼東西,大致上來說就是需要在新增指令的時候大概按照他的樹狀結構編排

Decode Tree 的開端來自於 MD_TOP_OP(INST) 這個 Macro


這個是來自 ARM 的

#define MD_TOP_OP(INST) (((INST) >> 24) & 0x0f)

ARM 使用 23~27 bit 當主要的 Opcode
28~31被拿去當 Condition Code

這個是來自 Alpha 的

#define MD_TOP_OP(INST)         (((INST) >> 26) & 0x3f)

Alpha 則是前 7 bit 都抓去當 Opcode

所以有了 MD_TOP_OP 後我們可以開始建構 Decode Tree 了

以Alpha 為例

LDA 的 OPCODE 是 0x08

那麼我們就直接定義


DEFINST(LDA,                    0x08,
        "lda",                  "a,o(b)",
        IntALU,                 F_ICOMP,
        DGPR(RA), DNA,          DNA, DGPR(RB), DNA)

第一個參數是拿來辨別的
第二個參數是OPCODE
第三個參數是拿來 disasm 用的資訊
第四個參數也是拿來 disasm 用的資訊
第五個參數是會用到哪個 Functional Unit, 這個在 sim-outorder 下會有影響
第六個參數則是分類該指令, 同樣的也是在 sim-outorder 下會有影響
接下來六七個是 Output Register , 拿來控制 Dependency 用的
八九十則是 Input Register , 也是拿來控制 Dependency 用的
所以後五個參數, 請直接跟同類型的指令拷貝

注意一下 ARM 的參數個數有點不太一樣, 主要差在後面不止五個

接著請記得在這個 Marco 的前面定義一個

LDA_IMPL 的 Macro


#define LDA_IMPL                    \
{                                   \
  SET_GPR(RA, GPR(RB) + SEXT(OFS)); \
}

這個是用來實作該指令的功能的


看到這邊應該正常來講已經可以做到基本的增加指令了

但是通常事情沒那麼簡單

常常有 OPCODE 外還會有 Function Code , Alpha 中Operate Instruction 就是這樣, 在 MIPS 中也有

那麼我們就不能直接像 LDA 般那麼歡樂的加指令

這時候套個 SimpleScalar 說明文件的術語

我們需要 Sub Decode Tree !

意思是說我們用 OPCODE 分了某類後想要再依照某些欄位分類的話就要 Sub Decode Tree

阿 Sub Decode Tree 到底是什麼 ?

簡單的說就是類似再一次的設定 MD_TOP_OP 的那種感覺

不過已經不是 TOP 而是 SECOND 了, 喔 這不是重點

接下來我們需要 DEFLINK 這個東西來定義 Sub Decode Tree Root

例如以 Alpha add, sub 等等的 OPCODE 0x10 為例



我們只要這樣定義


DEFLINK(INTA, 0x10, "inta", 5, 0x7f)

第一個欄位是該  Sub Decode Tree 的名稱
第二個欄位是OPCODE
第三個欄位是註解
第四個欄位是新的OPCODE的偏移量
第五個欄位是新的OPCODE的MASK

所以這個 DEFLINK 的效用大概會等於

MD_SECOND_OP(INST) ((INST >> 5) & 0x7f)

喔, 不過沒有 MD_SECOND_OP 這麼 Macro , 別真的去宣告


就會出現一顆 Sub Decode Tree 了


接下來很重要的是我們需要 CONNECT 兩棵 Decode Tree

CONNECT(INTA)

然後就只要符合 MD_TOP_OP(INST) = 0x10 的都會掉進這顆叫 INTA 的 Sub Decode Tree 了~

接著我們只要開心的 DEFINST 就可以了~

不過其實很多情況下我們並不只想要兩層 Decode Tree 就解決, 有時候可能會需要三層甚至四層, 這時候該怎麼辦呢?

方法就是在該 Sub Decode Tree 的 CONNECT 後再 DEFLINK

那麼這個 DEFLINK 就會是 Sub Sub Decode Tree 了

在 Alpha 中就用這種無聊的技巧來分別第三個 Operand 是 Imm 還是 Reg

對, 真的很無聊...明明就用個 if 就解決了, 還要靠這該死的 Decode Tree

如果無聊去看實作的話會發現這樣做只是比較慢而且免費讓 DEF 膨脹到快兩倍而已






下集待續吧~

沒有留言:

張貼留言