Hi all,
Does anyone happen to know if there are *any* 32-bit architectures (on
which Linux runs) for which the ABI for a "long long" is different from
passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
or (lo,hi) for littleendian?
I'd like to switch klibc to use the 64-bit file ABI thoughout, but it's
a considerable porting effort, and I'm trying to figure out how to best
manage it.
-hpa
H. Peter Anvin wrote:
> Hi all,
>
> Does anyone happen to know if there are *any* 32-bit architectures (on
> which Linux runs) for which the ABI for a "long long" is different from
> passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
> or (lo,hi) for littleendian?
>
> I'd like to switch klibc to use the 64-bit file ABI thoughout, but it's
> a considerable porting effort, and I'm trying to figure out how to best
> manage it.
>
I don't know how it is for GCC, but when using the Sun compiler, "long
long" for 32-bit is low-high, while "long long" (or just long) for
64-bit is high-low. This has been an annoyance to me. :)
On Wed, 28 Jan 2004 14:12:50 -0500
Timothy Miller <[email protected]> wrote:
> I don't know how it is for GCC, but when using the Sun compiler, "long
> long" for 32-bit is low-high, while "long long" (or just long) for
> 64-bit is high-low. This has been an annoyance to me. :)
For 64-bit it goes into a single 64-bit register.
And for 32-bit the sequence is high 32-bits low 32-bits.
At least on Sparc.
extern void foo(long long a);
void bar(void)
{
foo(1);
}
/* gcc -m32 -S -o bar.s bar.c */
bar:
!#PROLOGUE# 0
save %sp, -104, %sp
!#PROLOGUE# 1
mov 0, %o0
mov 1, %o1
call foo, 0
nop
nop
ret
restore
/* gcc -m64 -S -o bar.s bar.c */
bar:
!#PROLOGUE# 0
save %sp, -192, %sp
!#PROLOGUE# 1
mov 1, %o0
call foo, 0
nop
nop
return %i7+8
H.P.A wrote:
> Does anyone happen to know if there are *any* 32-bit architectures (on
> which Linux runs) for which the ABI for a "long long" is different from
> passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
> or (lo,hi) for littleendian?
Some architectures require long long arguments to be passed as an
even/odd register pair. For example on s390,
void f(int a, int b, long long x)
uses registers 2, 3, 4 and 5, while
void f(int a, long long x, int b)
uses registers 2, 4, 5 and 6. AFAIK, mips does the same, probably others
as well.
Arnd <><
On Wed, Jan 28, 2004 at 08:22:01PM +0100, Arnd Bergmann wrote:
>
> H.P.A wrote:
>
> > Does anyone happen to know if there are *any* 32-bit architectures (on
> > which Linux runs) for which the ABI for a "long long" is different from
> > passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
> > or (lo,hi) for littleendian?
>
> Some architectures require long long arguments to be passed as an
> even/odd register pair. For example on s390,
>
> void f(int a, int b, long long x)
>
> uses registers 2, 3, 4 and 5, while
>
> void f(int a, long long x, int b)
>
> uses registers 2, 4, 5 and 6. AFAIK, mips does the same, probably others
> as well.
Yes. Also, IIRC, one of SH3 and SH4 requires the padding, and the
other doesn't.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
Arnd Bergmann wrote:
>Some architectures require long long arguments to be passed as an
>even/odd register pair. For example on s390,
>
> void f(int a, int b, long long x)
>
>uses registers 2, 3, 4 and 5, while
>
> void f(int a, long long x, int b)
>
>uses registers 2, 4, 5 and 6.
Actually, this isn't quite true -- the second case will also
use registers 2, 3, 4, and 5.
However, there is still a case where a single long long is
passed differently from a pair of longs: when there is only
a single register remaining for parameters.
This means that
void f(int a, int b, int c, int d, long e, long f)
is passed as
a-d in register 2-5
e in register 6
f on the stack (4 bytes)
while
void f(int a, int b, int c, int d, long long e)
is passed as
a-d in register 2-5
nothing in register 6
e on the stack (8 bytes)
Bye,
Ulrich
--
Dr. Ulrich Weigand
[email protected]
Ulrich Weigand wrote:
> Arnd Bergmann wrote:
>
>
>>Some architectures require long long arguments to be passed as an
>>even/odd register pair. For example on s390,
>>
>> void f(int a, int b, long long x)
>>
>>uses registers 2, 3, 4 and 5, while
>>
>> void f(int a, long long x, int b)
>>
>>uses registers 2, 4, 5 and 6.
>
>
> Actually, this isn't quite true -- the second case will also
> use registers 2, 3, 4, and 5.
>
> However, there is still a case where a single long long is
> passed differently from a pair of longs: when there is only
> a single register remaining for parameters.
>
> This means that
> void f(int a, int b, int c, int d, long e, long f)
> is passed as
> a-d in register 2-5
> e in register 6
> f on the stack (4 bytes)
>
> while
> void f(int a, int b, int c, int d, long long e)
> is passed as
> a-d in register 2-5
> nothing in register 6
> e on the stack (8 bytes)
>
If I remember correctly, a 6-argument system call on s390 will put a
pointer to the last two arguments as the effective 5th argument, so this
would not affect the system call calling convention, correct?
-hpa
On Thursday 29 January 2004 02:34, H. Peter Anvin wrote:
> If I remember correctly, a 6-argument system call on s390 will put a
> pointer to the last two arguments as the effective 5th argument, so this
> would not affect the system call calling convention, correct?
Almost. I think this is only relevant for mmap2(), where we pass a single
pointer to a struct with all six arguments, but the result is the same.
I don't know where I got the misinformation about the register pairs
on s390, but I verified that the problem exists on MIPS and PowerPC.
See sys32_ftruncate64 in arch/mips/kernel/linux32.c and
arch/ppc64/kernel/sys_ppc32.c. PA-RISC appearantly work around this
by defining their own system call handlers with separate high/low
arguments, so they effectively work like i386 and s390.
Arnd <><
H. Peter Anvin writes:
> Does anyone happen to know if there are *any* 32-bit architectures (on
> which Linux runs) for which the ABI for a "long long" is different from
> passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
> or (lo,hi) for littleendian?
Are you are talking about passing arguments to a function? PPC32
passes long long arguments in two registers in the order you would
expect (hi, lo), BUT you have to use an odd/even register pair. In
other words, if you have a function like this:
int foo(int a, long long b)
then a will be passed in r3 and b will be passed in r5 and r6, and r4
will be unused.
Regards,
Paul.
Paul Mackerras wrote:
> H. Peter Anvin writes:
>
>
>>Does anyone happen to know if there are *any* 32-bit architectures (on
>>which Linux runs) for which the ABI for a "long long" is different from
>>passing two "longs" in the appropriate order, i.e. (hi,lo) for bigendian
>>or (lo,hi) for littleendian?
>
>
> Are you are talking about passing arguments to a function? PPC32
> passes long long arguments in two registers in the order you would
> expect (hi, lo), BUT you have to use an odd/even register pair. In
> other words, if you have a function like this:
>
> int foo(int a, long long b)
>
> then a will be passed in r3 and b will be passed in r5 and r6, and r4
> will be unused.
>
Does system calls follow the same convention?
-hpa
On Saturday 31 January 2004 07:08, H. Peter Anvin wrote:
> Does system calls follow the same convention?
I have just looked up in glibc what architectures need this kind
of handling and found that there is no easy rule. The good news
is that none of (hppa m68k s390 sparc x86_64 alpha cris i386 sparc64
arm ia64) are doing this.
AFAICS, the padding is done for exactly these system calls:
ppc: truncate64, ftruncate64, pread64, pwrite64
mips: truncate64, ftruncate64, pread64, pwrite64
sh: pread64, pwrite64
fadvise64_64 is another story:
mips does no padding, ppc32 reorders the arguments (int fd, int advise,
off64_t offset, off64_t len) and s390 passes a struct, for the
reason Uli already explained.
Arnd <><
Arnd Bergmann wrote:
> On Saturday 31 January 2004 07:08, H. Peter Anvin wrote:
>
>>Does system calls follow the same convention?
>
>
> I have just looked up in glibc what architectures need this kind
> of handling and found that there is no easy rule. The good news
> is that none of (hppa m68k s390 sparc x86_64 alpha cris i386 sparc64
> arm ia64) are doing this.
>
> AFAICS, the padding is done for exactly these system calls:
>
> ppc: truncate64, ftruncate64, pread64, pwrite64
> mips: truncate64, ftruncate64, pread64, pwrite64
> sh: pread64, pwrite64
>
> fadvise64_64 is another story:
> mips does no padding, ppc32 reorders the arguments (int fd, int advise,
> off64_t offset, off64_t len) and s390 passes a struct, for the
> reason Uli already explained.
>
<BARF>
I hate ad hockery :( Yet more evidence for the need of a formal
description of the ABI in the kernel.
-hpa
H. Peter Anvin writes:
> Does system calls follow the same convention?
Yes. A system call with a long long argument will be handled by a C
routine in the kernel. The system call arguments in r3 - r8 are
unchanged by the system call exception entry code and end up being the
arguments to the C routine.
Paul.