[uClibc]Note- MIPS syscall
Shane Nay
Shane.Nay at taec.toshiba.com
Tue Jul 30 18:50:44 UTC 2002
The asm/unistd.h is not sufficient with the newer compiler/linker versions.
Here is a snippet of that file-
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a, btype b) \
{ \
register unsigned long __v0 asm("$2") = __NR_##name; \
register unsigned long __a0 asm("$4") = (unsigned long) a; \
register unsigned long __a1 asm("$5") = (unsigned long) b; \
register unsigned long __a3 asm("$7"); \
\
__asm__ volatile ( \
".set\tnoreorder\n\t" \
"li\t$2, %4\t\t\t# " #name "\n\t" \
"syscall\n\t" \
".set\treorder" \
: "=&r" (__v0), "=r" (__a3) \
: "r" (__a0), "r" (__a1), "i" (__NR_##name) \
: "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
\
if (__a3 == 0) \
return (type) __v0; \
errno = __v0; \
return -1; \
}
What happens is this-
In the case that __a3 is not zero, the new value of errno is present in
register v0. "errno" is a global, so it needs to figure out the address of
that variable, so it has to call the resolver. The resolver returns the
address of errno in the v0 register.
So, it overwrites the v0 register with the value for the address of errno.
Then it stores v0 at v0, which puts the address of errno in the errno
variable.
I'm trying a temporary solution of putting an unsigned long variable in there,
and saving the value of v0 in that variable before setting the value to
errno. The assembly produced by the compiler in the new case at least has a
prayer of working :). (it moves the value to another register before doing
the jump to the global resolver)
Thanks,
Shane Nay.
More information about the uClibc
mailing list