[英]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
。
然而,雖然有些人可能將此視為一項功能,但其他人(例如我自己)更可能將此視為錯誤或奇怪,因為可能不需要隱式寄存器(您永遠無法更改)以匯編形式——顯式使用壓縮操作碼時。
基本指令集(即無壓縮)沒有隱式寄存器——從機器代碼的角度來看——所有操作數都在機器指令中指定。
某些匯編助記符允許省略寄存器,然后在生成機器代碼時由匯編程序填充:例如jal
和ret
(偽指令)不允許或要求匯編程序命名寄存器但這些指令的機器代碼有一個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.