關於RISCV儲存器訪問指令的分析

2021-09-10 23:43:36 字數 2507 閱讀 8007

risc v 32i 指令訪問儲存器指令有load和store兩類。這裡說的load就是從儲存器memory裡面讀出資料到暫存器組register files。而store正式相反的方向。

無論是load還是store我總結都有如下特點:

1,位址的生成都是乙個暫存器的數值+乙個立即數的偏移量(此立即數是有符號擴充套件)。

2,都是直接跟暫存器進行資料交換,也就是從暫存器到儲存器不存在運算,都是直接拷貝進去。

我們知道,在c語言中可用的資料型別有位元組,半字,和字。在32位的目標機中一般分別對應如下:

位元組,byte 對應 unsigned char 或者char 

半字,half word 對應unsigned short 或者short

字, word 對應unsigned int 或者 int .

以上這三類是處理器最基本的處理的資料型別,所以riscv 要分別實現對這三種資料型別load和store 。也因為這三種型別都要能定址出來,所以位址應該用最小元素的位址單位,是位元組位址。實際也是這樣的,我們在儲存器裡說的位址都是位元組位址。

我們先看store ,有三條指令  sb,sh,word,分別是store byte,store half word, store word .

store byte是將暫存器rs2的0位到7位內容儲存在rs1為基位址,立即數進行有符號擴充套件後的s_imm為偏移量(可正可負)的位址。

store half word 將暫存器rs2的0位到15位內容儲存在rs1為基位址,立即數進行有符號擴充套件後的s_imm為偏移量(可正可負)為開始兩個位元組的位址。這兩個位元組位址分別儲存0為到7位,以及8-15位。這就有了大小字端的區別:如果0-7位儲存在低位元組位址,那麼此儲存方式就是小字段,反之為大字段。riscv 支援的儲存方式小字段,這和當下流行的intel 以及arm 是一致的。

store word 將暫存器rs2的0位到31位內容儲存在rs1為基位址,立即數進行有符號擴充套件後的s_imm為偏移量(可正可負)為開始四個位元組的位址。當然也存在大小字端的說法,按照小字端方式儲存。

這三條指令都是將某暫存器的內容裡的某些位拷貝到指定的儲存儲存位址,而下面的這load指令就稍微複雜了點兒。

我們知道整數型別的資料都有signed 和unsigned 型別,也就是說有符號和無符號型別。而進行運算的暫存器型別都是32位,所以當從暫存器載入乙個8位或者16位的資料的時候,就要區別這個資料是signed還是unsigned的,以便儲存在32位暫存器裡還是乙個對應數值。

先回顧一下計算機實際表示負數的方法,基本我們所接觸的系統表示整型負數都是用補碼,乙個負數的補碼就是這個數對應整數的整數按位取反後加1。而看乙個數是否為負數就看資料型別的最高位是否為1,  所以我們看char 型別的-1表示為 ~1+1 =8'hff。而int型別的-1表示為 ~1+1 = 32'hffff_ffff  。我要舉的例子就是將乙個char型別的位元組 8'hff 如果直接拷貝到32位暫存器的低8位,那麼得到的數值按照32位的有符號整數或者32位無符號整數怎麼解析都是32'h0000_00ff,是十進位制的255,就不是-1了。怎麼解決這個問題呢,就是載入這個8位數的時候首先要明確是否當做有符號數來載入,當做有符號資料載入就用lb  load byte 指令,而當做無符號數載入就用lbu load byte unsigned 來載入。lbu就是將位元組簡單的放在32位暫存器的低8位,其餘高24位全部填0;而lb會先判斷一下儲存器位元組的最高位是否1,如果是1就講高24位全部填充為1,這樣保持符號相同。所以我們如果將儲存器裡面的'hff內容當做8位無符號整數(255)載入到暫存器就用lbu指令,在暫存器裡面得到32'h0000_00ff這個結果,還是255;如果將儲存器裡面的'hff內容當做8位有符號整數(-1)載入到暫存器就用lb指令,j載入時候進行符號位擴充套件(位元組的最高位是1,所以32位暫存器的高24位都填寫為1)在暫存器裡面得到32'hffff_ffff這個結果,這就是32位表示的有符號整數的-1。

我們這裡不妨再較真一下,為了是lb 和lbu,是載入位元組和載入無符號位元組,這裡應該是隱含了一層意思:lb除了載入有符號的位元組整數,還可以載入無符號的位元組整數?仔細想想,有符號位元組可以表示正數,0和負數。而乙個表示正數的有符號數進行位擴充套件實際也是將高24位填充為0,也就相當於實現了lbu,也就是實現了載入無符號位元組,所以不能簡單說這種為擴充套件指令就是load byte signed。

上面分析了符號位擴充套件的必要性(保持正負號以及數值一致)和實現方式(可進行符號位擴充套件)。

同樣道理載入乙個16位的半字,也就對應有了lh和lhu這兩條指令。

載入乙個32位的字,儲存器裡面儲存的32位和處理器內通用暫存器儲存的內容完全對應,因此不需要擴充套件,(也可以認為進行了擴充套件,只是最高符號位的擴充套件被忽略了),只有load word這條指令。而如果我們處理器執行的指令系統是64位的,也就是說暫存器是64位的,那麼乙個32位的儲存器內容要載入到64位的暫存器裡面同樣面臨是否進行位擴充套件的問題,這也就是為什麼在64位指令系統裡面多出了乙個指令 lwu 。這麼說來對應lw在64位暫存器的處理器實現要進行符號位擴充套件啦。

以上分析了riscv32的儲存相關指令。為了避免本篇內容太長,我在另外的blog再分析一下跟儲存指令實現相關的內容。

有興趣的朋友可以加qq群一起學習討論 29304866

RISC V 指令集的模組化和暫存器結構

risc v 指令集架構是加州大學伯克利分校研發的第五代精簡指令集架構,先後經歷了四代精簡指令集的發展,旨在設計乙個完全開放 免費的和效能強大的指令集架構。它和x86 arm相比,一大優勢就是支援模組化,下面我們就來介紹一下risc v指令集的模組化結構,順便再介紹下其暫存器結構。risc v 指令...

關於儲存器

查了好多資料 進行乙個小的總結,侵刪 儲存器這個名詞包含的範圍很大,它幾乎涵蓋了所有關於儲存的範疇。暫存器 記憶體 外儲存器都是儲存器裡面的一種。凡是有儲存能力的硬體,都可以稱之為儲存器。快取就是資料交換的緩衝區 稱作cache 硬體系統需要讀取資料時,會首先從快取中查詢需要的資料,如果找到了則直接...

關於訪問器屬性

要修改屬性預設的特性,必須使用ecamscript 5的 object.defineproperty 方法。例如 var person object.defineproperty person,name console.log person.name tom person.name join con...