Support cancellation in librt.
[glibc.git] / sysdeps / alpha / div.S
blob2bc3d56a113fd20a544aad0b207eff951ecbf5ee
1 /* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Richard Henderson <rth@tamu.edu>.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
22 #ifdef __linux__
23 # include <asm/gentrap.h>
24 # include <asm/pal.h>
25 #else
26 # include <machine/pal.h>
27 #endif
29         .set noat
31         .align 4
32         .globl div
33         .ent div
34 div:
35         .frame sp, 0, ra
36 #ifdef PROF
37         ldgp    gp, 0(pv)
38         lda     AT, _mcount
39         jsr     AT, (AT), _mcount
40         .prologue 1
41 #else
42         .prologue 0
43 #endif
45 #define divisor   t1
46 #define mask      t2
47 #define quotient  t3
48 #define modulus   t4
49 #define tmp1      t5
50 #define tmp2      t6
51 #define compare   t7
53         /* find correct sign for input to unsigned divide loop. */
54         negl    a1, modulus                     # e0    :
55         negl    a2, divisor                     # .. e1 :
56         sextl   a1, a1                          # e0    :
57         sextl   a2, a2                          # .. e1 :
58         mov     zero, quotient                  # e0    :
59         mov     1, mask                         # .. e1 :
60         cmovge  a1, a1, modulus                 # e0    :
61         cmovge  a2, a2, divisor                 # .. e1 :
62         beq     a2, $divbyzero                  # e1    :
63         unop                                    #       :
65         /* shift divisor left, using 3-bit shifts for 32-bit divides as we
66            can't overflow.  Three-bit shifts will result in looping three
67            times less here, but can result in two loops more later.  Thus
68            using a large shift isn't worth it (and s8addq pairs better than
69            a shift).  */
71 1:      cmpult  divisor, modulus, compare       # e0    :
72         s8addq  divisor, zero, divisor          # .. e1 :
73         s8addq  mask, zero, mask                # e0    :
74         bne     compare, 1b                     # .. e1 :
76         /* start to go right again. */
77 2:      addq    quotient, mask, tmp2            # e1    :
78         srl     mask, 1, mask                   # .. e0 :
79         cmpule  divisor, modulus, compare       # e0    :
80         subq    modulus, divisor, tmp1          # .. e1 :
81         cmovne  compare, tmp2, quotient         # e1    :
82         srl     divisor, 1, divisor             # .. e0 :
83         cmovne  compare, tmp1, modulus          # e0    :
84         bne     mask, 2b                        # .. e1 :
86         /* find correct sign for result.  */
87         xor     a1, a2, compare                 # e0    :
88         negl    quotient, tmp1                  # .. e1 :
89         negl    modulus, tmp2                   # e0    :
90         cmovlt  compare, tmp1, quotient         # .. e1 :
91         cmovlt  a1, tmp2, modulus               # e1    :
93         /* and store it away in the structure.  */
94         stl     quotient, 0(a0)                 # .. e0 :
95         mov     a0, v0                          # e1    :
96         stl     modulus, 4(a0)                  # .. e0 :
97         ret                                     # e1    :
99 $divbyzero:
100         mov     a0, v0
101         ldiq    a0, GEN_INTDIV
102         call_pal PAL_gentrap
104         /* if trap returns, return zero.  */
105         stl     zero, 0(v0)
106         stl     zero, 4(v0)
107         ret
109         .end div