[LV] [PATCH] libgcc: Add __udivsi3 and __umodsi3 for vax-*-linux*
Maciej W. Rozycki
macro at linux-mips.org
Wed Jun 10 02:13:14 CEST 2009
Hi,
The VAX processor does not support a 32-bit unsigned division operation
in hardware. Which means appropriate SImode primitives have to be
provided by a library. What the CPU does support is a 32-bit signed
division operation and a 64-bit by 32-bit extended precision signed
division operation. According to a comment in vax.md the latter tends to
be painfully slow, so here's my proposed implementation, which takes the
following approach:
1. If both the divisor and the dividend fit in the 31-bit positive space
of signed 32-bit numbers, then the 32-bit signed division is used (as
the operation does not calculate the remainder, for the modulo
operation an additional multiplication and subtraction is performed).
2. Otherwise if the divisor only fits in the 31-bit positive space of
signed 32-bit numbers, then the 64-bit by 32-bit extended precision
signed division is used (this operation does calculate the remainder
for a change).
3. Otherwise the quotient and the remainder can only have either of two
values each, which is calculated by a single subtraction (and some
further fiddling so that the need to take a branch does not hurt
performance with more recent processor implementations).
Unlike with the BSD target, for Linux I believe there is no point in
putting either of the functions into the C library (with -ffreestanding to
be considered too), nor in using non-standard names, either of which would
make the VAX/Linux port different to all the others and thus possibly
causing portability problems. Hence the implementation introduces a
TARGET_BSD_DIVMOD macro to control the preference on how the two functions
are handled by GCC. The default is the current arrangement.
The vax-linux configuration is not capable enough for regression testing
yet, but correctness of these functions has been verified by running a
simple program testing boundary values of the dividend and the divisor and
checking that the quotient and remainder produced was correct. The two
functions are needed for further progress with the port.
gcc/
2009-06-10 Maciej W. Rozycki <macro at linux-mips.org>
* config/vax/vax.h (TARGET_BSD_DIVMOD): New macro. Set to 1.
* config/vax/linux.h (TARGET_BSD_DIVMOD): New macro. Redefine the
to 0.
* config/vax/vax.c (vax_init_libfuncs): Only redefine udiv_optab
and umod_optab if TARGET_BSD_DIVMOD.
* config/vax/lib1funcs.asm: New file.
* config/vax/t-linux: New file.
* config.gcc (vax-*-linux*): Set tmake_file to vax/t-linux.
OK to apply?
Maciej
gcc-4.5.0-20090609-vax-linux-divmod.patch
Index: gcc-4.5.0-20090609-vax-linux/gcc/config.gcc
===================================================================
--- gcc-4.5.0-20090609-vax-linux.orig/gcc/config.gcc
+++ gcc-4.5.0-20090609-vax-linux/gcc/config.gcc
@@ -2414,6 +2414,7 @@ v850-*-*)
;;
vax-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h vax/elf.h vax/linux.h"
+ tmake_file=vax/t-linux
;;
vax-*-netbsdelf*)
tm_file="${tm_file} elfos.h netbsd.h netbsd-elf.h vax/elf.h vax/netbsd-elf.h"
Index: gcc-4.5.0-20090609-vax-linux/gcc/config/vax/lib1funcs.asm
===================================================================
--- /dev/null
+++ gcc-4.5.0-20090609-vax-linux/gcc/config/vax/lib1funcs.asm
@@ -0,0 +1,92 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of GCC.
+ Contributed by Maciej W. Rozycki <macro at linux-mips.org>.
+
+ This file 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, or (at your option) any
+ later version.
+
+ This file 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef L_udivsi3
+ .text
+ .globl __udivsi3
+ .type __udivsi3, @function
+__udivsi3:
+ .word 0
+ movl 8(%ap), %r1
+ blss 0f /* Check bit #31 of divisor. */
+ movl 4(%ap), %r2
+ blss 1f /* Check bit #31 of dividend. */
+
+ /* Both zero, do a standard division. */
+
+ divl3 %r1, %r2, %r0
+ ret
+
+ /* MSB of divisor set, only 1 or 0 may result. */
+0:
+ decl %r1
+ clrl %r0
+ cmpl %r1, 4(%ap)
+ adwc $0, %r0
+ ret
+
+ /* MSB of dividend set, do an extended division. */
+1:
+ clrl %r3
+ ediv %r1, %r2, %r0, %r3
+ ret
+ .size __udivsi3, . - __udivsi3
+ .previous
+#endif
+
+#ifdef L_umodsi3
+ .text
+ .globl __umodsi3
+ .type __umodsi3, @function
+__umodsi3:
+ .word 0
+ movl 8(%ap), %r1
+ blss 0f /* Check bit #31 of divisor. */
+ movl 4(%ap), %r2
+ blss 1f /* Check bit #31 of dividend. */
+
+ /* Both zero, do a standard division. */
+
+ divl3 %r1, %r2, %r0
+ mull2 %r0, %r1
+ subl3 %r1, %r2, %r0
+ ret
+
+ /* MSB of divisor set, subtract the divisor at most once. */
+0:
+ movl 4(%ap), %r2
+ clrl %r0
+ cmpl %r2, %r1
+ sbwc $0, %r0
+ bicl2 %r0, %r1
+ subl3 %r1, %r2, %r0
+ ret
+
+ /* MSB of dividend set, do an extended division. */
+1:
+ clrl %r3
+ ediv %r1, %r2, %r3, %r0
+ ret
+ .size __umodsi3, . - __umodsi3
+ .previous
+#endif
Index: gcc-4.5.0-20090609-vax-linux/gcc/config/vax/linux.h
===================================================================
--- gcc-4.5.0-20090609-vax-linux.orig/gcc/config/vax/linux.h
+++ gcc-4.5.0-20090609-vax-linux/gcc/config/vax/linux.h
@@ -37,6 +37,10 @@ along with GCC; see the file COPYING3.
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_QMATH | MASK_G_FLOAT)
+/* Use standard names for udiv and umod libgcc calls. */
+#undef TARGET_BSD_DIVMOD
+#define TARGET_BSD_DIVMOD 0
+
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
Index: gcc-4.5.0-20090609-vax-linux/gcc/config/vax/t-linux
===================================================================
--- /dev/null
+++ gcc-4.5.0-20090609-vax-linux/gcc/config/vax/t-linux
@@ -0,0 +1,2 @@
+LIB1ASMSRC = vax/lib1funcs.asm
+LIB1ASMFUNCS = _udivsi3 _umodsi3
Index: gcc-4.5.0-20090609-vax-linux/gcc/config/vax/vax.c
===================================================================
--- gcc-4.5.0-20090609-vax-linux.orig/gcc/config/vax/vax.c
+++ gcc-4.5.0-20090609-vax-linux/gcc/config/vax/vax.c
@@ -172,8 +172,11 @@ vax_file_start (void)
static void
vax_init_libfuncs (void)
{
- set_optab_libfunc (udiv_optab, SImode, TARGET_ELF ? "*__udiv" : "*udiv");
- set_optab_libfunc (umod_optab, SImode, TARGET_ELF ? "*__urem" : "*urem");
+ if (TARGET_BSD_DIVMOD)
+ {
+ set_optab_libfunc (udiv_optab, SImode, TARGET_ELF ? "*__udiv" : "*udiv");
+ set_optab_libfunc (umod_optab, SImode, TARGET_ELF ? "*__urem" : "*urem");
+ }
}
/* This is like nonimmediate_operand with a restriction on the type of MEM. */
Index: gcc-4.5.0-20090609-vax-linux/gcc/config/vax/vax.h
===================================================================
--- gcc-4.5.0-20090609-vax-linux.orig/gcc/config/vax/vax.h
+++ gcc-4.5.0-20090609-vax-linux/gcc/config/vax/vax.h
@@ -63,6 +63,9 @@ along with GCC; see the file COPYING3.
/* Nonzero if ELF. Redefined by vax/elf.h. */
#define TARGET_ELF 0
+/* Use BSD names for udiv and umod libgcc calls. */
+#define TARGET_BSD_DIVMOD 1
+
/* Default target_flags if no switches specified. */
#ifndef TARGET_DEFAULT
_______________________________________________
Linux-Vax mailing list
Linux-Vax at mail.pergamentum.com
http://mail.pergamentum.com/mailman/listinfo/linux-vax
More information about the Vax-linux
mailing list