qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] Specific use of lfs for loading int leads to wrong value


From: Pierre Mallard
Subject: Re: [Qemu-ppc] Specific use of lfs for loading int leads to wrong value in f register
Date: Fri, 12 Sep 2014 21:19:39 +0200

Hi Tom, 

Here is the C file that led to the sample assembly code seen :

##############################
float func()
{
   int a = 1023;
   return (float)a;
}
#############################

Running cross compiler from Xilinx SDK 14.7 :
powerpc-eabi-gcc -S -mcpu=440 -mfpu=sp_full -o asm.s -c asm.c

Leads to :

#############################
func:
        stwu 1,-40(1)
        stw 31,36(1)
        mr 31,1
        li 0,1023
        stw 0,8(31)
        lwz 0,8(31)
        stw 0,24(31)
        lfs 0,24(31)
        fcfid 0,0
        fmr 1,0
        lwz 11,0(1)
        lwz 31,-4(11)
        mr 1,11
        blr
##############################

So the clear goal of lfs and fcfid is to convert an int32 to a float. While the documentation of Xilinx (http://www.xilinx.com/support/documentation/ip_documentation/apu_fpu_virtex5.pdf) is quite explicit on how they shall act in single precision mode, (mode which is defined by hardware design configuration), the test leads to 0 also on their platform (maybe the low 32 bit of your result).

Therefore I think either gcc's Xilinx patch is not correct to perform type cast with lfs, or there is an error in the hardware test I made and Xilinx support this converison. I will post at Xilinx forum, and if this behavior is really confirmed by Xilinx (lfs + fcfid) I will come back to you, but anyway we might stick with double precision in our design :D !

Pierre



Pierre Mallard
SILICOM Grand Sud Ouest
05 34 60 57 59
12 rue Caulet
31300 Toulouse


On Fri, Sep 12, 2014 at 3:48 PM, Tom Musta <address@hidden> wrote:
On 9/12/2014 2:07 AM, Pierre Mallard wrote:
> Hi,
>
> In simple float precision mode the xilinx ppc 440 's gcc (with sp_full flag) will do cast between int and float as follow :
>
> #Cast of 1023 in float
> li      r0,1023
> stw  r0,24(r31)
> lfs    f0,24(r31) #Load int "as is" in a float register
> fcfid f0,f0          #Convert to float in place
>
> Running qemu leads to a f0 register equal to 0 before the fcfid takes place.
>

I'm not sure that I understand the instruction sequence to be a valid way to cast.  Or perhaps I don't understand what you mean by "simple float precision mode".

The first two instructions result in the value 0x000003FF being written into memory.  The third instruction (lfs) loads that word as a single precision number.  But since PowerPC FPRs are always double precision format, there is an inherent conversion to
DP.  The word in question is a denormalized single precision number and results in F0 containing the value 373FF80000000000. (see Book I, Section 4.6.2 Floating Point Load Instructions).  The fcfid then interprets this data as two's complement integer and
converts to double precision floating point.  The result is 0x43CB9FFC00000000 = 3.981173e+18.

QEMU gets the same answer as Power7 hardware for the above sequence.

Here is my test in case you can see something that I did incorrectly:

#include <stdint.h>
#include <stdio.h>

void cast(uint32_t *buffer, uint64_t *value)
{
    asm volatile(
        "li 0,1023 \n"
        "stw 0,0(3) \n"
        "lfs 0,0(3) \n"
        "fcfid 0,0 \n"
        "stfd 0,0(4) \n"
        );
}

int main(int argc, char** argv)
{
    uint32_t buffer = 0;
    uint64_t value = 0;

    cast(&buffer, &value);
    printf("%016llx -> %e\n", value, *((double *)&value));
}


> While the overall cast is not a standard approach since fcfid is not meant to work on simple float precision, I would be interested in making things work on qemu.
>
> As far as I understand the code in qemu, the lfs implementation loads memory (as if destination was a 32bit) and cast it from FLOAT 32 bits to FLOAT 64 bits, allowing further computation. This works well for loading float but not in my case where lfs is
> used to load an integer.
> As far as I can imagine, the PPC itself would load the integer 32 bits without any cast and would perform the cast with fcfid from int32 to float32 in place (yes I know this is not standard).
>
> I don't see anyway to emulates this behavior in Qemu since making things work for lfs + fcfid, i.e. by not attempting to cast to float 64 in gen_qemu_ld32fs, would break a simple floating point load from memory (because this one would need an internal cast
> in 64 bits for further operation).
>
> Any idea are welcome !
>
> Pierre
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]