OSDN Git Service

* config/i386/i386.c (ix86_expand_setcc): Don't use method 0
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / lib1funcs.asm
1 /* DEC Alpha division and remainder support.
2    Copyright (C) 1994, 1999 Free Software Foundation, Inc.
3
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
7 later version.
8
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
16 executable.)
17
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.
22
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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
26
27 /* This had to be written in assembler because the division functions 
28    use a non-standard calling convention. 
29
30    This file provides an implementation of __divqu, __divq, __divlu, 
31    __divl, __remqu, __remq, __remlu and __reml.  CPP macros control
32    the exact operation.
33
34    Operation performed: $27 := $24 o $25, clobber $28, return address to
35    caller in $23, where o one of the operations.
36
37    The following macros need to be defined: 
38
39         SIZE, the number of bits, 32 or 64.
40
41         TYPE, either UNSIGNED or SIGNED
42
43         OPERATION, either DIVISION or REMAINDER
44    
45         SPECIAL_CALLING_CONVENTION, 0 or 1.  It is useful for debugging to
46         define this to 0.  That removes the `__' prefix to make the function
47         name not collide with the existing libc.a names, and uses the
48         standard Alpha procedure calling convention.
49 */
50
51 #ifndef SPECIAL_CALLING_CONVENTION
52 #define SPECIAL_CALLING_CONVENTION 1
53 #endif
54
55 #ifdef L_divl
56 #if SPECIAL_CALLING_CONVENTION
57 #define FUNCTION_NAME __divl
58 #else
59 #define FUNCTION_NAME divl
60 #endif
61 #define SIZE 32
62 #define TYPE SIGNED
63 #define OPERATION DIVISION
64 #endif
65
66 #ifdef L_divlu
67 #if SPECIAL_CALLING_CONVENTION
68 #define FUNCTION_NAME __divlu
69 #else
70 #define FUNCTION_NAME divlu
71 #endif
72 #define SIZE 32
73 #define TYPE UNSIGNED
74 #define OPERATION DIVISION
75 #endif
76
77 #ifdef L_divq
78 #if SPECIAL_CALLING_CONVENTION
79 #define FUNCTION_NAME __divq
80 #else
81 #define FUNCTION_NAME divq
82 #endif
83 #define SIZE 64
84 #define TYPE SIGNED
85 #define OPERATION DIVISION
86 #endif
87
88 #ifdef L_divqu
89 #if SPECIAL_CALLING_CONVENTION
90 #define FUNCTION_NAME __divqu
91 #else
92 #define FUNCTION_NAME divqu
93 #endif
94 #define SIZE 64
95 #define TYPE UNSIGNED
96 #define OPERATION DIVISION
97 #endif
98
99 #ifdef L_reml
100 #if SPECIAL_CALLING_CONVENTION
101 #define FUNCTION_NAME __reml
102 #else
103 #define FUNCTION_NAME reml
104 #endif
105 #define SIZE 32
106 #define TYPE SIGNED
107 #define OPERATION REMAINDER
108 #endif
109
110 #ifdef L_remlu
111 #if SPECIAL_CALLING_CONVENTION
112 #define FUNCTION_NAME __remlu
113 #else
114 #define FUNCTION_NAME remlu
115 #endif
116 #define SIZE 32
117 #define TYPE UNSIGNED
118 #define OPERATION REMAINDER
119 #endif
120
121 #ifdef L_remq
122 #if SPECIAL_CALLING_CONVENTION
123 #define FUNCTION_NAME __remq
124 #else
125 #define FUNCTION_NAME remq
126 #endif
127 #define SIZE 64
128 #define TYPE SIGNED
129 #define OPERATION REMAINDER
130 #endif
131
132 #ifdef L_remqu
133 #if SPECIAL_CALLING_CONVENTION
134 #define FUNCTION_NAME __remqu
135 #else
136 #define FUNCTION_NAME remqu
137 #endif
138 #define SIZE 64
139 #define TYPE UNSIGNED
140 #define OPERATION REMAINDER
141 #endif
142
143 #define tmp0 $3
144 #define tmp1 $28
145 #define cnt $1
146 #define result_sign $2
147
148 #if SPECIAL_CALLING_CONVENTION
149 #define N $24
150 #define D $25
151 #define Q RETREG
152 #define RETREG $27
153 #else
154 #define N $16
155 #define D $17
156 #define Q RETREG
157 #define RETREG $0
158 #endif
159
160 /* Misc symbols to make alpha assembler easier to read.  */
161 #define zero $31
162 #define sp $30
163
164 /* Symbols to make interface nicer.  */
165 #define UNSIGNED 0
166 #define SIGNED 1
167 #define DIVISION 0
168 #define REMAINDER 1
169
170         .set noreorder
171         .set noat
172 .text
173         .align 3
174         .globl FUNCTION_NAME
175         .ent FUNCTION_NAME
176 FUNCTION_NAME:
177
178         .frame  $30,0,$26,0
179         .prologue 0
180
181 /* Under the special calling convention, we have to preserve all register
182    values but $23 and $28.  */
183 #if SPECIAL_CALLING_CONVENTION
184         lda     sp,-64(sp)
185 #if OPERATION == DIVISION
186         stq     N,0(sp)
187 #endif
188         stq     D,8(sp)
189         stq     cnt,16(sp)
190         stq     result_sign,24(sp)
191         stq     tmp0,32(sp)
192 #endif
193
194 /* If we are computing the remainder, move N to the register that is used
195    for the return value, and redefine what register is used for N.  */
196 #if OPERATION == REMAINDER
197         bis     N,N,RETREG
198 #undef N
199 #define N RETREG
200 #endif
201
202 /* Perform conversion from 32 bit types to 64 bit types.  */
203 #if SIZE == 32
204 #if TYPE == SIGNED
205         /* If there are problems with the signed case, add these instructions.
206            The caller should already have done this.
207         addl    N,0,N           # sign extend N
208         addl    D,0,D           # sign extend D
209         */
210 #else /* UNSIGNED */
211         zap     N,0xf0,N        # zero extend N (caller required to sign extend)
212         zap     D,0xf0,D        # zero extend D
213 #endif
214 #endif
215
216 /* Check for divide by zero.  */
217         bne     D,$34
218         lda     $16,-2(zero)
219         call_pal 0xaa
220 $34:
221
222 #if TYPE == SIGNED
223 #if OPERATION == DIVISION
224         xor     N,D,result_sign
225 #else
226         bis     N,N,result_sign
227 #endif
228 /* Get the absolute values of N and D.  */
229         subq    zero,N,tmp0
230         cmovlt  N,tmp0,N
231         subq    zero,D,tmp0
232         cmovlt  D,tmp0,D
233 #endif
234
235 /* Compute CNT = ceil(log2(N)) - ceil(log2(D)).  This is the number of
236    divide iterations we will have to perform.  Should you wish to optimize
237    this, check a few bits at a time, preferably using zap/zapnot.  Be
238    careful though, this code runs fast fro the most common cases, when the
239    quotient is small.  */
240         bge     N,$35
241         bis     zero,1,cnt
242         blt     D,$40
243         .align  3
244 $39:    addq    D,D,D
245         addl    cnt,1,cnt
246         bge     D,$39
247         br      zero,$40
248 $35:    cmpult  N,D,tmp0
249         bis     zero,zero,cnt
250         bne     tmp0,$42
251         .align  3
252 $44:    addq    D,D,D
253         cmpult  N,D,tmp0
254         addl    cnt,1,cnt
255         beq     tmp0,$44
256 $42:    srl     D,1,D
257 $40:
258         subl    cnt,1,cnt
259
260
261 /* Actual divide.  Could be optimized with unrolling.  */
262 #if OPERATION == DIVISION
263         bis     zero,zero,Q
264 #endif
265         blt     cnt,$46
266         .align  3
267 $49:    cmpule  D,N,tmp1
268         subq    N,D,tmp0
269         srl     D,1,D
270         subl    cnt,1,cnt
271         cmovne  tmp1,tmp0,N
272 #if OPERATION == DIVISION
273         addq    Q,Q,Q
274         bis     Q,tmp1,Q
275 #endif
276         bge     cnt,$49
277 $46:
278
279
280 /* The result is now in RETREG.  NOTE!  It was written to RETREG using
281    either N or Q as a synonym!  */
282
283
284 /* Change the sign of the result as needed.  */
285 #if TYPE == SIGNED
286         subq    zero,RETREG,tmp0
287         cmovlt  result_sign,tmp0,RETREG
288 #endif
289
290
291 /* Restore clobbered registers.  */
292 #if SPECIAL_CALLING_CONVENTION
293 #if OPERATION == DIVISION
294         ldq     N,0(sp)
295 #endif
296         ldq     D,8(sp)
297         ldq     cnt,16(sp)
298         ldq     result_sign,24(sp)
299         ldq     tmp0,32(sp)
300
301         lda     sp,64(sp)
302 #endif
303
304
305 /* Sign extend an *unsigned* 32 bit result, as required by the Alpha
306    conventions.  */
307 #if TYPE == UNSIGNED && SIZE == 32
308         /* This could be avoided by adding some CPP hair to the divide loop.
309            It is probably not worth the added complexity.    */
310         addl    RETREG,0,RETREG
311 #endif
312
313
314 #if SPECIAL_CALLING_CONVENTION
315         ret     zero,($23),1
316 #else
317         ret     zero,($26),1
318 #endif
319         .end    FUNCTION_NAME