|
From: Julian S. <js...@ac...> - 2005-06-03 12:10:09
|
I'm cleaning up the syscall handlers and associated logic/types/abstractions
so we can fold in ppc-linux support cleanly. One thing I'd like to do is
(at least to some extent) remove handwritten procedures in .S files and
instead put them in .c files. This reduces the number of files and
generally makes the code easier to understand.
An example is shown below.
Does anybody know of any reason why I shouldn't do this?
J
// for reference -- abstracts syscall return results
typedef
struct {
UWord val;
Bool isError;
}
SysRes;
#if defined(VGP_x86_linux)
extern UInt do_syscall_x86_linux_WRK (
UInt syscall_no,
UInt a1, UInt a2, UInt a3,
UInt a4, UInt a5, UInt a6
);
asm(
"do_syscall_x86_linux_WRK:\n"
" push %esi\n"
" push %edi\n"
" push %ebx\n"
" push %ebp\n"
" movl 16+ 4(%esp),%eax\n"
" movl 16+ 8(%esp),%ebx\n"
" movl 16+12(%esp),%ecx\n"
" movl 16+16(%esp),%edx\n"
" movl 16+20(%esp),%esi\n"
" movl 16+24(%esp),%edi\n"
" movl 16+28(%esp),%ebp\n"
" int $0x80\n"
" popl %ebp\n"
" popl %ebx\n"
" popl %edi\n"
" popl %esi\n"
" ret\n"
);
#endif
SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
UWord a4, UWord a5, UWord a6 )
{
SysRes res;
# if defined(VGP_x86_linux)
/* From:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
linux/i386/sysdep.h?
rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
Linux uses a negative return value to indicate syscall errors,
unlike most Unices, which use the condition codes' carry flag.
Since version 2.1 the return value of a system call might be
negative even if the call succeeded. E.g., the 'lseek' system
call might return a large offset. Therefore we must not anymore
test for < 0, but test for a real error by making sure the value
in %eax is a real error number. Linus said he will make sure
the no syscall returns a value in -1 .. -4095 as a valid result
so we can safely test with -4095.
*/
UInt u = do_syscall_x86_linux_WRK(sysno,a1,a2,a3,a4,a5,a6);
Int i = (Int)u;
res.isError = i >= -4095 && i <= -1;
res.val = res.isError ? -i : i;
# else
# error VG_(do_syscall): unimplemented on this platform
# endif
return res;
}
|
|
From: Tom H. <to...@co...> - 2005-06-03 12:48:43
|
In message <200...@ac...>
Julian Seward <js...@ac...> wrote:
> I'm cleaning up the syscall handlers and associated logic/types/abstractions
> so we can fold in ppc-linux support cleanly. One thing I'd like to do is
> (at least to some extent) remove handwritten procedures in .S files and
> instead put them in .c files. This reduces the number of files and
> generally makes the code easier to understand.
>
> An example is shown below.
>
> Does anybody know of any reason why I shouldn't do this?
The main issue with inline assembly is avoiding register conflicts
with the compiler, especially on x86 systems. The main trick is not
to explicitly request a fixed register but use a mov if necessary
to get the value in the right place.
> #if defined(VGP_x86_linux)
> extern UInt do_syscall_x86_linux_WRK (
> UInt syscall_no,
> UInt a1, UInt a2, UInt a3,
> UInt a4, UInt a5, UInt a6
> );
> asm(
> "do_syscall_x86_linux_WRK:\n"
> " push %esi\n"
> " push %edi\n"
> " push %ebx\n"
> " push %ebp\n"
> " movl 16+ 4(%esp),%eax\n"
> " movl 16+ 8(%esp),%ebx\n"
> " movl 16+12(%esp),%ecx\n"
> " movl 16+16(%esp),%edx\n"
> " movl 16+20(%esp),%esi\n"
> " movl 16+24(%esp),%edi\n"
> " movl 16+28(%esp),%ebp\n"
> " int $0x80\n"
> " popl %ebp\n"
> " popl %ebx\n"
> " popl %edi\n"
> " popl %esi\n"
> " ret\n"
> );
> #endif
That looks broken to me - you're making assumptions about where
the stack pointer is pointing at the start of the assembly section.
Or is that a pure assembly routine rather than a C routine with
some inline assembly? I guess that will work... I just didn't
realise gcc could do that.
If you do it that way then my caveats above don't really apply.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Julian S. <js...@ac...> - 2005-06-03 13:06:24
|
> The main issue with inline assembly is avoiding register conflicts > with the compiler, especially on x86 systems. Indeed true, but .. I'm importing complete handwritten functions, not fragments thereof. > > #if defined(VGP_x86_linux) > > extern UInt do_syscall_x86_linux_WRK ( > > UInt syscall_no, > > UInt a1, UInt a2, UInt a3, > > UInt a4, UInt a5, UInt a6 > > ); > > asm( > > "do_syscall_x86_linux_WRK:\n" > > " push %esi\n" > > " push %edi\n" > > " push %ebx\n" > > " push %ebp\n" > > " movl 16+ 4(%esp),%eax\n" > > " movl 16+ 8(%esp),%ebx\n" > > " movl 16+12(%esp),%ecx\n" > > " movl 16+16(%esp),%edx\n" > > " movl 16+20(%esp),%esi\n" > > " movl 16+24(%esp),%edi\n" > > " movl 16+28(%esp),%ebp\n" > > " int $0x80\n" > > " popl %ebp\n" > > " popl %ebx\n" > > " popl %edi\n" > > " popl %esi\n" > > " ret\n" > > ); > > #endif There's a ; between the end of the formal parameter list and the asm(), which crucially changes the meaning. The asm is a standalone top-level thing. The prototype is just there for readability; it could be anywhere. The question really is: is inline asm at the top-level OK, or can it somehow cause problems? J |
|
From: Jeremy F. <je...@go...> - 2005-06-03 20:46:06
|
Julian Seward wrote:
>I'm cleaning up the syscall handlers and associated logic/types/abstractions
>so we can fold in ppc-linux support cleanly. One thing I'd like to do is
>(at least to some extent) remove handwritten procedures in .S files and
>instead put them in .c files. This reduces the number of files and
>generally makes the code easier to understand.
>
>
I generally find embedding assember into .c files is harder to maintain,
mostly because the syntax is so awkward. It's particularly tricky to
use preprocessor macros for constants in embedded asm statements,
because you need to get them into string form so they can be
concatenated with the asm string properly (for naked asms, you can't use
parameter substitution like you can for asms within C functions).
J
|
|
From: Nicholas N. <nj...@cs...> - 2005-06-04 04:02:57
|
On Fri, 3 Jun 2005, Jeremy Fitzhardinge wrote: > I generally find embedding assember into .c files is harder to maintain, > mostly because the syntax is so awkward. It's particularly tricky to > use preprocessor macros for constants in embedded asm statements, > because you need to get them into string form so they can be > concatenated with the asm string properly (for naked asms, you can't use > parameter substitution like you can for asms within C functions). I agree with this. Anything bigger than a few lines I prefer to see in a separate .S file. N |