Comment 4 for bug 1821444

Revision history for this message
Sergei Trofimovich (trofi) wrote :

A bit more investigation:

It looks like the bug happens in float->double conversion direction.

$ cat a.c
#include <stdio.h>
#include <stdint.h>

int main() {
    volatile uint32_t i = 1;
    volatile float f;
    volatile double d;
    *(volatile uint32_t*)&f = i;
    d = f;
    printf("d = %#llx (expect 0x36a0000000000000)\n", *(volatile uint64_t*)&d);
}

$ powerpc-unknown-linux-gnu-gcc -O2 a.c -Wall -o a -fno-strict-aliasing -fno-stack-protector -static && qemu-ppc ./a
d = 0x36b0000000080000 (expect 0x36a0000000000000)

10000400 <main>:
10000404: 39 20 00 01 li r9,1
...
10000434: 91 21 00 10 stw r9,16(r1)
...
1000043c: c0 01 00 10 lfs f0,16(r1)
10000440: d8 01 00 08 stfd f0,8(r1)
...
10000448: 80 a1 00 08 lwz r5,8(r1)
1000044c: 80 c1 00 0c lwz r6,12(r1)
...
10000454: 48 02 01 ad bl 10020600 <___printf_chk>

This is just lfs/stfd conversion. qemu does translates that pair if instructions into:
$ ppc-linux-user/qemu-ppc -d in_asm,out_asm,op,op_opt /tmp/b/a
...
IN: main
...
0x1000043c: c0010010 lfs f0, 0x10(r1)
0x10000440: d8010008 stfd f0, 8(r1)
...
OP:
 ---- 1000043c
 movi_i32 tmp1,$0x10
 add_i32 tmp0,r1,tmp1
 qemu_ld_i32 tmp1,tmp0,beul,2
 call todouble,$0x5,$1,tmp2,tmp1
 st_i64 tmp2,env,$0x9198

'todouble' must be a 'uint64_t helper_todouble(uint32_t arg=0x1)' from:
    https://github.com/qemu/qemu/blob/master/target/ppc/fpu_helper.c#L55