This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libgcc: Add __udivsi3 and __umodsi3 for vax-*-linux*


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@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@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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]