1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 Contributed by David Mosberger (davidm@cs.arizona.edu).
4 This file is part of the GNU C Library.
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.
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.
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. */
21 /* The current Alpha chips don't provide hardware for integer
22 division. The C compiler expects the functions
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
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. */
38 # include <asm/gentrap.h>
41 # include <machine/pal.h>
66 # define dividend result
67 # define quotient arg1
68 # define GETDIVIDEND bis arg1,zero,dividend
70 # define dividend arg1
71 # define quotient result
76 # define LONGIFYarg1 GETDIVIDEND
80 # define LONGIFYarg1 addl arg1,zero,dividend
81 # define LONGIFYarg2 addl arg2,zero,divisor
83 # define LONGIFYarg1 zapnot arg1,0x0f,dividend
84 # define LONGIFYarg2 zapnot arg2,0x0f,divisor
89 # define SETSIGN(sign,reg,tmp) subq zero,reg,tmp; cmovlt sign,tmp,reg
91 # define GETSIGN(x,y,s) bis x,zero,s
93 # define GETSIGN(x,y,s) xor x,y,s
96 # define SETSIGN(sign,reg,tmp)
97 # define GETSIGN(x,y,s)
106 #define FRAME_SIZE 0x30
121 jsr AT, (AT), _mcount
128 .frame sp, FRAME_SIZE, ra, 0
129 lda sp,-FRAME_SIZE(sp)
138 bis zero,zero,quotient
140 beq divisor,divbyzero
142 GETSIGN(dividend,divisor,sign)
144 subq zero,dividend,tmp0
145 subq zero,divisor,tmp1
146 cmovlt dividend,tmp0,dividend
147 cmovlt divisor,tmp1,divisor
150 * Shift divisor left until either bit 63 is set or until it
151 * is at least as big as the dividend:
154 1: cmpule dividend,divisor,AT
158 addq divisor,divisor,divisor
162 2: addq mask,quotient,tmp0
163 cmpule divisor,dividend,AT
164 subq dividend,divisor,tmp1
165 srl divisor,1,divisor
167 cmovlbs AT,tmp0,quotient
168 cmovlbs AT,tmp1,dividend
172 SETSIGN(sign,result,tmp0)
173 done: ldq arg2,0x08(sp)
178 lda sp,FRAME_SIZE(sp)
182 lda a0,GEN_INTDIV(zero)
184 bis zero,zero,result /* if trap returns, return 0 */