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
127 .frame sp, FRAME_SIZE, retaddr, 0
128 lda sp,-FRAME_SIZE(sp)
137 bis zero,zero,quotient
139 beq divisor,$divbyzero
141 GETSIGN(dividend,divisor,sign)
143 subq zero,dividend,tmp0
144 subq zero,divisor,tmp1
145 cmovlt dividend,tmp0,dividend
146 cmovlt divisor,tmp1,divisor
149 * Shift divisor left until either bit 63 is set or until it
150 * is at least as big as the dividend:
153 1: cmpule dividend,divisor,AT
157 addq divisor,divisor,divisor
161 2: addq mask,quotient,tmp0
162 cmpule divisor,dividend,AT
163 subq dividend,divisor,tmp1
164 srl divisor,1,divisor
166 cmovlbs AT,tmp0,quotient
167 cmovlbs AT,tmp1,dividend
171 SETSIGN(sign,result,tmp0)
172 $done: ldq arg2,0x08(sp)
177 lda sp,FRAME_SIZE(sp)
181 lda a0,GEN_INTDIV(zero)
183 bis zero,zero,result /* if trap returns, return 0 */