[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