文章總列表

道道指令皆辛苦...

從前讀ARM instruction set的時候, 覺得CPU提供一大堆addressing mode很煩
那時候想說, 反正就是多一道兩道指令, 何必這麼辛苦?

最近有機會提CPU enhancement proposal, 需要仔細review C code和assembly code
舉例來講, C code可能長這樣...

    WRITE(ADDR, 0xaaaa)

首先是寫constant的部分, 需要三道指令才做得完

    load #ADDR, r0
    load #0xaaaa, r1
    store r1, [r0]

接著我們就會想, 如果可以直接把constant塞到instruction的話
就可以少一道指令, 也可以少用一個register


    load #ADDR, r0
    store 0xaaaa, [r0]



----


接著繼續思考不同的C code...


    WRITE(ADDR, 0xaaaa)
    WRITE(ADDR+1, 0xbbbb)


把上面的enhancement拿來用, 會變成這樣...


    load #ADDR, r0
    store 0xaaaa, [r0]
    add r0, #1
    store 0xbbbb, [r0]

如果遇到連續的address寫入, 這樣就會多一道中間的addi, 看起來有點討厭
如果讓store做完的時候, 同時把address pointer +1, 這個問題就可以被完美的解決


    load #ADDR, r0
    store 0xaaaa, [r0], #1
    store 0xbbbb, [r0], #1



這樣一來, 除了第一道指令載入address, 剩下都可以1cycle寫一筆出去


----


然後接著又會想, store constant的指令, 寫完就+1是不是我們要的行為?
有些硬體用indirect的方法存取, 行為像是這樣...

    WRITE(PERI_ADDR, 0x100)
    WRITE(PERI_ADDR+1, 0xaaaa) // peri[0x100] = 0xaaaa
    WRITE(PERI_ADDR+1, 0xbbbb) // peri[0x101] = 0xbbbb

    WRITE(PERI_ADDR+1, 0xcccc) // peri[0x102] = 0xcccc


如果store constant的指令固定會+1, 那上面的指令就會變成


    load #ADDR, r0
    store 0x100, [r0], #1
    store 0xaaaa, [r0], #1
    add r0, #-1
    store 0xbbbb, [r0], #1
    add r0, #-1
    store 0xcccc, [r0], #1

因為會有硬體用indirect的方式存取, store constant也不能讓他總是動pointer
所以說呢, 我們還要提供一個模式, 決定是不是要post-increment
如果可以在指令裡決定post-increment, 這樣問題就解決了...


    load #ADDR, r0
    store 0x100, [r0], #1
    store 0xaaaa, [r0], #0
    store 0xbbbb, [r0], #0
    store 0xcccc, [r0], #0




----


但是呢, 指令的bits數可能不夠, 以上面的例子來說, 這些資訊要塞進指令裡
    - op-code
    - immediate value
    - register index
    - post-increment or not

post-increment切換的功能需要1bit, 但是我已經用完所有空間
思考要不要拿register index來交換? 比如我只定址一半的register交換post-increment
再下一個問題, 好吧我真的拿register來換了, 是拿前半段還是後半段?
那就算換了, compiler是不是能自動產生出指令?


----


表面上看起來, 啊不就是要做到這些嗎? 其實背後分析的工作量遠超乎想像

做過才知道, 為了讓code跑得飛快, 真的是不容易




留言

這個網誌中的熱門文章

幼犬書桌椅選擇心得 升降桌 兒童桌椅

STM32 UART + DMA,使用HAL實作TX/RX,以及不定長度接收

CANON G3000 廢墨瓶改裝