【发布时间】:2020-05-26 19:08:36
【问题描述】:
我正在为 ARM 处理器 (Cortex-A9) 编写操作系统。
我正在尝试实现浮点寄存器的惰性上下文切换。这背后的想法是,浮点扩展最初是为线程禁用的,因此不需要在任务切换上保存浮点上下文。
当线程尝试使用浮点指令时,它会触发异常。操作系统然后启用浮点扩展,并且知道必须在下一次上下文切换中为此线程保存浮点上下文。然后重新执行浮点指令。
我的问题是,即使在 c 代码中没有使用浮点运算,编译器也会生成浮点指令。 这是一个在 c 中不使用浮点的函数的反汇编示例:
10002f5c <rmtcpy_from>:
10002f5c: e1a0c00d mov ip, sp
10002f60: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
10002f64: e24cb004 sub fp, ip, #4
10002f68: ed2d8b02 vpush {d8}
...
10002f80: ee082a10 vmov s16, r2
...
10002fe0: ee180a10 vmov r0, s16
...
1000308c: ecbc8b02 vldmia ip!, {d8}
...
当我有很多这样的功能时,懒惰的上下文切换就没有意义了。
有人知道如何告诉编译器只有在c代码中有浮点运算时才应该生成浮点指令吗?
我使用 gcc 9.2.0。浮点选项为:-mhard-float -mfloat-abi=hard -mfpu=vfp
这里是一个例子c函数(不能用,只是demo):
void func(char *a1, char *a2, char *a3);
int bar_1[1], foo_1, foo_2;
void fpu_test() {
int oldest_idx = -1;
while (1) {
int *oldest = (int *)0;
int idx = oldest_idx;
for (int i = 0; i < 3; i++) {
if (++idx >= 3)
idx = 0;
int *lec = &bar_1[idx];
if (*lec) {
if (*lec - *oldest < 0) {
oldest = lec;
oldest_idx = idx;
}
}
}
if (oldest) {
foo_1++;
if (foo_2)
func("1", "2", "3");
}
}
}
gcc 命令行:
$HOME/devel/opt/cross-musl/bin/arm-linux-musleabihf-gcc -O2 -march=armv7-a -mtune=cortex-a9 -mhard-float -mfloat-abi=hard -mfpu=vfp -Wa,-ahlms=fpu_test.lst -mapcs-frame -c fpu_test.c -o fpu_test.o
汇编程序列表:
...
35 0000 0DC0A0E1 mov ip, sp
36 0004 003000E3 movw r3, #:lower16:foo_2
37 0008 F0DF2DE9 push {r4, r5, r6, r7, r8, r9, r10, fp, ip, lr, pc}
38 000c 006000E3 movw r6, #:lower16:foo_1
39 0010 003040E3 movt r3, #:upper16:foo_2
40 0014 04B04CE2 sub fp, ip, #4
41 0018 006040E3 movt r6, #:upper16:foo_1
42 001c 004000E3 movw r4, #:lower16:bar_1
43 0020 028B2DED vpush.64 {d8} <=== this is the problem
...
【问题讨论】:
-
所有这些选项都在告诉编译器为浮点构建,您是否有演示问题的示例/最小 C 函数和完整的 gcc 命令行(或足以演示问题)?
-
我用 gcc 命令行的示例 c 函数和汇编程序列表的一部分更新了我的帖子
-
-mapcs-frame 为所有函数生成一个符合 ARM 过程调用标准的堆栈帧,即使这对于正确执行代码并不是绝对必要的。使用此选项指定 -fomit-frame-pointer 会导致不为叶函数生成堆栈帧。默认值为 -mno-apcs-frame。此选项已弃用。
-
如果我删除它,那么这个推送就会消失(就像浪费寄存器的堆栈帧一样)
-
删除 -mapcs-frame 适用于简单功能。在我的项目中,vpush 指令的数量减少了,但它们仍然存在。
标签: gcc floating-point arm osdev