[LV] [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 _______________________________________________ Linux-Vax mailing list Linux-Vax@mail.pergamentum.com http://mail.pergamentum.com/mailman/listinfo/linux-vax
Teilnehmer (2)
-
Jan-Benedict Glaw
-
Maciej W. Rozycki