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

问题描述

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

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

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

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

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

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

c.addi16sp 32
c.addi4spn x10,8

解决方法

首先回退(并了解程序集是特定于工具而不是目标)。

.hword 0x110c

   0:   110c                    addi    x11,x2,160

然后再尝试一些

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

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

此指令用于生成指向堆栈分配的变量的指针,并扩展为addi rd',x2,nzuimm。

这是通过gnu汇编器和binutils中的objdump完成的。

您似乎需要一个四倍的立即数:

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

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

将其优化为该指令。

,

由于某些原因,我不知道,在使用这些指令时,我们必须命名sp寄存器:

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

这可能是为了与未压缩的指令扩展保持一致,在此处您还必须命名为sp

但是,尽管有些人可能将此视为功能,但其他人(例如我自己)最多可能将其视为错误或奇怪之处,因为隐式寄存器(您永远都不能更改)可能不应该”显式使用压缩的操作码时,不需要以汇编形式。

从机器代码的角度来看,基本指令集(即无压缩)没有隐式寄存器-所有操作数都在机器指令中指定。

某些汇编助记符允许省略寄存器,然后由汇编程序在生成机器代码时填充该寄存器:jalret(伪指令),例如,不允许或不需要汇编程序命名一个寄存器,但这些指令的机器代码有一个rd / rs1寄存器字段,分别由汇编程序用x1 / ra填充。

要使用c.lwsp,我们还要指定sp寄存器,因此它看起来很像lw指令。并且c.jal看起来像jal伪指令,假设x1作为链接寄存器-尽管c.jal确实将硬编码x1作为隐式目标寄存器,从机器代码的角度来看,jal的翻译不是。

所以,我想他们想要的是与未压缩的指令汇编形式的最大兼容性。而且我猜想这使反汇编更加可口,因为它无法告诉您最初使用的是压缩操作码还是汇编指令压缩指令(尽管我不确定使用未压缩的指令显示反汇编的压缩指令是多么值得可压缩形式)。


test.s:

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

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

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

Disassembly of section .text:

00000000 <.text>:
   0:   0028                    addi    a0,8    # c.addi4spn
   2:   0028                    addi    a0,8    # c.addi4spn
   4:   6141                    addi    sp,16   # c.addi16sp
   6:   0141                    addi    sp,16   # c.addi
   8:   6109                    addi    sp,128  # c.addi16sp
   a:   6109                    addi    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",INSN_CLASS_C,"Ct,Cc,CK",MATCH_C_ADDI4SPN,MASK_C_ADDI4SPN,match_c_addi4spn,0 },{"c.addi16sp","Cc,CL",MATCH_C_ADDI16SP,MASK_C_ADDI16SP,match_c_addi16sp,

Ct Cc CK和CL是操作数:
Ct:/ * RS2 x8-x15 * /
抄送:sp(这就是为什么需要sp的原因)。
RVC_ADDI4SPN_IMM和RVC_ADDI16SP_IMM的CK和CL。

在objdump中添加addi的原因是:

{"addi",INSN_ALIAS },

{"addi",

由于它们是在前面的声明之前声明的,因此objdump匹配一个addi。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...