簡體   English   中英

如何使用RISC-V架構的C.ADDI4SPN和C.ADDI16SP指令(壓縮子集)?

[英]How to use C.ADDI4SPN and C.ADDI16SP instructions (compressed subset) of RISC-V architecture?

我不知道如何以正確的方式調用這兩個指令。 第一條指令C.ADDI4SPN的第一個操作數應該是一個寄存器,第二個,如果我是對的,應該是一個按 4 縮放的數字。

但是當我嘗試調用指令時,我收到操作數非法的消息。

與第二條指令C.ADDI16SP ,唯一不同的是數字應按 16 縮放。 這些是手冊中指令的說明:

C.ADDI16SP 將非零符號擴展的 6 位立即數添加到堆棧指針 (sp=x2) 中的值,其中立即數被縮放以表示范圍 (-512,496) 中 16 的倍數。

C.ADDI4SPN 是一條 CIW 格式的 RV32C/RV64C 指令,它向堆棧指針 x2 添加一個零擴展非零立即數,按 4 縮放,並將結果寫入 rd0

這些是我如何嘗試使用說明的示例:

c.addi16sp 32
c.addi4spn x10, 8

從倒退開始(並了解裝配是特定於工具的而非目標)。

.hword 0x110c

   0:   110c                    addi    x11,x2,160

然后再試試

.hword 0x110c
addi    x11,x2,160
addi    x12,x2,160
addi    x13,x2,160
addi    x14,x2,160
addi    x14,x2,40
addi    x14,x2,4

00000000 <.text>:
   0:   110c                    addi    x11,x2,160
   2:   110c                    addi    x11,x2,160
   4:   1110                    addi    x12,x2,160
   6:   1114                    addi    x13,x2,160
   8:   1118                    addi    x14,x2,160
   a:   1038                    addi    x14,x2,40
   c:   0058                    addi    x14,x2,4

該指令用於生成指向堆棧分配變量的指針,並擴展為 addi rd ′ , x2, nzuimm。

這是通過 gnu 匯編程序和 binutils 的 objdump 完成的。

看來您需要一個四的倍數的立即數:

addi    x14,x2,4
addi    x14,x2,5
addi    x14,x2,6
addi    x14,x2,7
addi    x14,x2,8

00000000 <.text>:
   0:   0058                addi    x14,x2,4
   2:   00510713            addi    x14,x2,5
   6:   00610713            addi    x14,x2,6
   a:   00710713            addi    x14,x2,7
   e:   0038                addi    x14,x2,8

讓它優化到這個指令。

似乎由於某種原因我不知道,我們必須在使用這些指令時命名sp寄存器:

c.addi4sp, x10, sp, 8
c.addi16sp sp, 16

這可能是為了與未壓縮指令擴展保持一致,您還必須命名sp

然而,雖然有些人可能將此視為一項功能,但其他人(例如我自己)更可能將此視為錯誤或奇怪,因為可能不需要隱式寄存器(您永遠無法更改)以匯編形式——顯式使用壓縮操作碼時。

基本指令集(即無壓縮)沒有隱式寄存器——從機器代碼的角度來看——所有操作數都在機器指令中指定。

某些匯編助記符允許省略寄存器,然后在生成機器代碼時由匯編程序填充:例如jalret (偽指令)不允許或要求匯編程序命名寄存器但這些指令的機器代碼有一個rd / rs1寄存器字段(分別)由匯編程序用x1 / ra填充。

要使用c.lwsp ,我們還指定了sp寄存器,因此它看起來非常像一條lw指令。 從機器代碼的角度來看, c.jal看起來就像假設x1作為鏈接寄存器的jal偽指令——即使c.jal x1硬編碼為隱式目標寄存器,而jal的翻譯沒有。

所以,我猜他們想要的是與未壓縮指令匯編形式的最大兼容性。 而且我想這會使反匯編更可口,因為它無法判斷您最初使用的是壓縮操作碼還是匯編器壓縮指令(盡管我不確定使用未壓縮但顯示壓縮指令的反匯編是否值得可壓縮形式)。


測試:

.text
c.addi4spn a0, sp, 8  # compressed instruction, must name sp
addi a0, sp, 8        # non-compressed instruction, gets compressed to c.addi4spn

c.addi16sp sp, 16     # compressed instruction, must name sp
addi sp, sp, 16       # non-compressed instruction, gets compressed to c.addi

c.addi16sp sp, 128    # compressed instruction, must name sp
addi sp, sp, 128      # non-compressed instruction, gets compressed to c.addi16sp

Disassembly of section .text:

00000000 <.text>:
   0:   0028                    addi    a0,sp,8    # c.addi4spn
   2:   0028                    addi    a0,sp,8    # c.addi4spn
   4:   6141                    addi    sp,sp,16   # c.addi16sp
   6:   0141                    addi    sp,sp,16   # c.addi
   8:   6109                    addi    sp,sp,128  # c.addi16sp
   a:   6109                    addi    sp,sp,128  # c.addi16sp

正如您所看到的,反匯編程序假定您使用(或希望看到)非壓縮指令語法,即使匯編程序可能已或可能沒有將這些轉換為它們的壓縮等價物。

正如@Erik Eidt 所提到的,您必須命名 sp 寄存器。
這個選擇是在 riscv-opc.c 中做出的。
https://github.com/riscv/riscv-binutils-gdb/blob/riscv-binutils-2.35/opcodes/riscv-opc.c
如果你看一下,你有這兩個定義:

{"c.addi4spn", 0, INSN_CLASS_C,   "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, 0 },
{"c.addi16sp", 0, INSN_CLASS_C,   "Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, 0 },

Ct Cc CK 和 CL 是操作數:
Ct : /* RS2 x8-x15 */
抄送: sp (這就是為什么你需要 sp )。
RVC_ADDI4SPN_IMM 和 RVC_ADDI16SP_IMM 的 CK 和 CL。

在 objdump 中有 addi 的原因是:

{"addi",        0, INSN_CLASS_C,   "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },

{"addi",        0, INSN_CLASS_C,   "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS },

由於它們是在前一個之前聲明的,因此 objdump 匹配一個 addi。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM