c - GCC PowerPC 避免使用 float 的 .rodata 部分

标签 c gcc assembly floating-point powerpc

我正在编写 C 代码并为 PowerPC 架构编译它。也就是说 C 代码包含浮点变量常量,我想将其放在 .text 部分而不是 .rodata 中,因此函数代码是独立的。

问题是在 PowerPC 中,the only way to move a floating point value into a floating point register is by loading it from memory .这是一个指令集限制。

为了说服 GCC 帮助我,我尝试将 float 声明为 static const。没有不同。使用指针,结果相同。对函数使用 __attribute__((section(".text"))),结果相同,每个浮点变量单独:

error: myFloatConstant causes a section type conflict with myFunction

我还尝试通过 #pragma GCC push_options 禁用优化 #pragma GCC optimize("O0")#pragma GCC pop_options。再加上假装我有一个 unsigned int 有效:

unsigned int *myFloatConstant = (unsigned int *) (0x11000018);
*myFloatConstant = 0x4C000000;

使用 float :

float theActualFloat = *(float *) myFloatConstant;

我仍然想保留 -O3 但它再次使用 .rodata 因此可能的答案将包括 which optimization flag causes the floats to be placed in .rodata-O1 开始,这是怎么回事?

最好的情况是我可以在代码中“正常”使用 float 并进行最大程度的优化,并且它们根本不会放在 .rodata 中。

我想 GCC 可能做的是通过混合数据和代码将浮点常量放在代码之间,从那个地方加载到浮点寄存器并继续。我相信这可以手动编写,但是如何让 GCC 做到这一点?强制每个变量的属性会导致上述错误,但从技术上讲这应该是可行的。

最佳答案

使用 GCC 7.1.0 powerpc-eabi(Linux 下的交叉编译器)以下代码对我有效:

float test(void)
{
    int x;
    volatile float y;
    float theActualFloat;

    *(float *)&x = 1.2345f;
    *(int *)&y = x;
    theActualFloat = y;

    return theActualFloat;
}

生成的汇编代码:

test:
    stwu 1,-24(1)
    lis 9,0x3f9e
    ori 9,9,0x419
    stw 9,8(1)
    lfs 1,8(1)
    addi 1,1,24
    blr

解释:

*(float *)&x = value 行中,您写入一个将由编译器优化的整数。编译器将执行整数运算,该运算不会访问 .rodata 中的浮点值。

无论如何,*(int *)&y = x 行是一个纯整数运算。

由于 volatiletheActualFloat = y 行无法优化,因此编译器必须将整数写入堆栈上的变量,并且必须读取结果来自变量。

关于c - GCC PowerPC 避免使用 float 的 .rodata 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45770593/

相关文章:

c++ - execv() 关于参数的怪癖

c - struct_ 前缀与无前缀

c - 为什么 .bss 显式地将全局变量初始化为零?

c - 在目标文件中嵌入链接器依赖项?

c++ - 如何在 MacOS 上的 g++ 中使用 gcc 内置 __sync_bool_compare_and_swap?

assembly - 如何在 x86 汇编中捕获 Tab 按操作?

c++ - 长格式和多格式路径操作库?

c - 文件(尤其是音频文件)在内部是如何组织的?

linux - 查找海湾合作委员会位置

assembly - 他们说 "Arguments are pushed in the reverse order"是什么意思?