Hi John,
At Thu, 18 Mar 2004 12:17:36 +1000,
John Williams wrote:
> I think it should probably be done like in David's m68knommu example.
> Declare the variable __res, then inline asm to make the syscall, being
> explicit about the register allocations. Here's a quick hack:
>
> #define _syscall2(type, name, atype, a, btype, b) \
> type name(atype a, btype b) \
> { \
> long __res; \
> __asm__ __volatile__ ("addk SYSCALL_ARG0, %2, r0 \n\t" \
> "addk SYSCALL_ARG1, %3, r0 \n\t" \
> "bralid r17, 0x08 \n\t" \
> "addik SYSCALL_NUM, r0, %1 \n\t" \
> "addk %0, SYSCALL_RET, r0 \n\t" \
> :"=r" (__res) \
> : "i" (__NR_##name), \
> "r" ((long)a), \
> "r" ((long)b) \
> : "cc", "SYSCALL_RET", "SYSCALL_ARG0", "SYSCALL_ARG1", \
> "SYSCALL_NUM");\
> if ((unsigned long)(__res) >= (unsigned long)(-125)) { \
> errno = -__res; \
> __res = -1; \
> } \
> return (type)__res; \
> }
>
> Or something like it. Note with this explicit approach we also get to
> use the delayslot on the bralid instruction, which is nice. Also the
> syscall params should be mapped into exactly the same registers as for
> the function call that's making it, so it should produce some pretty
> streamlined assembly.
>
> > if you can tell me how you want, i can generate a patch. ;)
>
> Great, well see if you can get my example above going, then map it into
> the syscall0 -> syscall5 macros
ok, here is my version of _sycall2
#define SYSCALL_CLOBBERS "r3", "r4", "r11", "r12", "r17"
#define _syscall2(type, name, type1, arg1, type2, arg2) \
type name (type1 arg1, type2 arg2) \
{ \
register long __r5 __asm__ ("r5") = arg1; \
register long __r6 __asm__ ("r6") = arg2; \
long __ret; \
__asm__ __volatile__ ("bralid r17, 0x8 \n\t" \
"addik r12, r0, %1 \n\t" \
"addk %0, r3, r0 \n\t" \
: "=r" (__ret) \
: "i" (__NR_##name), \
"r" (__r5), \
"r" (__r6) \
: SYSCALL_CLOBBERS); \
__syscall_return (type, __ret); \
}
the difference from John's are:
- keep using C declarations for syscall arguments.
- keey using __syscall_return
- no mention of SYSCALL_ARG# in clobbers. they are listed in input operand
- all volatile registers, except r5-r10, are in clobbers
- use type# and arg# instead of a b c.
this code generates some this like this with -Os:
2ef98: 3021ffd8 addik r1, r1, -40
2ef9c: fac10024 swi r22, r1, 36
2efa0: d9e00800 sw r15, r0, r1
2efa4: ba3c0008 bralid r17, 8
2efa8: 3180003f addik r12, r0, 63
2efac: 12c30000 addk r22, r3, r0
2efb0: aa56ff82 xori r18, r22, -126
2efb4: bcb2000c bgei r18, 12 // 2efc0
2efb8: bcb60028 bgei r22, 40 // 2efe0
2efbc: b800000c bri 12 // 2efc8
2efc0: 3656ff82 rsubik r18, r22, -126
2efc4: bcb2001c bgei r18, 28 // 2efe0
2efc8: b000ffff imm -1
2efcc: b9f45d00 brlid r15, 23808 // 24ccc <__errno_location>
2efd0: 80000000 or r0, r0, r0
2efd4: 14960000 rsubk r4, r22, r0
2efd8: d8801800 sw r4, r0, r3
2efdc: 32c0ffff addik r22, r0, -1
2efe0: 10760000 addk r3, r22, r0
2efe4: eac10024 lwi r22, r1, 36
2efe8: c9e00800 lw r15, r0, r1
2efec: b60f0008 rtsd r15, 8
2eff0: 30210028 addik r1, r1, 40
the patch for unistd.h is attached.
regards,
--
yashi
Attachment:
unistd.h-1.3-explicit.patch
Description: Binary data