【问题标题】:How to use C.ADDI4SPN and C.ADDI16SP instructions (compressed subset) of RISC-V architecture?如何使用 RISC-V 架构的 C.ADDI4SPN 和 C.ADDI16SP 指令(压缩子集)?
【发布时间】:2020-08-31 16:21:05
【问题描述】:

我不知道如何以正确的方式调用这两条指令。第一条指令C.ADDI4SPN 的第一个操作数应该是一个寄存器,第二个,如果我是对的,应该是一个 4 倍数。

但是当我尝试调用指令时,我收到操作数非法的消息。

第二条指令C.ADDI16SP也是一样,唯一的区别是数字应该是16。 这些是手册中的说明说明:

C.ADDI16SP 添加 堆栈指针 (sp=x2) 中值的非零符号扩展 6 位立即数,其中 立即缩放以表示范围 (-512,496) 中 16 的倍数。

C.ADDI4SPN 是 CIW 格式的 RV32C/RV64C-only 指令,它添加了一个零扩展的非零 立即,缩放 4,到堆栈指针 x2,并将结果写入 rd0

这些是我尝试使用说明的示例:

c.addi16sp 32
c.addi4spn x10, 8

【问题讨论】:

    标签: assembly riscv instructions operands


    【解决方案1】:

    似乎出于某种我不知道的原因,我们在使用这些指令时必须命名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.jalx1 硬编码为隐式目标寄存器,而jal 的翻译没有——从机器代码的角度来看。

    所以,我猜他们的目的是最大限度地兼容未压缩的指令汇编形式。而且我想这会使反汇编更加可口,因为它无法判断您最初是使用压缩操作码还是使用压缩指令的汇编程序(尽管我不确定使用未压缩但显示压缩指令的反汇编是否值得可压缩形式)。


    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
    

    如您所见,反汇编程序假定您使用(或希望看到)非压缩指令语法,即使汇编程序可能已将这些指令转换为压缩等效项,也可能没有。

    【讨论】:

      【解决方案2】:

      从倒退开始(并了解程序集是特定于工具的,而不是目标)。

      .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
      

      让它优化到这个指令中。

      【讨论】:

        【解决方案3】:

        正如@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。

        【讨论】:

          猜你喜欢
          • 2023-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-01
          • 2018-11-22
          • 2023-03-22
          • 2020-12-09
          • 1970-01-01
          相关资源
          最近更新 更多