Re: Return value on MIPS N64 ABI

2016-06-20 Thread Heiher
Thank you.

On Mon, Jun 13, 2016 at 6:19 PM, Matthew Fortune
 wrote:
> Heiher  writes:
>> Looks the return value of TestNewA is passed on $f0/$f2 from disassembly
>> code.  I don't known why the return value of TestNewB is passed on
>> $v0/$v1? a bug?
>
> I believe this is an area where GNU strays from the N64 ABI definition but
> is defacto standard. TestA is a struct of two floating point fields which
> is passed and returned in FP registers. TestB is a struct of a struct of
> two floating point fields (or at least I think that is the interpretation).
>
> The ABI does say that this should be flattened and be seen as simply two
> floating point fields but GCC does not and passes it in integer registers
> instead. Or at least the ABI says this for arguments but not results.
>
> The relevant bit of the ABI we are not adhering to is 'Structs,unions' on
> page 7 which covers arguments, however the corresponding text for results
> does not include the part about ignoring the struct field structure
> when determining between floating point and integer chunks.
>
> https://dmz-portal.ba.imgtec.org/mw/images/6/6f/007-2816-005-1.pdf
>
> FWIW: Clang/LLVM ABI implementation matches GCC in this regard as we run
> cross linking tests and use GCC as 'correct'.
>
> Thanks,
> Matthew
>
>> 229 00012c40 <_Z8TestNewAv>:
>> 23012c40:   3c030002lui v1,0x2
>> 23112c44:   0079182ddaddu   v1,v1,t9
>> 23212c48:   64638400daddiu  v1,v1,-31744
>> 23312c4c:   dc628050ld  v0,-32688(v1)
>> 23412c50:   67bdffe0daddiu  sp,sp,-32
>> 23512c54:   d4400e68ldc1$f0,3688(v0)
>> 23612c58:   dc628050ld  v0,-32688(v1)
>> 23712c5c:   67bd0020daddiu  sp,sp,32
>> 23812c60:   03e8jr  ra
>> 23912c64:   d4420e70ldc1$f2,3696(v0)
>> 240
>> 241 00012c68 <_Z8TestNewBv>:
>> 24212c68:   3c0307f9lui v1,0x7f9
>> 24312c6c:   3c0207f7lui v0,0x7f7
>> 24412c70:   3463ori v1,v1,0x
>> 24512c74:   3442ori v0,v0,0x
>> 24612c78:   00031cb8dsllv1,v1,0x12
>> 24712c7c:   000214b8dsllv0,v0,0x12
>> 24812c80:   3463cccdori v1,v1,0xcccd
>> 24912c84:   3442cccdori v0,v0,0xcccd
>> 25012c88:   67bdfff0daddiu  sp,sp,-16
>> 25112c8c:   00031c78dsllv1,v1,0x11
>> 25212c90:   00021478dsllv0,v0,0x11
>> 25312c94:   6463999adaddiu  v1,v1,-26214
>> 25412c98:   6442999adaddiu  v0,v0,-26214
>> 25512c9c:   03e8jr  ra
>> 25612ca0:   67bd0010daddiu  sp,sp,16
>>
>> // test.cpp
>> // gcc -march=mips64r2 -mabi=64 -O3 -o test test.cpp #include 
>>
>> class TestA
>> {
>> public:
>> double l;
>> double h;
>>
>> TestA(double l, double h) : l(l), h(h) {} };
>>
>> class TestB : public TestA
>> {
>> public:
>> TestB(const TestA& a) : TestA(a) {} };
>>
>> TestA
>> TestNewA(void)
>> {
>> return TestA(0.1, 0.2);
>> }
>>
>> TestB
>> TestNewB(void)
>> {
>> return TestA(0.1, 0.2);
>> }
>>
>> int
>> main(int argch, char *argv[])
>> {
>> TestA a = TestNewA();
>> printf("%lf, %lf\n", a.l, a.h);
>>
>> TestB b = TestNewB();
>> printf("%lf, %lf\n", b.l, b.h);
>>
>> return 0;
>> }



-- 
Best regards!
Heiher
http://hev.cc


RE: Return value on MIPS N64 ABI

2016-06-13 Thread Matthew Fortune
Heiher  writes:
> Looks the return value of TestNewA is passed on $f0/$f2 from disassembly
> code.  I don't known why the return value of TestNewB is passed on
> $v0/$v1? a bug?

I believe this is an area where GNU strays from the N64 ABI definition but
is defacto standard. TestA is a struct of two floating point fields which
is passed and returned in FP registers. TestB is a struct of a struct of
two floating point fields (or at least I think that is the interpretation).

The ABI does say that this should be flattened and be seen as simply two
floating point fields but GCC does not and passes it in integer registers
instead. Or at least the ABI says this for arguments but not results.

The relevant bit of the ABI we are not adhering to is 'Structs,unions' on
page 7 which covers arguments, however the corresponding text for results
does not include the part about ignoring the struct field structure
when determining between floating point and integer chunks.

https://dmz-portal.ba.imgtec.org/mw/images/6/6f/007-2816-005-1.pdf

FWIW: Clang/LLVM ABI implementation matches GCC in this regard as we run
cross linking tests and use GCC as 'correct'.

Thanks,
Matthew

> 229 00012c40 <_Z8TestNewAv>:
> 23012c40:   3c030002lui v1,0x2
> 23112c44:   0079182ddaddu   v1,v1,t9
> 23212c48:   64638400daddiu  v1,v1,-31744
> 23312c4c:   dc628050ld  v0,-32688(v1)
> 23412c50:   67bdffe0daddiu  sp,sp,-32
> 23512c54:   d4400e68ldc1$f0,3688(v0)
> 23612c58:   dc628050ld  v0,-32688(v1)
> 23712c5c:   67bd0020daddiu  sp,sp,32
> 23812c60:   03e8jr  ra
> 23912c64:   d4420e70ldc1$f2,3696(v0)
> 240
> 241 00012c68 <_Z8TestNewBv>:
> 24212c68:   3c0307f9lui v1,0x7f9
> 24312c6c:   3c0207f7lui v0,0x7f7
> 24412c70:   3463ori v1,v1,0x
> 24512c74:   3442ori v0,v0,0x
> 24612c78:   00031cb8dsllv1,v1,0x12
> 24712c7c:   000214b8dsllv0,v0,0x12
> 24812c80:   3463cccdori v1,v1,0xcccd
> 24912c84:   3442cccdori v0,v0,0xcccd
> 25012c88:   67bdfff0daddiu  sp,sp,-16
> 25112c8c:   00031c78dsllv1,v1,0x11
> 25212c90:   00021478dsllv0,v0,0x11
> 25312c94:   6463999adaddiu  v1,v1,-26214
> 25412c98:   6442999adaddiu  v0,v0,-26214
> 25512c9c:   03e8jr  ra
> 25612ca0:   67bd0010daddiu  sp,sp,16
> 
> // test.cpp
> // gcc -march=mips64r2 -mabi=64 -O3 -o test test.cpp #include 
> 
> class TestA
> {
> public:
> double l;
> double h;
> 
> TestA(double l, double h) : l(l), h(h) {} };
> 
> class TestB : public TestA
> {
> public:
> TestB(const TestA& a) : TestA(a) {} };
> 
> TestA
> TestNewA(void)
> {
> return TestA(0.1, 0.2);
> }
> 
> TestB
> TestNewB(void)
> {
> return TestA(0.1, 0.2);
> }
> 
> int
> main(int argch, char *argv[])
> {
> TestA a = TestNewA();
> printf("%lf, %lf\n", a.l, a.h);
> 
> TestB b = TestNewB();
> printf("%lf, %lf\n", b.l, b.h);
> 
> return 0;
> }


Return value on MIPS N64 ABI

2016-06-13 Thread Heiher
Hi,

Looks the return value of TestNewA is passed on $f0/$f2 from
disassembly code.  I don't known why the return value of TestNewB is
passed on $v0/$v1? a bug?

229 00012c40 <_Z8TestNewAv>:
23012c40:   3c030002lui v1,0x2
23112c44:   0079182ddaddu   v1,v1,t9
23212c48:   64638400daddiu  v1,v1,-31744
23312c4c:   dc628050ld  v0,-32688(v1)
23412c50:   67bdffe0daddiu  sp,sp,-32
23512c54:   d4400e68ldc1$f0,3688(v0)
23612c58:   dc628050ld  v0,-32688(v1)
23712c5c:   67bd0020daddiu  sp,sp,32
23812c60:   03e8jr  ra
23912c64:   d4420e70ldc1$f2,3696(v0)
240
241 00012c68 <_Z8TestNewBv>:
24212c68:   3c0307f9lui v1,0x7f9
24312c6c:   3c0207f7lui v0,0x7f7
24412c70:   3463ori v1,v1,0x
24512c74:   3442ori v0,v0,0x
24612c78:   00031cb8dsllv1,v1,0x12
24712c7c:   000214b8dsllv0,v0,0x12
24812c80:   3463cccdori v1,v1,0xcccd
24912c84:   3442cccdori v0,v0,0xcccd
25012c88:   67bdfff0daddiu  sp,sp,-16
25112c8c:   00031c78dsllv1,v1,0x11
25212c90:   00021478dsllv0,v0,0x11
25312c94:   6463999adaddiu  v1,v1,-26214
25412c98:   6442999adaddiu  v0,v0,-26214
25512c9c:   03e8jr  ra
25612ca0:   67bd0010daddiu  sp,sp,16

// test.cpp
// gcc -march=mips64r2 -mabi=64 -O3 -o test test.cpp
#include 

class TestA
{
public:
double l;
double h;

TestA(double l, double h) : l(l), h(h) {}
};

class TestB : public TestA
{
public:
TestB(const TestA& a) : TestA(a) {}
};

TestA
TestNewA(void)
{
return TestA(0.1, 0.2);
}

TestB
TestNewB(void)
{
return TestA(0.1, 0.2);
}

int
main(int argch, char *argv[])
{
TestA a = TestNewA();
printf("%lf, %lf\n", a.l, a.h);

TestB b = TestNewB();
printf("%lf, %lf\n", b.l, b.h);

return 0;
}