gpt4 book ai didi

c++ - C++函数调用到RISC-V系统调用

转载 作者:行者123 更新时间:2023-12-02 09:54:48 27 4
gpt4 key购买 nike

我有一个奇怪的情况,似乎对我来说很好,但是我需要知道如何使它变得更好或如何生活。

我正在使用C++作为游戏引擎的编译脚本语言。 RISC-V系统调用ABI与C函数调用约定相同,不同之处在于,系统调用号使用A7代替第8个整数或指针参数。是的,你知道这是怎么回事。看哪:

extern "C" long syscall_enter(...);

template <typename... Args>
inline long syscall(long syscall_n, Args&&... args)
{
asm volatile ("li a7, %0" : : "i"(syscall_n));
return syscall_enter(std::forward<Args>(args)...);
}

而syscall_enter只是.text中带有syscall指令和ret的符号。系统调用返回值也与普通函数返回相同。
000103f0 <syscall_enter>:
syscall_enter():
103f0: 00000073 ecall
103f4: 00008067 ret

在此之前,我必须创建20多个函数来涵盖使用整数和带有编译器屏障的指针进行系统调用的所有各种方式,并且当我想添加带有浮点值的函数时,会说该调用很模糊整数和浮点数可以来回转换。因此,我可以开始向函数添加唯一的名称,或者只是以更好的方式解决此问题。老实说,这很烦人,并给原本出色的体验加了阻尼器。我真的很喜欢能够同时使用C++。

编译器生成的指令似乎还不错。它是JAL和JALR syscall_enter,这很好。编译器似乎有些困惑,但是我不介意增加一条指令。
   10204:       1f500793                li      a5,501
10208: 00078893 mv a7,a5
1020c: 00000513 li a0,0
10210: 1e0000ef jal ra,103f0 <syscall_enter>

以及中央摄像头的位置:
   100d4:       19600793                li      a5,406
100d8: 00078893 mv a7,a5
100dc: 000127b7 lui a5,0x12
100e0: 4207b587 fld fa1,1056(a5) # 12420 <_exit+0x2308>
100e4: 22b58553 fmv.d fa0,fa1
100e8: 010000ef jal ra,100f8 <syscall_enter>

再次增加一条移动指令。看起来不错。该API已经被大量使用,并且还有一个与此相关的线程API。

现在,还有更好的方法吗?我想不出一种更好的方法来用数字加载a7,然后强制编译器设置函数调用,而不进行实际的函数调用。我当时正在考虑使用模板参数作为系统电话号码,但其余部分我不太确定。也许我们可以将参数数量限制为7?当存在整数和浮点参数时,这将是不正确的,但这很好。堆栈存储的结构易于传递。

经过一些测试,我决定使用此:
extern "C" long syscall_enter(...);

template <typename... Args>
inline long syscall(long syscall_n, Args&&... args)
{
// This will prevent some cases of too many arguments,
// but not a mix of float and integral arguments.
static_assert(sizeof...(args) < 8, "There is a system call limit of 8 integer arguments");
// The memory clobbering prevents reordering of a7
asm volatile ("li a7, %0" : : "i"(syscall_n) : "a7", "memory");
return syscall_enter(std::forward<Args>(args)...);
asm volatile("" : : : "memory");
}

应该足够了。不需要syscall函数发送垃圾邮件。检查计数参数不是最佳方法,因为它只能阻止使用第8个整数寄存器(这意味着对整数,指针和引用参数进行计数)。但这可以防止某些情况。

最佳答案

这有两个问题。

首先是您没有告诉编译器您正在使用a7,因此它可能会尝试在其中放置其他内容,从而导致代码不正确。您需要将a7添加到asm的clobbers列表中:

asm volatile ("mv a7, %0" : : "r"(syscall_n) : "a7");

第二个问题是asm语句未连接到调用,因此编译器可能会重新排序,特别是在asm mv指令和调用之间移动其他代码。如果发生这种情况,并且相关代码修改了a7,您将最终调用错误的syscall。

关于c++ - C++函数调用到RISC-V系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61147779/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com