GCC PowerPC avoiding .rodata section for floats

I'm writing C code and compile it for the PowerPC architecture. That said C code contains floating point variable constants which I want to be placed in the .text section instead of .rodata so the function code is self-contained.

The problem with this is that in PowerPC , the only way to move a floating point value into a floating point register is by loading it from memory. It is an instruction set restriction.

To convince GCC to help me, I tried declaring the floats as static const . No difference. Using pointers, same results. Using __attribute__((section(".text"))) for the function, same results and for each floating point variable individually:

error: myFloatConstant causes a section type conflict with myFunction

I also tried disabling optimizations via #pragma GCC push_options #pragma GCC optimize("O0") and #pragma GCC pop_options . Plus pretending I have an unsigned int worked:

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

Using the float:

float theActualFloat = *(float *) myFloatConstant;

I still would like to keep -O3 but it again uses .rodata so a potential answer would include which optimization flag causes the floats to be placed in .rodata since starting from -O1 this is happening?

Best case scenario would be that I can use floats "normally" in the code plus maximum optimizations and they never get placed in .rodata at all.

What I imagine GCC to possibly do is placing the float constant in-between the code by mixing data and code, loading from that place into a floating point register and continue. This is possible to write manually I believe but how to make GCC do that? Forcing the attribute per variable causes the error from above but technically this should be feasible.


Using GCC 7.1.0 powerpc-eabi (cross compiler under Linux) the following code worked for me:

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

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

    return theActualFloat;
}

Resulting assembly code:

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

Explaination:

In the line *(float *)&x = value you write to an integer which will be optimized by the compiler. The compiler will perform an integer operation which does not access floating point values in .rodata .

The line *(int *)&y = x is a pure integer operation anyway.

The line theActualFloat = y cannot be optimized due to the volatile so the compiler has to write the integer to the variable on the stack and it has to read the result from the variable.


I found another solution which avoids stack frame creation and .rodata usage but requires an absolute memory address to store the float in:

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

    return pointer;
}

It is used like this:

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

It is important to not make a local float variable, only volatile pointers so it won't use .rodata again.

链接地址: http://www.djcxy.com/p/40268.html

上一篇: 如何安装Visual Studio 2017的旧版本?

下一篇: GCC PowerPC避免浮动的.rodata节