Heiher <ad...@heiher.info> 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 0000000120000c40 <_Z8TestNewAv>: > 230 120000c40: 3c030002 lui v1,0x2 > 231 120000c44: 0079182d daddu v1,v1,t9 > 232 120000c48: 64638400 daddiu v1,v1,-31744 > 233 120000c4c: dc628050 ld v0,-32688(v1) > 234 120000c50: 67bdffe0 daddiu sp,sp,-32 > 235 120000c54: d4400e68 ldc1 $f0,3688(v0) > 236 120000c58: dc628050 ld v0,-32688(v1) > 237 120000c5c: 67bd0020 daddiu sp,sp,32 > 238 120000c60: 03e00008 jr ra > 239 120000c64: d4420e70 ldc1 $f2,3696(v0) > 240 > 241 0000000120000c68 <_Z8TestNewBv>: > 242 120000c68: 3c0307f9 lui v1,0x7f9 > 243 120000c6c: 3c0207f7 lui v0,0x7f7 > 244 120000c70: 34633333 ori v1,v1,0x3333 > 245 120000c74: 34423333 ori v0,v0,0x3333 > 246 120000c78: 00031cb8 dsll v1,v1,0x12 > 247 120000c7c: 000214b8 dsll v0,v0,0x12 > 248 120000c80: 3463cccd ori v1,v1,0xcccd > 249 120000c84: 3442cccd ori v0,v0,0xcccd > 250 120000c88: 67bdfff0 daddiu sp,sp,-16 > 251 120000c8c: 00031c78 dsll v1,v1,0x11 > 252 120000c90: 00021478 dsll v0,v0,0x11 > 253 120000c94: 6463999a daddiu v1,v1,-26214 > 254 120000c98: 6442999a daddiu v0,v0,-26214 > 255 120000c9c: 03e00008 jr ra > 256 120000ca0: 67bd0010 daddiu sp,sp,16 > > // test.cpp > // gcc -march=mips64r2 -mabi=64 -O3 -o test test.cpp #include <stdio.h> > > 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; > }