[RISCV] 一些关于-march、-mabi 和-mtune的发现

本文讨论了RISC-V工具链中ISA(指令集架构)和ABI(应用程序二进制接口)的选择,强调了配置选项的区别,如-march和-mabi,以及它们在代码生成和兼容性上的影响。同时提到了浮点代码生成的不同策略和特定场景下的优化可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The only build-time differences between the various RISC-V toolchain configure options are what the defaults are, all toolchains support all targets. C libraries must be built to target each ISA and ABI variant you’re interested in, you can see an example of how we’re doing that in riscv-gnu-toolchain.

各种 RISC-V 工具链配置选项之间唯一的构建时差异是默认值,所有工具链都支持所有目标。 必须构建 C 库来针对您感兴趣的每个 ISA 和 ABI 变体,您可以在 riscv-gnu-toolchain 中查看我们如何做到这一点的示例。

-m32/-m64 are gone from RISC-V gcc/binutils, they’re unnecessary because of -march. Whatever documentation they’re in is wrong, if you can give me a pointer I’ll fix it.

-m32/-m64 已从 RISC-V gcc/binutils 中消失,由于 -march,它们不再需要。 无论它们所在的文档是错误的,如果您能给我一个指示,我会修复它。

-march=ISA controls the targeted ISA, using a lower case RISC-V ISA string name (for example, “rv64ic”). This controls what instructions the compiler generates and the assembler accepts. You’re allowed to link together to objects that were produced with different “-march” values.

-march=ISA 使用小写 RISC-V ISA 字符串名称(例如“rv64ic”)控制目标 ISA。 这控制编译器生成和汇编器接受的指令。 您可以将使用不同“-march”值生成的对象链接在一起。

-mabi=ABI controls the targeted ABI, using an ABI string (for example “ilp32d”). ABI strings look like the standard way to describe ABIs (ie ilp32 means Integer, Long, and Pointer are 32 bits; while lp64 means Long and Pointer are 64-bits) but with an addition letter describing the largest supported floating-point mode (f, d, or q). ABI strings control how C types exist in memory, and therefor it is illegal to link together two objects of different ABIs.

-mabi=ABI 使用 ABI 字符串(例如“ilp32d”)控制目标 ABI。 ABI 字符串看起来像描述 ABI 的标准方式(即“ilp32”表示整数、长整型和指针是 32 位;而“lp64”表示长整型和指针是 64 位),但带有一个附加字母来描述支持的最大浮点数 点模式(f、d 或 q)。 ABI 字符串控制 C 类型在内存中的存在方式,因此将不同 ABI 的两个对象链接在一起是非法的。

-mtune=UARCH controls performance-sensitive code generation for a target microarchitecture, but doesn’t have any correctness impact. Right now I think we only support generic, but there might still be a rocket tuning in there as well.

-mtune=UARCH 控制目标微架构的性能敏感代码生成,但不会产生任何正确性影响。 现在我认为我们只支持“通用”,但那里可能仍然有“火箭”调整。

At least some of the problems here are due to march/mabi mismatches – it looks like you’re requested “-mabi=lp64d” code with “-march=rv32im”. This is impossible, as the “lp64d” ABI says that 64-bit integer/pointer types are passed in X registers (which is impossible when xlen=32), and that single+double are passed in F registers (which is impossible when flen=0).

至少这里的一些问题是由于 March/mabi 不匹配造成的——看起来你需要“-mabi=lp64d”代码和“-march=rv32im”。 这是不可能的,因为“lp64d”ABI 表示 64 位整数/指针类型在 X 寄存器中传递(当 xlen=32 时这是不可能的),而 single+double 在 F 寄存器中传递(当 flen 时这是不可能的) =0)。


The reason it’s done this way is that “hard float” and “soft float” are a bit ambiguous: does the “hard” refer to the ABI constraint or the instruction constraint? There’s actually four options for floating-point code generation:

这样做的原因是“硬浮点”和“软浮点”有点含糊:“硬”是指ABI约束还是指令约束? 实际上有四种浮点代码生成选项:

  • “-march=rv64id -mabi=lp64d”: FP types are passed in F registers, and FP operations are done using explicit floating-point instructions. This coresponds to ARM’s “-mfloat-abi=hard”.

“-march=rv64id -mabi=lp64d”:FP类型在F寄存器中传递,FP操作使用显式浮点指令完成。 这对应于 ARM 的“-mfloat-abi=hard”。

  • “-march=rv64i -mabi=lp64d”: FP types are passed in F registers, but FP operations are done using a software floating-point implementation. This doesn’t make any sense, as on RISC-V you must implement the floating-point instructions if you have F registers. Thus the toolchain explicitly disallows this option – though we could always allow it in the future, if someone has a compelling reason to do so.

“-march=rv64i -mabi=lp64d”:FP 类型在 F 寄存器中传递,但 FP 操作是使用软件浮点实现完成的。 这没有任何意义,因为在 RISC-V 上,如果有 F 寄存器,则必须实现浮点指令。 因此,工具链明确不允许这个选项——尽管我们将来总是可以允许它,如果有人有令人信服的理由这样做的话。

  • “-march=rv64id -mabi=lp64”: FP types are passed in X registers, but FP operations are done using explicit floating-point instructions. This cooresponds to ARM’s “-mfloat-abi=softfp”, a silly name.
  • “-march=rv64id -mabi=lp64”:FP 类型在 X 寄存器中传递,但 FP 操作是使用显式浮点指令完成的。 这对应于 ARM 的“-mfloat-abi=softfp”,一个愚蠢的名字。
  • “-march=rv64i -mabi=lp64”: FP types are passed in X registers, and FP operations are done using a software floating-point implementation. This cooresponds to ARM’s “-mfloat-abi=soft”.
  • “-march=rv64i -mabi=lp64”:FP 类型在 X 寄存器中传递,并且 FP 操作使用软件浮点实现来完成。 这对应于 ARM 的“-mfloat-abi=soft”。

You’re more than welcome to implement whatever microarchitecture you want, if it executes all the RISC-V instructions then it’ll run code our toolchain generates. Specifically as to your “CPU that use the integer register file to feed the FPU” seems possible: if you’re building a machine with register renaming that shares the physical register file between X and F registers then you could perform some renaming tricks to make fmv.x.d and friends just copy physical register IDs instead of copying data. Optimizing a high-performance machine for “-march=rv64i -mabi=lp64d” performance seems like a bad place to spend your time, but in this case it might come for free from eliding all other copy instructions so maybe it’s worth it.

我们非常欢迎您实现您想要的任何微架构,如果它执行所有 RISC-V 指令,那么它将运行我们的工具链生成的代码。 具体来说,您的“使用整数寄存器文件来馈送 FPU 的 CPU”似乎是可能的:如果您正在构建一台具有寄存器重命名功能的机器,该机器在 X 和 F 寄存器之间共享物理寄存器文件,那么您可以执行一些重命名技巧来使 fmv.x.d 和朋友只是复制物理寄存器 ID,而不是复制数据。 优化高性能机器以获得“-march=rv64i -mabi=lp64d”性能似乎是一个不好的地方,但在这种情况下,它可能会免费消除所有其他复制指令,所以也许这是值得的。

### 工具链 `gcc-riscv64-linux-gnu` 的使用教程 #### 一、工具链概述 `gcc-riscv64-linux-gnu` 是一种用于 Linux 环境下的 RISC-V 架构交叉编译器。它主要用于为目标平台为运行 Linux 操作系统的 RISC-V 处理器生成可执行文件或库文件。该工具链属于适用于 Linux 环境的交叉编译工具链[^4]。 --- #### 二、安装方法 在 Ubuntu 上可以通过包管理工具直接安装此工具链,具体命令如下: ```bash sudo apt update sudo apt install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu binutils-riscv64-linux-gnu ``` 上述命令会安装以下组件: - `gcc-riscv64-linux-gnu`: C 编译器。 - `g++-riscv64-linux-gnu`: C++ 编译器。 - `binutils-riscv64-linux-gnu`: 提供链接器 (`ld`) 汇编器 (`as`) 等工具。 完成安装后,可以验证版本号以确认安装成功: ```bash riscv64-linux-gnu-gcc --version ``` --- #### 三、基本使用示例 ##### 1. 创建简单的 C 文件 创建一个名为 `hello_world.c` 的简单程序: ```c #include <stdio.h> int main() { printf("Hello, RISC-V!\n"); return 0; } ``` ##### 2. 使用工具链编译 通过 `gcc-riscv64-linux-gnu` 对源码进行编译并生成目标文件: ```bash riscv64-linux-gnu-gcc -o hello_world hello_world.c ``` 这一步骤将生成一个名为 `hello_world` 的可执行文件,专为基于 Linux 的 RISC-V 平台设计。 ##### 3. 验证生成的目标文件架构 为了确认生成的文件是否针对 RISC-V 架构,可以使用 `file` 命令查看其属性: ```bash file hello_world ``` 预期输出应类似于以下内容: ``` hello_world: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1, for GNU/Linux 3.2.0, not stripped ``` --- #### 四、高级选项说明 以下是常用的编译参数及其作用: | 参数 | 描述 | |--------------------------|----------------------------------------------------------------------| | `-march=rv64gc` | 设置指令集架构为 RV64GC(通用扩展)。 | | `-mabi=lp64d` | 定义 ABI 类型为 LP64D(双精度浮点支持)。 | | `-static` | 将所有依赖项静态链接到最终的可执行文件中。 | | `-O2` | 启用优化级别 O2,平衡性能代码大小。 | 例如,在编译时指定特定的 ISA ABI: ```bash riscv64-linux-gnu-gcc -march=rv64gc -mabi=lp64d -o optimized_program program.c ``` --- #### 五、调试与分析 如果需要对生成的二进制文件进行调试,可以配合 GDB 调试器一起使用: ```bash riscv64-linux-gnu-gdb ./hello_world ``` 此外,还可以利用 `objdump` 查看反汇编后的机器码: ```bash riscv64-linux-gnu-objdump -d hello_world ``` --- ### 总结 以上展示了如何配置、安装以及使用 `gcc-riscv64-linux-gnu` 工具链来开发面向 RISC-V Linux 系统的应用程序。对于更复杂的场景,可以根据实际需求调整编译选项或引入其他辅助工具。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山猫Show

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值