From 55d38162be9ebd5b90b2550d0331a030c446c001 Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Mon, 1 Jun 2020 23:47:49 +0200 Subject: [PATCH] Introduce libmescc.a; Put division by integer in there; split syscalls' errno off. * build-aux/configure-lib.sh (libmescc_SOURCES): Add lib/mes/div.c, lib/linux/*/syscall-internal.c. * build-aux/build-lib.sh: Add libmescc.a. * build-aux/build-mes.sh: On gcc, add "-lmescc". * build-aux/test-c.sh: Add "-lmescc". * build-aux/check.sh.in: Add mescc to LIBS. * module/mescc/mescc.scm (mescc:link): Add "mescc". * module/mescc.scm (mescc:main): Update documentation of "-nodefaultlibs" and "-nostdlib". * lib/mes/div.c (ldiv): Rename to... (__mesabi_ldiv): ...this. Avoid assert. (__mesabi_div0): Avoid assert. (__aeabi_idivmod): New procedure. (__aeabi_idiv): New procedure. (__aeabi_uidivmod): New procedure. (__aeabi_uidiv): New procedure. * lib/linux/x86-mes-gcc/syscall.c (__sys_call, __sys_call1, __sys_call2, __sys_call3, __sys_call4): Move to... * lib/linux/x86-mes-gcc/syscall-internal.c: ...here. (__raise): New procedure. * lib/linux/x86-mes-mescc/syscall.c (__sys_call, __sys_call1, __sys_call2, __sys_call3, __sys_call4): Move to... * lib/linux/x86-mes-mescc/syscall-internal.c: ...here. (__raise): New procedure. * lib/linux/arm-mes-gcc/syscall.c: New file. * lib/linux/arm-mes-gcc/syscall-internal.c: New file. * lib/linux/arm-mes-mescc/syscall.c: New file. * lib/linux/arm-mes-mescc/syscall-internal.c: New file. * lib/gnu/syscall.c (__syscall, __syscall2, __syscall_get, __syscall_put): Move to... * lib/gnu/syscall-internal.c: ...here. --- build-aux/build-lib.sh | 6 + build-aux/build-mes.sh | 4 + build-aux/check.sh.in | 2 +- build-aux/configure-lib.sh | 6 +- build-aux/test-c.sh | 14 +- lib/gnu/syscall-internal.c | 143 +++++++++++++++++++++ lib/gnu/syscall.c | 123 ------------------ lib/linux/arm-mes-gcc/syscall-internal.c | 141 ++++++++++++++++++++ lib/linux/arm-mes-gcc/syscall.c | 116 +++++++++++++++++ lib/linux/arm-mes-mescc/syscall-internal.c | 90 +++++++++++++ lib/linux/arm-mes-mescc/syscall.c | 113 ++++++++++++++++ lib/linux/x86-mes-gcc/syscall-internal.c | 118 +++++++++++++++++ lib/linux/x86-mes-gcc/syscall.c | 66 ++-------- lib/linux/x86-mes-mescc/syscall-internal.c | 77 +++++++++++ lib/linux/x86-mes-mescc/syscall.c | 49 +------ lib/mes/div.c | 74 +++++++++-- module/mescc.scm | 4 +- module/mescc/mescc.scm | 5 +- 18 files changed, 905 insertions(+), 246 deletions(-) create mode 100644 lib/gnu/syscall-internal.c create mode 100644 lib/linux/arm-mes-gcc/syscall-internal.c create mode 100644 lib/linux/arm-mes-gcc/syscall.c create mode 100644 lib/linux/arm-mes-mescc/syscall-internal.c create mode 100644 lib/linux/arm-mes-mescc/syscall.c create mode 100644 lib/linux/x86-mes-gcc/syscall-internal.c create mode 100644 lib/linux/x86-mes-mescc/syscall-internal.c diff --git a/build-aux/build-lib.sh b/build-aux/build-lib.sh index 4ef701c3..ea36bfbe 100755 --- a/build-aux/build-lib.sh +++ b/build-aux/build-lib.sh @@ -44,6 +44,12 @@ if test -e libmes.s; then cp libmes.s $mes_cpu-mes fi +archive libmescc.a $libmescc_SOURCES +cp libmescc.a $mes_cpu-mes +if test -e libmescc.s; then + cp libmescc.s $mes_cpu-mes +fi + if test $mes_libc = mes; then archive libc.a $libc_SOURCES cp libc.a $mes_cpu-mes diff --git a/build-aux/build-mes.sh b/build-aux/build-mes.sh index 4e388c4f..df3c93fe 100755 --- a/build-aux/build-mes.sh +++ b/build-aux/build-mes.sh @@ -53,5 +53,9 @@ done if test $mes_libc = system; then LIBS=-lmes fi +if [ "$compiler" = "gcc" ] +then + LIBS="${LIBS} -lmescc" +fi link bin/mes-$compiler cp bin/mes-$compiler bin/mes diff --git a/build-aux/check.sh.in b/build-aux/check.sh.in index 94a0dbf8..e692bc53 100644 --- a/build-aux/check.sh.in +++ b/build-aux/check.sh.in @@ -97,7 +97,7 @@ fi LDFLAGS=" -nostdlib " - LIBS=-lc + LIBS="-lc -lmescc" AR="${srcdest}pre-inst-env mesar" CC="${srcdest}pre-inst-env mescc" ../pre-inst-env ${SHELL} ${srcdest}build-aux/check-mescc.sh diff --git a/build-aux/configure-lib.sh b/build-aux/configure-lib.sh index ed0e23bb..7bd2f876 100644 --- a/build-aux/configure-lib.sh +++ b/build-aux/configure-lib.sh @@ -76,11 +76,15 @@ lib/mes/mini-write.c " fi +libmescc_SOURCES=" +lib/linux/$mes_cpu-mes-$compiler/syscall-internal.c +lib/mes/div.c +" + libmes_SOURCES=" $libc_mini_shared_SOURCES lib/ctype/isnumber.c lib/mes/abtol.c -lib/mes/div.c lib/mes/eputc.c lib/mes/fdgetc.c lib/mes/fdputc.c diff --git a/build-aux/test-c.sh b/build-aux/test-c.sh index 00844075..39c69f9e 100755 --- a/build-aux/test-c.sh +++ b/build-aux/test-c.sh @@ -41,25 +41,25 @@ CC=${CC-gcc} i=$(basename "$t" .c) if [ -z "${i/[012][0-9]-*/}" ]; then - LIBS= + LIBS='-l mescc' elif [ -z "${i/[34][0-9]-*/}" ]; then - LIBS='-l c-mini' + LIBS='-l c-mini -l mescc' elif [ -z "${i/[78][0-9a-z]-*/}" ]; then - LIBS='-l c+tcc' + LIBS='-l c+tcc -l mescc' elif [ -z "${i/9[0-9a-z]-*/}" ]; then - LIBS='-l c+gnu' + LIBS='-l c+gnu -l mescc' else - LIBS='-l c' + LIBS='-l c -l mescc' fi if test $mes_kernel = gnu\ && test -z "$LIBS"; then - LIBS="-l c-mini" + LIBS="-l c-mini -l mescc" fi if test $mes_libc = system; then crt1= - LIBS='-l mes' + LIBS='-l mes -l mescc' else crt1=crt1.o fi diff --git a/lib/gnu/syscall-internal.c b/lib/gnu/syscall-internal.c new file mode 100644 index 00000000..d60a6d4d --- /dev/null +++ b/lib/gnu/syscall-internal.c @@ -0,0 +1,143 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +#include + +static mach_msg_type_t mach_msg_type_int32 = + { + .msgt_name = (unsigned char) MACH_MSG_TYPE_INTEGER_32, // msgt_name + .msgt_size = 32, // msgt_size + .msgt_number = 1, // msgt_number + .msgt_inline = 1, // msgt_inline + .msgt_longform = 0, // msgt_longform + .msgt_deallocate = 0, // msgt_deallocate + .msgt_unused = 0 // msgt_unused + }; + +static mach_msg_type_long_t mach_msg_type_pointer = + { + { + 0, // msgt_name + 0, // msgt_size + 0, // msgt_number + 1, // msgt_inline FIXME: we always outline... + 1, // msgt_longform + 0, // msgt_deallocate + 0, // msgt_unused + }, + MACH_MSG_TYPE_CHAR, // msgtl_name + 8, // msgtl_size + 2048, // msgtl_number + }; + +static mach_msg_type_t mach_msg_type_int64 = + { + (unsigned char) MACH_MSG_TYPE_INTEGER_64, // msgt_name + 64, // msgt_size + 1, // msgt_number + 1, // msgt_inline + 0, // msgt_longform + 0, // msgt_deallocate + 0, // msgt_unused + }; + +kern_return_t +__syscall (mach_port_t port, int sys_call) +{ + struct mach_msg message = + { + { + MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE), + 0, + port, + {__mach_reply_port (),}, + 0, + sys_call, + } + }; + return __mach_msg (&message.header, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, + sizeof (message), + sizeof (message), + message.header.msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); +} + +kern_return_t +__syscall2 (mach_port_t port, int sys_call, int one, int two) +{ + struct mach_msg_2 message = + { + { + MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE), + 0, + port, + {__mach_reply_port (),}, + 0, + sys_call, + }, + mach_msg_type_int32, one, + mach_msg_type_int32, two, + }; + return __mach_msg (&message.header, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, + sizeof (message), + sizeof (message), + message.header.msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); +} + +kern_return_t +__syscall_get (mach_port_t port, int sys_call, mach_msg_header_t *message, size_t size) +{ + message->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); + message->msgh_remote_port = port; + message->msgh_local_port = __mach_reply_port (); + message->msgh_seqno = 0; + message->msgh_id = sys_call; + return __mach_msg (message, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, + message->msgh_size, + size, + message->msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); +} + +kern_return_t +__syscall_put (mach_port_t port, int sys_call, mach_msg_header_t *message, size_t size) +{ + message->msgh_bits |= MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); + message->msgh_remote_port = port; + message->msgh_local_port = __mach_reply_port (); + message->msgh_seqno = 0; + message->msgh_id = sys_call; + return __mach_msg (message, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, + message->msgh_size, + size, + message->msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); +} diff --git a/lib/gnu/syscall.c b/lib/gnu/syscall.c index bd919a47..55b98ca8 100644 --- a/lib/gnu/syscall.c +++ b/lib/gnu/syscall.c @@ -18,126 +18,3 @@ * along with GNU Mes. If not, see . */ -#include - -#include - -mach_msg_type_t mach_msg_type_int32 = - { - .msgt_name = (unsigned char) MACH_MSG_TYPE_INTEGER_32, // msgt_name - .msgt_size = 32, // msgt_size - .msgt_number = 1, // msgt_number - .msgt_inline = 1, // msgt_inline - .msgt_longform = 0, // msgt_longform - .msgt_deallocate = 0, // msgt_deallocate - .msgt_unused = 0 // msgt_unused - }; - -mach_msg_type_long_t mach_msg_type_pointer = - { - { - 0, // msgt_name - 0, // msgt_size - 0, // msgt_number - 1, // msgt_inline FIXME: we always outline... - 1, // msgt_longform - 0, // msgt_deallocate - 0, // msgt_unused - }, - MACH_MSG_TYPE_CHAR, // msgtl_name - 8, // msgtl_size - 2048, // msgtl_number - }; - -mach_msg_type_t mach_msg_type_int64 = - { - (unsigned char) MACH_MSG_TYPE_INTEGER_64, // msgt_name - 64, // msgt_size - 1, // msgt_number - 1, // msgt_inline - 0, // msgt_longform - 0, // msgt_deallocate - 0, // msgt_unused - }; - -kern_return_t -__syscall (mach_port_t port, int sys_call) -{ - struct mach_msg message = - { - { - MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE), - 0, - port, - {__mach_reply_port (),}, - 0, - sys_call, - } - }; - return __mach_msg (&message.header, - MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, - sizeof (message), - sizeof (message), - message.header.msgh_local_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); -} - -kern_return_t -__syscall2 (mach_port_t port, int sys_call, int one, int two) -{ - struct mach_msg_2 message = - { - { - MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE), - 0, - port, - {__mach_reply_port (),}, - 0, - sys_call, - }, - mach_msg_type_int32, one, - mach_msg_type_int32, two, - }; - return __mach_msg (&message.header, - MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, - sizeof (message), - sizeof (message), - message.header.msgh_local_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); -} - -kern_return_t -__syscall_get (mach_port_t port, int sys_call, mach_msg_header_t *message, size_t size) -{ - message->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - message->msgh_remote_port = port; - message->msgh_local_port = __mach_reply_port (); - message->msgh_seqno = 0; - message->msgh_id = sys_call; - return __mach_msg (message, - MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, - message->msgh_size, - size, - message->msgh_local_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); -} - -kern_return_t -__syscall_put (mach_port_t port, int sys_call, mach_msg_header_t *message, size_t size) -{ - message->msgh_bits |= MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - message->msgh_remote_port = port; - message->msgh_local_port = __mach_reply_port (); - message->msgh_seqno = 0; - message->msgh_id = sys_call; - return __mach_msg (message, - MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, - message->msgh_size, - size, - message->msgh_local_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); -} diff --git a/lib/linux/arm-mes-gcc/syscall-internal.c b/lib/linux/arm-mes-gcc/syscall-internal.c new file mode 100644 index 00000000..1f4fc16b --- /dev/null +++ b/lib/linux/arm-mes-gcc/syscall-internal.c @@ -0,0 +1,141 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +// *INDENT-OFF* +long +__sys_call (long sys_call) +{ + long r; + asm ( + "mov r7, %1\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call) + : "r0", "r7" + ); + return r; +} + +long +__sys_call1 (long sys_call, long one) +{ + long r; + asm ( + "mov r7, %1\n\t" + "mov r0, %2\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call), "r" (one) + : "r0", "r7" + ); + return r; +} + +long +__sys_call2 (long sys_call, long one, long two) +{ + long r; + asm ( + "mov r7, %1\n\t" + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call), "r" (one), "r" (two) + : "r0", "r1", "r7" + ); + return r; +} + +long +__sys_call3 (long sys_call, long one, long two, long three) +{ + long r; + asm ( + "mov r7, %1\n\t" + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call), "r" (one), "r" (two), "r" (three) + : "r0", "r1", "r2", "r7" + ); + return r; +} + +long +__sys_call4 (long sys_call, long one, long two, long three, long four) +{ + long r; + asm ( + "mov r7, %1\n\t" + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call), "r" (one), "r" (two), "r" (three), "r" (four) + : "r0", "r1", "r2", "r3", "r7" + ); + return r; +} + +#if 0 +long +__sys_call6 (long sys_call, long one, long two, long three, long four, long five, long six) +{ + long r; + asm ( + "mov r7, %1\n\t" + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "mov r5, %7\n\t" + "swi $0\n\t" + "mov %0, r0\n\t" + : "=r" (r) + : "r" (sys_call), "r" (one), "r" (two), "r" (three), "r" (four), "r" (five), "r" (six) + : "r0", "r1", "r2", "r3", "r4", "r5" //, "r7" FIXME + ); + return r; +} +#endif + +/* Returns < 0 on error (errno-like value from kernel), or 0 on success */ +int +__raise(int signum) +{ + long pid = __sys_call (SYS_getpid); + if (pid < 0) + return pid; + else + return __sys_call2 (SYS_kill, pid, signum); +} diff --git a/lib/linux/arm-mes-gcc/syscall.c b/lib/linux/arm-mes-gcc/syscall.c new file mode 100644 index 00000000..9f0251c7 --- /dev/null +++ b/lib/linux/arm-mes-gcc/syscall.c @@ -0,0 +1,116 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include + +long __sys_call (long sys_call); +long __sys_call1 (long sys_call, long one); +long __sys_call2 (long sys_call, long one, long two); +long __sys_call3 (long sys_call, long one, long two, long three); +long __sys_call4 (long sys_call, long one, long two, long three, long four); +long __sys_call6 (long sys_call, long one, long two, long three, long four, long five, long six); + +// *INDENT-OFF* +long +_sys_call (long sys_call) +{ + long r = __sys_call(sys_call); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call1 (long sys_call, long one) +{ + long r = __sys_call1(sys_call, one); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call2 (long sys_call, long one, long two) +{ + long r = __sys_call2(sys_call, one, two); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call3 (long sys_call, long one, long two, long three) +{ + long r = __sys_call3(sys_call, one, two, three); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call4 (long sys_call, long one, long two, long three, long four) +{ + long r = __sys_call4(sys_call, one, two, three, four); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +#if 0 +long +_sys_call6 (long sys_call, long one, long two, long three, long four, long five, long six) +{ + long r = __sys_call6(sys_call, one, two, three, four, five, six); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} +#endif diff --git a/lib/linux/arm-mes-mescc/syscall-internal.c b/lib/linux/arm-mes-mescc/syscall-internal.c new file mode 100644 index 00000000..e74fb440 --- /dev/null +++ b/lib/linux/arm-mes-mescc/syscall-internal.c @@ -0,0 +1,90 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +int +__sys_call (int sys_call) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +int +__sys_call1 (int sys_call, int one) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("!12 ldr____%r0,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +int +__sys_call2 (int sys_call, int one, int two) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("!12 ldr____%r0,(%fp,+#$i8)"); + asm ("!16 ldr____%r1,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +int +__sys_call3 (int sys_call, int one, int two, int three) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("!12 ldr____%r0,(%fp,+#$i8)"); + asm ("!16 ldr____%r1,(%fp,+#$i8)"); + asm ("!20 ldr____%r2,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +int +__sys_call4 (int sys_call, int one, int two, int three, int four) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("!12 ldr____%r0,(%fp,+#$i8)"); + asm ("!16 ldr____%r1,(%fp,+#$i8)"); + asm ("!20 ldr____%r2,(%fp,+#$i8)"); + asm ("!24 ldr____%r3,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +int +__sys_call6 (int sys_call, int one, int two, int three, int four, int five, int six) +{ + asm ("!8 ldr____%r7,(%fp,+#$i8)"); + asm ("!12 ldr____%r0,(%fp,+#$i8)"); + asm ("!16 ldr____%r1,(%fp,+#$i8)"); + asm ("!20 ldr____%r2,(%fp,+#$i8)"); + asm ("!24 ldr____%r3,(%fp,+#$i8)"); + asm ("!28 ldr____%r4,(%fp,+#$i8)"); + asm ("!32 ldr____%r5,(%fp,+#$i8)"); + asm ("swi____$0"); +} + +/* Returns < 0 on error (errno-like value from kernel), or 0 on success */ +int +__raise(int signum) +{ + int pid = __sys_call (SYS_getpid); + if (pid < 0) + return pid; + else + return __sys_call2 (SYS_kill, pid, signum); +} diff --git a/lib/linux/arm-mes-mescc/syscall.c b/lib/linux/arm-mes-mescc/syscall.c new file mode 100644 index 00000000..a8535917 --- /dev/null +++ b/lib/linux/arm-mes-mescc/syscall.c @@ -0,0 +1,113 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include + +int __sys_call (int sys_call); +int __sys_call1 (int sys_call, int one); +int __sys_call2 (int sys_call, int one, int two); +int __sys_call3 (int sys_call, int one, int two, int three); +int __sys_call4 (int sys_call, int one, int two, int three, int four); +int __sys_call6 (int sys_call, int one, int two, int three, int four, int five, int six); + +int +_sys_call (int sys_call) +{ + int r = __sys_call (sys_call); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +int +_sys_call1 (int sys_call, int one) +{ + int r = __sys_call1 (sys_call, one); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +int +_sys_call2 (int sys_call, int one, int two) +{ + int r = __sys_call2 (sys_call, one, two); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +int +_sys_call3 (int sys_call, int one, int two, int three) +{ + int r = __sys_call3 (sys_call, one, two, three); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +int +_sys_call4 (int sys_call, int one, int two, int three, int four) +{ + int r = __sys_call4 (sys_call, one, two, three, four); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +int +_sys_call6 (int sys_call, int one, int two, int three, int four, int five, int six) +{ + int r = __sys_call6 (sys_call, one, two, three, four, five, six); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} diff --git a/lib/linux/x86-mes-gcc/syscall-internal.c b/lib/linux/x86-mes-gcc/syscall-internal.c new file mode 100644 index 00000000..fe2117bb --- /dev/null +++ b/lib/linux/x86-mes-gcc/syscall-internal.c @@ -0,0 +1,118 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +// *INDENT-OFF* +long +__sys_call (long sys_call) +{ + long r; + asm ( + "mov %1,%%eax\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : "rm" (sys_call) + : "eax" + ); + return r; +} + +long +__sys_call1 (long sys_call, long one) +{ + long r; + asm ( + "mov %1,%%eax\n\t" + "mov %2,%%ebx\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : "rm" (sys_call), "rm" (one) + : "eax", "ebx" + ); + return r; +} + +long +__sys_call2 (long sys_call, long one, long two) +{ + long r; + asm ( + "mov %1,%%eax\n\t" + "mov %2,%%ebx\n\t" + "mov %3,%%ecx\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : "rm" (sys_call), "rm" (one), "rm" (two) + : "eax", "ebx", "ecx" + ); + return r; +} + +long +__sys_call3 (long sys_call, long one, long two, long three) +{ + long r; + asm ( + "mov %2,%%ebx\n\t" + "mov %3,%%ecx\n\t" + "mov %4,%%edx\n\t" + "mov %1,%%eax\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : "rm" (sys_call), "rm" (one), "rm" (two), "rm" (three) + : "eax", "ebx", "ecx", "edx" + ); + return r; +} + +long +__sys_call4 (long sys_call, long one, long two, long three, long four) +{ + long r; + asm ( + "mov %2,%%ebx\n\t" + "mov %3,%%ecx\n\t" + "mov %4,%%edx\n\t" + "mov %5,%%esi\n\t" + "mov %1,%%eax\n\t" + "int $0x80\n\t" + "mov %%eax,%0\n\t" + : "=r" (r) + : "rm" (sys_call), "rm" (one), "rm" (two), "rm" (three), "rm" (four) + : "eax", "ebx", "ecx", "edx", "esi" + ); + return r; +} + +/* Returns < 0 on error (errno-like value from kernel), or 0 on success */ +int +__raise(int signum) +{ + long pid = __sys_call (SYS_getpid); + if (pid < 0) + return pid; + else + return __sys_call2 (SYS_kill, pid, signum); +} diff --git a/lib/linux/x86-mes-gcc/syscall.c b/lib/linux/x86-mes-gcc/syscall.c index f6eb4e80..0b5c2a70 100644 --- a/lib/linux/x86-mes-gcc/syscall.c +++ b/lib/linux/x86-mes-gcc/syscall.c @@ -21,19 +21,17 @@ #include #include +long __sys_call (long sys_call); +long __sys_call1 (long sys_call, long one); +long __sys_call2 (long sys_call, long one, long two); +long __sys_call3 (long sys_call, long one, long two, long three); +long __sys_call4 (long sys_call, long one, long two, long three, long four); + // *INDENT-OFF* long _sys_call (long sys_call) { - long r; - asm ( - "mov %1,%%eax\n\t" - "int $0x80\n\t" - "mov %%eax,%0\n\t" - : "=r" (r) - : "rm" (sys_call) - : "eax" - ); + long r = __sys_call(sys_call); if (r < 0) { errno = -r; @@ -47,16 +45,7 @@ _sys_call (long sys_call) long _sys_call1 (long sys_call, long one) { - long r; - asm ( - "mov %1,%%eax\n\t" - "mov %2,%%ebx\n\t" - "int $0x80\n\t" - "mov %%eax,%0\n\t" - : "=r" (r) - : "rm" (sys_call), "rm" (one) - : "eax", "ebx" - ); + long r = __sys_call1(sys_call, one); if (r < 0) { errno = -r; @@ -70,17 +59,7 @@ _sys_call1 (long sys_call, long one) long _sys_call2 (long sys_call, long one, long two) { - long r; - asm ( - "mov %1,%%eax\n\t" - "mov %2,%%ebx\n\t" - "mov %3,%%ecx\n\t" - "int $0x80\n\t" - "mov %%eax,%0\n\t" - : "=r" (r) - : "rm" (sys_call), "rm" (one), "rm" (two) - : "eax", "ebx", "ecx" - ); + long r = __sys_call2(sys_call, one, two); if (r < 0) { errno = -r; @@ -94,18 +73,7 @@ _sys_call2 (long sys_call, long one, long two) long _sys_call3 (long sys_call, long one, long two, long three) { - long r; - asm ( - "mov %2,%%ebx\n\t" - "mov %3,%%ecx\n\t" - "mov %4,%%edx\n\t" - "mov %1,%%eax\n\t" - "int $0x80\n\t" - "mov %%eax,%0\n\t" - : "=r" (r) - : "rm" (sys_call), "rm" (one), "rm" (two), "rm" (three) - : "eax", "ebx", "ecx", "edx" - ); + long r = __sys_call3(sys_call, one, two, three); if (r < 0) { errno = -r; @@ -119,19 +87,7 @@ _sys_call3 (long sys_call, long one, long two, long three) long _sys_call4 (long sys_call, long one, long two, long three, long four) { - long r; - asm ( - "mov %2,%%ebx\n\t" - "mov %3,%%ecx\n\t" - "mov %4,%%edx\n\t" - "mov %5,%%esi\n\t" - "mov %1,%%eax\n\t" - "int $0x80\n\t" - "mov %%eax,%0\n\t" - : "=r" (r) - : "rm" (sys_call), "rm" (one), "rm" (two), "rm" (three), "rm" (four) - : "eax", "ebx", "ecx", "edx", "esi" - ); + long r = __sys_call4(sys_call, one, two, three, four); if (r < 0) { errno = -r; diff --git a/lib/linux/x86-mes-mescc/syscall-internal.c b/lib/linux/x86-mes-mescc/syscall-internal.c new file mode 100644 index 00000000..cf115810 --- /dev/null +++ b/lib/linux/x86-mes-mescc/syscall-internal.c @@ -0,0 +1,77 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +int +__sys_call (int sys_call) +{ + asm ("mov____0x8(%ebp),%eax !8"); + asm ("int____$0x80"); +} + +int +__sys_call1 (int sys_call, int one) +{ + asm ("mov____0x8(%ebp),%eax !8"); + asm ("mov____0x8(%ebp),%ebx !12"); + asm ("int____$0x80"); +} + +int +__sys_call2 (int sys_call, int one, int two) +{ + asm ("mov____0x8(%ebp),%eax !8"); + asm ("mov____0x8(%ebp),%ebx !12"); + asm ("mov____0x8(%ebp),%ecx !16"); + asm ("int____$0x80"); +} + +int +__sys_call3 (int sys_call, int one, int two, int three) +{ + asm ("mov____0x8(%ebp),%eax !8"); + asm ("mov____0x8(%ebp),%ebx !12"); + asm ("mov____0x8(%ebp),%ecx !16"); + asm ("mov____0x8(%ebp),%edx !20"); + asm ("int____$0x80"); +} + +int +__sys_call4 (int sys_call, int one, int two, int three, int four) +{ + asm ("mov____0x8(%ebp),%eax !8"); + asm ("mov____0x8(%ebp),%ebx !12"); + asm ("mov____0x8(%ebp),%ecx !16"); + asm ("mov____0x8(%ebp),%edx !20"); + asm ("mov____0x8(%ebp),%esi !24"); + asm ("int____$0x80"); +} + +/* Returns < 0 on error (errno-like value from kernel), or 0 on success */ +int +__raise(int signum) +{ + int pid = __sys_call (SYS_getpid); + if (pid < 0) + return pid; + else + return __sys_call2 (SYS_kill, pid, signum); +} diff --git a/lib/linux/x86-mes-mescc/syscall.c b/lib/linux/x86-mes-mescc/syscall.c index 5d88cca5..2488e860 100644 --- a/lib/linux/x86-mes-mescc/syscall.c +++ b/lib/linux/x86-mes-mescc/syscall.c @@ -21,50 +21,11 @@ #include #include -int -__sys_call (int sys_call) -{ - asm ("mov____0x8(%ebp),%eax !8"); - asm ("int____$0x80"); -} - -int -__sys_call1 (int sys_call, int one) -{ - asm ("mov____0x8(%ebp),%eax !8"); - asm ("mov____0x8(%ebp),%ebx !12"); - asm ("int____$0x80"); -} - -int -__sys_call2 (int sys_call, int one, int two) -{ - asm ("mov____0x8(%ebp),%eax !8"); - asm ("mov____0x8(%ebp),%ebx !12"); - asm ("mov____0x8(%ebp),%ecx !16"); - asm ("int____$0x80"); -} - -int -__sys_call3 (int sys_call, int one, int two, int three) -{ - asm ("mov____0x8(%ebp),%eax !8"); - asm ("mov____0x8(%ebp),%ebx !12"); - asm ("mov____0x8(%ebp),%ecx !16"); - asm ("mov____0x8(%ebp),%edx !20"); - asm ("int____$0x80"); -} - -int -__sys_call4 (int sys_call, int one, int two, int three, int four) -{ - asm ("mov____0x8(%ebp),%eax !8"); - asm ("mov____0x8(%ebp),%ebx !12"); - asm ("mov____0x8(%ebp),%ecx !16"); - asm ("mov____0x8(%ebp),%edx !20"); - asm ("mov____0x8(%ebp),%esi !24"); - asm ("int____$0x80"); -} +int __sys_call (int sys_call); +int __sys_call1 (int sys_call, int one); +int __sys_call2 (int sys_call, int one, int two); +int __sys_call3 (int sys_call, int one, int two, int three); +int __sys_call4 (int sys_call, int one, int two, int three, int four); int _sys_call (int sys_call) diff --git a/lib/mes/div.c b/lib/mes/div.c index fa61a691..352acc07 100644 --- a/lib/mes/div.c +++ b/lib/mes/div.c @@ -20,11 +20,9 @@ */ #include -#include #include #include - -/*#define LONG_MIN (-(~0UL>>1)-1)*/ +#include typedef struct { @@ -32,15 +30,21 @@ typedef struct long rem; } ldiv_t; -void __mesabi_div0(void) +int __raise(int); + +void +__mesabi_div0 (void) { - eputs(" ***MES C LIB*** divide by zero numerator="); - eputs("\n"); - assert(0); + if (__raise(SIGFPE) < 0) { /* could not raise SIGFPE */ + /* Fail in any way possible */ + unsigned char* x = (unsigned char*) 0; + *x = 2; + } } -/* Compare gcc: __udivdi3 */ -unsigned long __mesabi_uldiv(unsigned long a, unsigned long b, unsigned long* remainder) +/* Compare gcc: __udivmoddi4 */ +unsigned long +__mesabi_uldiv (unsigned long a, unsigned long b, unsigned long* remainder) { unsigned long tmp; if (!remainder) @@ -63,11 +67,12 @@ unsigned long __mesabi_uldiv(unsigned long a, unsigned long b, unsigned long* re /* Note: Rounds towards zero. Maintainer: Be careful to satisfy quot * b + rem == a. That means that rem can be negative. */ -ldiv_t ldiv(long a, long b) +ldiv_t __mesabi_ldiv(long a, long b) { ldiv_t result; int negate_result = (a < 0) ^ (b < 0); - assert(b != LONG_MIN); + if (b == LONG_MIN) + __mesabi_div0(); if (a != LONG_MIN) { int negative_a = (a < 0); @@ -108,3 +113,50 @@ ldiv_t ldiv(long a, long b) return result; } } + +#if __GNUC__ && !SYSTEM_LIBC && __arm__ +// ...-binutils-2.31.1/bin/ld: hash.o: in function `hash_cstring': +// hash.c:(.text+0x56): undefined reference to `__aeabi_idivmod' +// ...-binutils-2.31.1/bin/ld: math.o: in function `divide': +// math.c:(.text+0x516): undefined reference to `__aeabi_idiv' +// ...-binutils-2.31.1/bin/ld: math.o: in function `modulo': +// math.c:(.text+0x5d2): undefined reference to `__aeabi_idivmod' +// ...-binutils-2.31.1/bin/ld: gcc-lib/libc.a(ntoab.o): in function `ntoab': +// ntoab.c:(.text+0x54): undefined reference to `__aeabi_uidivmod' +// ...-binutils-2.31.1/bin/ld: ntoab.c:(.text+0x62): undefined reference to `__aeabi_uidiv' + +/* Result: r0: quotient; r1: remainder */ +long +__aeabi_idivmod (long a, long b) +{ + ldiv_t result = __mesabi_ldiv(a, b); + register long rem_result asm("r1"); + rem_result = result.rem; + return result.quot; +} + +long +__aeabi_idiv (long a, long b) +{ + ldiv_t result = __mesabi_ldiv(a, b); + return result.quot; +} + +/* Result: r0: quotient; r1: remainder */ +unsigned long +__aeabi_uidivmod (unsigned long a, unsigned long b) +{ + unsigned long quot; + unsigned long rem; + register unsigned long rem_result asm("r1"); + quot = __mesabi_uldiv (a, b, &rem); + rem_result = rem; + return quot; +} + +unsigned long +__aeabi_uidiv (unsigned long a, unsigned long b) +{ + return __mesabi_uldiv (a, b, 0); +} +#endif // __GNUC__ && !SYSTEM_LIBC && __arm__ diff --git a/module/mescc.scm b/module/mescc.scm index 2967c014..9772d858 100644 --- a/module/mescc.scm +++ b/module/mescc.scm @@ -116,9 +116,9 @@ Options: -L DIR append DIR to library path -l LIBNAME link with LIBNAME -m BITS compile for BITS bits [32] - -nodefaultlibs do not use libc.o when linking + -nodefaultlibs do not use libc.o nor libmescc.a when linking -nostartfiles do not use crt1.o when linking - -nostdlib do not use crt1.o or libc.o when linking + -nostdlib do not use crt1.o or libc.o or libmescc.a when linking -o FILE write output to FILE -O LEVEL use optimizing LEVEL -S preprocess and compile only; do not assemble or link diff --git a/module/mescc/mescc.scm b/module/mescc/mescc.scm index 9e0b9db2..d54d620d 100644 --- a/module/mescc/mescc.scm +++ b/module/mescc/mescc.scm @@ -143,8 +143,9 @@ (append hex2-files (list (infos->hex2 options hex2-file-name infos))))) (default-libraries (if (or (option-ref options 'nodefaultlibs #f) - (option-ref options 'nostdlib #f)) '() - '("c"))) + (option-ref options 'nostdlib #f)) + '() + '("mescc" "c"))) (libraries (filter-map (multi-opt 'library) options)) (libraries (delete-duplicates (append libraries default-libraries))) (hex2-libraries (map (cut find-library options ".a" <>) libraries))