1 /* DEC Alpha division
and remainder support.
2 Copyright
(C
) 1994, 1999 Free Software Foundation
, Inc.
4 This file is free software
; you can redistribute it and/or modify it
5 under the terms of the GNU General
Public License as published by the
6 Free Software Foundation
; either version 2, or (at your option) any
9 In addition to the permissions
in the GNU General
Public License
, the
10 Free Software Foundation gives you unlimited permission to link the
11 compiled version of
this file
into combinations with other programs
,
12 and to distribute those combinations without any restriction coming
13 from the use of
this file.
(The General
Public License restrictions
14 do apply
in other respects
; for example, they cover modification of
15 the file
, and distribution when
not linked
into a combine
18 This file is distributed
in the hope that it will be useful
, but
19 WITHOUT ANY WARRANTY
; without even the implied warranty of
20 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General
Public License for more details.
23 You should have received a copy of the GNU General
Public License
24 along with
this program
; see the file COPYING. If not, write to
25 the Free Software Foundation
, 51 Franklin Street
, Fifth Floor
,
26 Boston
, MA
02110-1301, USA.
*/
28 /* This had to be written
in assembler because the division functions
29 use a non
-standard calling convention.
31 This file provides an implementation of __divqu
, __divq
, __divlu
,
32 __divl
, __remqu
, __remq
, __remlu
and __reml. CPP macros control
35 Operation
performed: $27 := $24 o
$25, clobber
$28, return address to
36 caller
in $23, where o one of the operations.
38 The following macros need to be
defined:
40 SIZE, the number of bits
, 32 or 64.
42 TYPE, either UNSIGNED
or SIGNED
44 OPERATION
, either DIVISION
or REMAINDER
46 SPECIAL_CALLING_CONVENTION
, 0 or 1. It is useful for debugging to
47 define
this to
0. That removes the `__
' prefix to make the function
48 name not collide with the existing libc.a names, and uses the
49 standard Alpha procedure calling convention.
52 #ifndef SPECIAL_CALLING_CONVENTION
53 #define SPECIAL_CALLING_CONVENTION 1
57 #if SPECIAL_CALLING_CONVENTION
58 #define FUNCTION_NAME __divl
60 #define FUNCTION_NAME divl
64 #define OPERATION DIVISION
68 #if SPECIAL_CALLING_CONVENTION
69 #define FUNCTION_NAME __divlu
71 #define FUNCTION_NAME divlu
75 #define OPERATION DIVISION
79 #if SPECIAL_CALLING_CONVENTION
80 #define FUNCTION_NAME __divq
82 #define FUNCTION_NAME divq
86 #define OPERATION DIVISION
90 #if SPECIAL_CALLING_CONVENTION
91 #define FUNCTION_NAME __divqu
93 #define FUNCTION_NAME divqu
97 #define OPERATION DIVISION
101 #if SPECIAL_CALLING_CONVENTION
102 #define FUNCTION_NAME __reml
104 #define FUNCTION_NAME reml
108 #define OPERATION REMAINDER
112 #if SPECIAL_CALLING_CONVENTION
113 #define FUNCTION_NAME __remlu
115 #define FUNCTION_NAME remlu
118 #define TYPE UNSIGNED
119 #define OPERATION REMAINDER
123 #if SPECIAL_CALLING_CONVENTION
124 #define FUNCTION_NAME __remq
126 #define FUNCTION_NAME remq
130 #define OPERATION REMAINDER
134 #if SPECIAL_CALLING_CONVENTION
135 #define FUNCTION_NAME __remqu
137 #define FUNCTION_NAME remqu
140 #define TYPE UNSIGNED
141 #define OPERATION REMAINDER
147 #define result_sign $2
149 #if SPECIAL_CALLING_CONVENTION
161 /* Misc symbols to make alpha assembler easier to read. */
165 /* Symbols to make interface nicer. */
182 /* Under the special calling convention, we have to preserve all register
183 values but $23 and $28. */
184 #if SPECIAL_CALLING_CONVENTION
186 #if OPERATION == DIVISION
191 stq result_sign,24(sp)
195 /* If we are computing the remainder, move N to the register that is used
196 for the return value, and redefine what register is used for N. */
197 #if OPERATION == REMAINDER
203 /* Perform conversion from 32 bit types to 64 bit types. */
206 /* If there are problems with the signed case, add these instructions.
207 The caller should already have done this.
208 addl N,0,N # sign extend N
209 addl D,0,D # sign extend D
212 zap N,0xf0,N # zero extend N (caller required to sign extend)
213 zap D,0xf0,D # zero extend D
217 /* Check for divide by zero. */
224 #if OPERATION == DIVISION
229 /* Get the absolute values of N and D. */
236 /* Compute CNT = ceil(log2(N)) - ceil(log2(D)). This is the number of
237 divide iterations we will have to perform. Should you wish to optimize
238 this, check a few bits at a time, preferably using zap/zapnot. Be
239 careful though, this code runs fast fro the most common cases, when the
240 quotient is small. */
262 /* Actual divide. Could be optimized with unrolling. */
263 #if OPERATION == DIVISION
273 #if OPERATION == DIVISION
281 /* The result is now in RETREG. NOTE! It was written to RETREG using
282 either N or Q as a synonym! */
285 /* Change the sign of the result as needed. */
287 subq zero,RETREG,tmp0
288 cmovlt result_sign,tmp0,RETREG
292 /* Restore clobbered registers. */
293 #if SPECIAL_CALLING_CONVENTION
294 #if OPERATION == DIVISION
299 ldq result_sign,24(sp)
306 /* Sign extend an *unsigned* 32 bit result, as required by the Alpha
308 #if TYPE == UNSIGNED && SIZE == 32
309 /* This could be avoided by adding some CPP hair to the divide loop.
310 It is probably not worth the added complexity. */
315 #if SPECIAL_CALLING_CONVENTION