Wed May 29 00:57:37 1996 David Mosberger-Tang <davidm@azstarnet.com>
[platform/upstream/glibc.git] / sysdeps / alpha / divrem.h
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2    Contributed by David Mosberger (davidm@cs.arizona.edu).
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB.  If
18 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 Cambridge, MA 02139, USA.  */
20
21 /* The current Alpha chips don't provide hardware for integer
22 division.  The C compiler expects the functions
23
24         __divqu: 64-bit unsigned long divide
25         __remqu: 64-bit unsigned long remainder
26         __divqs/__remqs: signed 64-bit
27         __divlu/__remlu: unsigned 32-bit
28         __divls/__remls: signed 32-bit
29
30 These are not normal C functions: instead of the normal calling
31 sequence, these expect their arguments in registers t10 and t11, and
32 return the result in t12 (aka pv). Registers AT and v0 may be
33 clobbered (assembly temporary), anything else must be saved.  */
34
35 #include <sysdep.h>
36
37 #ifdef __linux__
38 # include <asm/gentrap.h>
39 # include <asm/pal.h>
40 #else
41 # include <machine/pal.h>
42 #endif
43
44 #ifdef DEBUG
45 # define arg1           a0
46 # define arg2           a1
47 # define result         v0
48 # define mask           t0
49 # define tmp0           t1
50 # define tmp1           t2
51 # define sign           t3
52 # define retaddr        ra
53 #else
54 # define arg1           t10
55 # define arg2           t11
56 # define result         t12
57 # define mask           v0
58 # define tmp0           t0
59 # define tmp1           t1
60 # define sign           t2
61 # define retaddr        t9
62 #endif
63
64 # define divisor        arg2
65 #if IS_REM
66 # define dividend       result
67 # define quotient       arg1
68 # define GETDIVIDEND    bis arg1,zero,dividend
69 #else
70 # define dividend       arg1
71 # define quotient       result
72 # define GETDIVIDEND
73 #endif
74
75 #if SIZE == 8
76 # define LONGIFYarg1    GETDIVIDEND
77 # define LONGIFYarg2
78 #else
79 # if SIGNED
80 #  define LONGIFYarg1   addl    arg1,zero,dividend
81 #  define LONGIFYarg2   addl    arg2,zero,divisor
82 # else
83 #  define LONGIFYarg1   zapnot  arg1,0x0f,dividend
84 #  define LONGIFYarg2   zapnot  arg2,0x0f,divisor
85 # endif
86 #endif
87
88 #if SIGNED
89 # define SETSIGN(sign,reg,tmp)  subq zero,reg,tmp; cmovlt sign,tmp,reg
90 # if IS_REM
91 #  define GETSIGN(x,y,s)        bis     x,zero,s
92 # else
93 #  define GETSIGN(x,y,s)        xor     x,y,s
94 # endif
95 #else
96 # define SETSIGN(sign,reg,tmp)
97 # define GETSIGN(x,y,s)
98 #endif
99
100         .set noreorder
101         .set noat
102
103         .ent FUNC_NAME
104         .globl FUNC_NAME
105
106 #define FRAME_SIZE      0x30
107
108         .align 5
109 FUNC_NAME:
110 #ifdef PROF
111         lda     sp, -0x18(sp)
112         stq     ra, 0x00(sp)
113         stq     pv, 0x08(sp)
114         stq     gp, 0x10(sp)
115
116         br      AT, 1f
117 1:      ldgp    gp, 0(AT)
118         lda     AT, _mcount
119
120         mov     retaddr, ra
121         jsr     AT, (AT), _mcount
122
123         ldq     ra, 0x00(sp)
124         ldq     pv, 0x08(sp)
125         ldq     gp, 0x10(sp)
126         lda     sp, 0x18(sp)
127 #endif
128         .frame  sp, FRAME_SIZE, ra, 0
129         lda     sp,-FRAME_SIZE(sp)
130         .prologue 1
131         stq     arg1,0x00(sp)
132         LONGIFYarg1
133         stq     arg2,0x08(sp)
134         LONGIFYarg2
135         stq     mask,0x10(sp)
136         bis     zero,1,mask
137         stq     tmp0,0x18(sp)
138         bis     zero,zero,quotient
139         stq     tmp1,0x20(sp)
140         beq     divisor,divbyzero
141         stq     sign,0x28(sp)
142         GETSIGN(dividend,divisor,sign)
143 #if SIGNED
144         subq    zero,dividend,tmp0
145         subq    zero,divisor,tmp1
146         cmovlt  dividend,tmp0,dividend
147         cmovlt  divisor,tmp1,divisor
148 #endif
149         /*
150          * Shift divisor left until either bit 63 is set or until it
151          * is at least as big as the dividend:
152          */
153         .align  3
154 1:      cmpule  dividend,divisor,AT
155         blt     divisor,2f
156         blbs    AT,2f
157         addq    mask,mask,mask
158         addq    divisor,divisor,divisor
159         br      1b
160
161         .align  3
162 2:      addq    mask,quotient,tmp0
163         cmpule  divisor,dividend,AT
164         subq    dividend,divisor,tmp1
165         srl     divisor,1,divisor
166         srl     mask,1,mask
167         cmovlbs AT,tmp0,quotient
168         cmovlbs AT,tmp1,dividend
169         bne     mask,2b
170
171         ldq     arg1,0x00(sp)
172         SETSIGN(sign,result,tmp0)
173 done:   ldq     arg2,0x08(sp)
174         ldq     mask,0x10(sp)
175         ldq     tmp0,0x18(sp)
176         ldq     tmp1,0x20(sp)
177         ldq     sign,0x28(sp)
178         lda     sp,FRAME_SIZE(sp)
179         ret     zero,(retaddr),0
180
181 divbyzero:
182         lda     a0,GEN_INTDIV(zero)
183         call_pal PAL_gentrap
184         bis     zero,zero,result        /* if trap returns, return 0 */
185         ldq     arg1,0x00(sp)
186         br      done
187
188         END(FUNC_NAME)