- To: freeware at sgi dot com
- Subject: Freeware comment
- From: Andy Polyakov <appro at fy dot chalmers dot se>
- Date: Mon, 05 Jun 2000 16:18:54 +0200
Hi,
http://freeware.sgi.com/Installable/gcc-2.95.2.html states:
<quote>
Unlike the SGI cc, gcc does not seem to support 128-bit quantities like
long double and long long on MIPS.
[From Jim Wilson] Gcc does not correctly pass/return structures which
are smaller than 16 bytes and which are not 8 bytes. The problem is very
involved and difficult to fix. It affects a number of other targets
also, but irix6 is affected the most, because it is a 64 bit target, and
4 byte structures are common. The exact problem is that structures are
being padded at the wrong end, e.g. a 4 byte structure is loaded into
the lower 4 bytes of the register when it should be loaded into the
upper 4 bytes of the register.
Gcc is consistent with itself, but not consistent with the SGI C
compiler [and the SGI supplied runtime libraries], so the only failures
that can happen are when there are library functions that take/return
such structures. There are very few such library functions. I can only
recall seeing a few of them: inet_ntoa, inet_aton, inet_lnaof,
inet_netof, and semctl.
A possible workaround: if you have a program that calls inet_ntoa and
friends or semctl, and your kernel supports 64-bit binaries (i.e. uname
-a prints IRIX64 rather than just IRIX),then you may compile with gcc
-mabi=64 to workaround this problem.
</quote>
There're several inaccuracies. To start with MIPSpro C doesn't support
128-bit long long either. Secondly inet_aton isn't affected by "padding
feature" as the structure is passed by reference. Finally "workaround"
helps semctl *only* and absolutely not "inet_ntoa and friends." However
it's possible to workaround all the mentioned problems if one links with
following piece of code:
#ifdef __GNUC__
#if _MIPS_SIM == _ABI64
typedef unsigned long reg_t;
#define REG_T
#elif _MIPS_SIM == _ABIN32
typedef unsigned long long reg_t;
#define REG_T
#endif /* _MIPS_SIM */
#ifdef REG_T
reg_t inet_ntoa (reg_t a0)
{ return _inet_ntoa (a0<<32); }
reg_t inet_lnaof (reg_t a0)
{ return _inet_lnaof (a0<<32); }
reg_t inet_netof (reg_t a0)
{ return _inet_netof (a0<<32); }
reg_t inet_makeaddr (reg_t a0, reg_t a1)
{ reg_t _inet_makeaddr ();
return _inet_makeaddr (a0,a1)>>32;
}
#if _MIPS_SIM != _ABI64
reg_t semctl (reg_t a0, reg_t a1, reg_t a2, reg_t a3)
{ return _semctl(a0,a1,a2,a3<<32); }
#endif /* _MIPS_SIM */
#endif /* REG_T */
#endif /* __GNUC__ */
If compiled code is appended to
/usr/gnu/gcc/lib/gcc-lib/mips-sgi-irix6.5/2.95.2/[mabi=64/]libgcc.a the
workaround becomes transparent to the user:-)
Andy.