diff options
Diffstat (limited to 'sysdeps/alpha/ldiv.S')
-rw-r--r-- | sysdeps/alpha/ldiv.S | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/sysdeps/alpha/ldiv.S b/sysdeps/alpha/ldiv.S new file mode 100644 index 0000000..ebbe055 --- /dev/null +++ b/sysdeps/alpha/ldiv.S @@ -0,0 +1,109 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@tamu.edu) + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. */ + + +#include <sysdep.h> + +#ifdef __linux__ +# include <asm/gentrap.h> +# include <asm/pal.h> +#else +# include <machine/pal.h> +#endif + + .set noat + + .align 4 + .globl ldiv + .ent ldiv +ldiv: + .frame sp, 0, ra +#ifdef PROF + ldgp gp, 0(pv) + lda AT, _mcount + jsr AT, (AT), _mcount + .prologue 1 +#else + .prologue 0 +#endif + +#define dividend t0 +#define divisor t1 +#define mask t2 +#define quotient t3 +#define modulus t4 +#define tmp1 t5 +#define tmp2 t6 +#define compare t7 + + /* find correct sign for input to unsigned divide loop. */ + mov a1, dividend # e0 : + mov a2, divisor # .. e1 : + negq a1, tmp1 # e0 : + negq a2, tmp2 # .. e1 : + cmovlt a1, tmp1, dividend # e0 : + cmovlt a2, tmp2, divisor # .. e1 : + beq a2, $divbyzero # e1 : + unop # : + + /* shift divisor left. */ +1: cmpult divisor, modulus, compare # e0 : + blt divisor, 2f # .. e1 : + addq divisor, divisor, divisor # e0 : + addq mask, mask, mask # .. e1 : + bne compare, 1b # e1 : + unop # : + + /* start to go right again. */ +2: addq quotient, mask, tmp2 # e1 : + srl mask, 1, mask # .. e0 : + cmpule divisor, modulus, compare # e0 : + subq modulus, divisor, tmp1 # .. e1 : + cmovne compare, tmp2, quotient # e1 : + srl divisor, 1, divisor # .. e0 : + cmovne compare, tmp1, modulus # e0 : + bne mask, 2b # .. e1 : + + /* find correct sign for result. */ + xor a1, a2, compare # e0 : + negq quotient, tmp1 # .. e1 : + negq modulus, tmp2 # e0 : + cmovlt compare, tmp1, quotient # .. e1 : + cmovlt a1, tmp2, modulus # e1 : + + /* and store it away in the structure. */ +9: stq quotient, 0(a0) # .. e0 : + mov a0, v0 # e1 : + stq modulus, 8(a0) # .. e0 : + ret # e1 : + +$divbyzero: + mov a0, v0 + lda a0, GEN_INTDIV + call_pal PAL_gentrap + + /* if trap returns, return zero. */ + stq zero, 0(v0) + stq zero, 8(v0) + ret + + .end ldiv + +weak_alias(ldiv, lldiv) |