简体   繁体   English

如何使用RISC-V架构的C.ADDI4SPN和C.ADDI16SP指令(压缩子集)?

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

I can't figure out how to call these two instructions in a proper way.我不知道如何以正确的方式调用这两个指令。 The first operand of the first instruction C.ADDI4SPN should be a register, and the second one, if I'm right, should be a number which is scaled by 4.第一条指令C.ADDI4SPN的第一个操作数应该是一个寄存器,第二个,如果我是对的,应该是一个按 4 缩放的数字。

But when I try to call the instruction I get the message that the operands are illegal.但是当我尝试调用指令时,我收到操作数非法的消息。

The same thing is with the second instruction C.ADDI16SP , the only difference is that the number should be scaled by 16. These are the descriptions of the instructions in the manual:与第二条指令C.ADDI16SP ,唯一不同的是数字应按 16 缩放。 这些是手册中指令的说明:

C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). C.ADDI16SP 将非零符号扩展的 6 位立即数添加到堆栈指针 (sp=x2) 中的值,其中立即数被缩放以表示范围 (-512,496) 中 16 的倍数。

C.ADDI4SPN is a CIW-format RV32C/RV64C-only instruction that adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd0 C.ADDI4SPN 是一条 CIW 格式的 RV32C/RV64C 指令,它向堆栈指针 x2 添加一个零扩展非零立即数,按 4 缩放,并将结果写入 rd0

These are the examples of how I attempt to use the instructions:这些是我如何尝试使用说明的示例:

c.addi16sp 32
c.addi4spn x10, 8

Start by going backward (and understand that assembly is tool specific not target).从倒退开始(并了解装配是特定于工具的而非目标)。

.hword 0x110c

   0:   110c                    addi    x11,x2,160

Then try some more然后再试试

.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

This instruction is used to generate pointers to stack-allocated variables, and expands to addi rd ′ , x2, nzuimm.该指令用于生成指向堆栈分配变量的指针,并扩展为 addi rd ′ , x2, nzuimm。

This was done with gnu assembler, and objdump from binutils.这是通过 gnu 汇编程序和 binutils 的 objdump 完成的。

It appears you need an immediate that is a multiple of four:看来您需要一个四的倍数的立即数:

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

to get it to optimize into this instruction.让它优化到这个指令。

It seems that for some reason I don't know, that we have to name the sp register when using these instructions:似乎由于某种原因我不知道,我们必须在使用这些指令时命名sp寄存器:

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

It is possible that this is for consistency with the uncompressed instruction expansion, where you also have to name sp .这可能是为了与未压缩指令扩展保持一致,您还必须命名sp

However, while some might count this as a feature, others (such as myself) more likely to count this as a bug or an oddity at best, because an implicit register (that you can't ever change) probably shouldn't be required in the assembly form — when explicitly using the compressed opcode.然而,虽然有些人可能将此视为一项功能,但其他人(例如我自己)更可能将此视为错误或奇怪,因为可能不需要隐式寄存器(您永远无法更改)以汇编形式——显式使用压缩操作码时。

The base instruction set (ie sans compression) has no implicit registers — from the machine code perspective — all operands are specified in the machine instruction.基本指令集(即无压缩)没有隐式寄存器——从机器代码的角度来看——所有操作数都在机器指令中指定。

Certain assembly mnemonics allow omitting the register, which is then filled in by the assembler in generating the machine code: jal and ret (pseudo instructions) for example do not allow or require the assembly program to name a register yet the machine code for these instructions has an rd / rs1 register field (respectively) filled in with x1 / ra by the assembler.某些汇编助记符允许省略寄存器,然后在生成机器代码时由汇编程序填充:例如jalret (伪指令)不允许或要求汇编程序命名寄存器但这些指令的机器代码有一个rd / rs1寄存器字段(分别)由汇编程序用x1 / ra填充。

To use c.lwsp , we also specify the sp register, so it looks very much like an lw instruction.要使用c.lwsp ,我们还指定了sp寄存器,因此它看起来非常像一条lw指令。 And c.jal looks just like the jal pseudo instruction in assuming x1 as the link register — even though c.jal does hard code x1 as an implicit target register, while jal 's translation does not — from the machine code perspective.从机器代码的角度来看, c.jal看起来就像假设x1作为链接寄存器的jal伪指令——即使c.jal x1硬编码为隐式目标寄存器,而jal的翻译没有。

So, I guess what they're going for is maximum compatibility with the uncompressed instructions assembly forms.所以,我猜他们想要的是与未压缩指令汇编形式的最大兼容性。 And I guess that makes the disassembly a bit more palatable, since it cannot tell whether you originally used a compressed opcode vs. the assembler compressing the instruction (though I'm not sure how worthwhile it is to show disassembly of compressed instructions using uncompressed but compressible forms).而且我想这会使反汇编更可口,因为它无法判断您最初使用的是压缩操作码还是汇编器压缩指令(尽管我不确定使用未压缩但显示压缩指令的反汇编是否值得可压缩形式)。


test.s:测试:

.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

As you can see the disassembler assumes you used (or want to see) non-compressed instruction syntax even though the assembler may or may not have converted these to their compressed equivalents.正如您所看到的,反汇编程序假定您使用(或希望看到)非压缩指令语法,即使汇编程序可能已或可能没有将这些转换为它们的压缩等价物。

As mentioned by @Erik Eidt you have to name the sp register.正如@Erik Eidt 所提到的,您必须命名 sp 寄存器。
This choice was made in riscv-opc.c.这个选择是在 riscv-opc.c 中做出的。
https://github.com/riscv/riscv-binutils-gdb/blob/riscv-binutils-2.35/opcodes/riscv-opc.c https://github.com/riscv/riscv-binutils-gdb/blob/riscv-binutils-2.35/opcodes/riscv-opc.c
If you take a look you have these two definitions:如果你看一下,你有这两个定义:

{"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 and CL are the operands: Ct Cc CK 和 CL 是操作数:
Ct : /* RS2 x8-x15 */ Ct : /* RS2 x8-x15 */
Cc : sp ( this is why you need the sp ).抄送: sp (这就是为什么你需要 sp )。
CK and CL for the RVC_ADDI4SPN_IMM and RVC_ADDI16SP_IMM. RVC_ADDI4SPN_IMM 和 RVC_ADDI16SP_IMM 的 CK 和 CL。

The reason why you have addi in the objdump is because :在 objdump 中有 addi 的原因是:

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

and

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

Since they are declared before the previous ones , the objdump match an addi.由于它们是在前一个之前声明的,因此 objdump 匹配一个 addi。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM