GCC PowerPC避免浮动的.rodata部分

时间:2017-08-19 10:45:42

标签: c gcc assembly floating-point powerpc

我正在编写C代码并为PowerPC架构编译它。那就是说C代码包含浮点变量常量,我想把它放在.text部分而不是.rodata中,所以函数代码是自包含的。

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

为了说服GCC帮助我,我尝试将浮动声明为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开始会发生这种情况?

最好的情况是我可以在代码中“正常”使用浮点数加上最大优化,但它们永远不会放在.rodata中。

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

2 个答案:

答案 0 :(得分:3)

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

clipsToBounds = true

产生的汇编代码:

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,行theActualFloat = y无法优化,因此编译器必须将整数写入堆栈中的变量,并且必须从变量中读取结果。

答案 1 :(得分:0)

我找到了另一种避免stack frame创建和.rodata使用的解决方案,但需要一个绝对内存地址来存储浮点数:

static inline volatile float *getFloatPointer(int address, float value) {
    float *pointer = (float *) address;
    *pointer = value;

    return pointer;
}

它的用法如下:

volatile float *myFloat = getFloatPointer(0x12345678, 30.f);
printf("%f", *myFloat);

重要的是不要制作本地float变量,只需volatile个指针,这样它就不会再次使用.rodata