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
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() { 000)\n" , *(volatile uint64_t*)&d);
volatile uint32_t i = 1;
volatile float f;
volatile double d;
*(volatile uint32_t*)&f = i;
d = f;
printf("d = %#llx (expect 0x36a0000000000
}
$ 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: user/qemu- ppc -d in_asm, out_asm, op,op_opt /tmp/b/a $0x5,$1, tmp2,tmp1
$ ppc-linux-
...
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,
st_i64 tmp2,env,$0x9198
'todouble' must be a 'uint64_t helper_ todouble( uint32_ t arg=0x1)' from: /github. com/qemu/ qemu/blob/ master/ target/ ppc/fpu_ helper. c#L55
https:/