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, 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, 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