]> gcc.gnu.org Git - gcc.git/blame - gcc/config/alpha/lib1funcs.asm
alpha-protos.h (alpha_output_mi_thunk_osf): Update signature to match target.h.
[gcc.git] / gcc / config / alpha / lib1funcs.asm
CommitLineData
ff1555f8
DT
1/* DEC Alpha division and remainder support.
2 Copyright (C) 1994, 1999 Free Software Foundation, Inc.
3
4This file is free software; you can redistribute it and/or modify it
5under the terms of the GNU General Public License as published by the
6Free Software Foundation; either version 2, or (at your option) any
7later version.
8
9In addition to the permissions in the GNU General Public License, the
10Free Software Foundation gives you unlimited permission to link the
f7af368f
JL
11compiled version of this file into combinations with other programs,
12and to distribute those combinations without any restriction coming
13from the use of this file. (The General Public License restrictions
14do apply in other respects; for example, they cover modification of
15the file, and distribution when not linked into a combine
16executable.)
ff1555f8
DT
17
18This file is distributed in the hope that it will be useful, but
19WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; see the file COPYING. If not, write to
9f2f9eb6
JM
25the Free Software Foundation, 59 Temple Place - Suite 330,
26Boston, MA 02111-1307, USA. */
ff1555f8 27
ff1555f8
DT
28/* This had to be written in assembler because the division functions
29 use a non-standard calling convention.
30
31 This file provides an implementation of __divqu, __divq, __divlu,
32 __divl, __remqu, __remq, __remlu and __reml. CPP macros control
33 the exact operation.
34
35 Operation performed: $27 := $24 o $25, clobber $28, return address to
36 caller in $23, where o one of the operations.
37
38 The following macros need to be defined:
39
40 SIZE, the number of bits, 32 or 64.
41
42 TYPE, either UNSIGNED or SIGNED
43
44 OPERATION, either DIVISION or REMAINDER
45
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.
50*/
51
52#ifndef SPECIAL_CALLING_CONVENTION
53#define SPECIAL_CALLING_CONVENTION 1
54#endif
55
56#ifdef L_divl
57#if SPECIAL_CALLING_CONVENTION
58#define FUNCTION_NAME __divl
59#else
60#define FUNCTION_NAME divl
61#endif
62#define SIZE 32
63#define TYPE SIGNED
64#define OPERATION DIVISION
65#endif
66
67#ifdef L_divlu
68#if SPECIAL_CALLING_CONVENTION
69#define FUNCTION_NAME __divlu
70#else
71#define FUNCTION_NAME divlu
72#endif
73#define SIZE 32
74#define TYPE UNSIGNED
75#define OPERATION DIVISION
76#endif
77
78#ifdef L_divq
79#if SPECIAL_CALLING_CONVENTION
80#define FUNCTION_NAME __divq
81#else
82#define FUNCTION_NAME divq
83#endif
84#define SIZE 64
85#define TYPE SIGNED
86#define OPERATION DIVISION
87#endif
88
89#ifdef L_divqu
90#if SPECIAL_CALLING_CONVENTION
91#define FUNCTION_NAME __divqu
92#else
93#define FUNCTION_NAME divqu
94#endif
95#define SIZE 64
96#define TYPE UNSIGNED
97#define OPERATION DIVISION
98#endif
99
100#ifdef L_reml
101#if SPECIAL_CALLING_CONVENTION
102#define FUNCTION_NAME __reml
103#else
104#define FUNCTION_NAME reml
105#endif
106#define SIZE 32
107#define TYPE SIGNED
108#define OPERATION REMAINDER
109#endif
110
111#ifdef L_remlu
112#if SPECIAL_CALLING_CONVENTION
113#define FUNCTION_NAME __remlu
114#else
115#define FUNCTION_NAME remlu
116#endif
117#define SIZE 32
118#define TYPE UNSIGNED
119#define OPERATION REMAINDER
120#endif
121
122#ifdef L_remq
123#if SPECIAL_CALLING_CONVENTION
124#define FUNCTION_NAME __remq
125#else
126#define FUNCTION_NAME remq
127#endif
128#define SIZE 64
129#define TYPE SIGNED
130#define OPERATION REMAINDER
131#endif
132
133#ifdef L_remqu
134#if SPECIAL_CALLING_CONVENTION
135#define FUNCTION_NAME __remqu
136#else
137#define FUNCTION_NAME remqu
138#endif
139#define SIZE 64
140#define TYPE UNSIGNED
141#define OPERATION REMAINDER
142#endif
143
144#define tmp0 $3
145#define tmp1 $28
146#define cnt $1
147#define result_sign $2
148
149#if SPECIAL_CALLING_CONVENTION
150#define N $24
151#define D $25
152#define Q RETREG
153#define RETREG $27
154#else
155#define N $16
156#define D $17
157#define Q RETREG
158#define RETREG $0
159#endif
160
161/* Misc symbols to make alpha assembler easier to read. */
162#define zero $31
163#define sp $30
164
165/* Symbols to make interface nicer. */
166#define UNSIGNED 0
167#define SIGNED 1
168#define DIVISION 0
169#define REMAINDER 1
170
171 .set noreorder
172 .set noat
173.text
174 .align 3
175 .globl FUNCTION_NAME
176 .ent FUNCTION_NAME
177FUNCTION_NAME:
178
179 .frame $30,0,$26,0
180 .prologue 0
181
182/* Under the special calling convention, we have to preserve all register
183 values but $23 and $28. */
184#if SPECIAL_CALLING_CONVENTION
185 lda sp,-64(sp)
186#if OPERATION == DIVISION
187 stq N,0(sp)
188#endif
189 stq D,8(sp)
190 stq cnt,16(sp)
191 stq result_sign,24(sp)
192 stq tmp0,32(sp)
193#endif
194
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
198 bis N,N,RETREG
199#undef N
200#define N RETREG
201#endif
202
203/* Perform conversion from 32 bit types to 64 bit types. */
204#if SIZE == 32
205#if TYPE == SIGNED
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
210 */
211#else /* UNSIGNED */
212 zap N,0xf0,N # zero extend N (caller required to sign extend)
213 zap D,0xf0,D # zero extend D
214#endif
215#endif
216
217/* Check for divide by zero. */
218 bne D,$34
219 lda $16,-2(zero)
220 call_pal 0xaa
221$34:
222
223#if TYPE == SIGNED
224#if OPERATION == DIVISION
225 xor N,D,result_sign
226#else
227 bis N,N,result_sign
228#endif
229/* Get the absolute values of N and D. */
230 subq zero,N,tmp0
231 cmovlt N,tmp0,N
232 subq zero,D,tmp0
233 cmovlt D,tmp0,D
234#endif
235
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. */
241 bge N,$35
242 bis zero,1,cnt
243 blt D,$40
244 .align 3
245$39: addq D,D,D
246 addl cnt,1,cnt
247 bge D,$39
248 br zero,$40
249$35: cmpult N,D,tmp0
250 bis zero,zero,cnt
251 bne tmp0,$42
252 .align 3
253$44: addq D,D,D
254 cmpult N,D,tmp0
255 addl cnt,1,cnt
256 beq tmp0,$44
257$42: srl D,1,D
258$40:
259 subl cnt,1,cnt
260
261
262/* Actual divide. Could be optimized with unrolling. */
263#if OPERATION == DIVISION
264 bis zero,zero,Q
265#endif
266 blt cnt,$46
267 .align 3
268$49: cmpule D,N,tmp1
269 subq N,D,tmp0
270 srl D,1,D
271 subl cnt,1,cnt
272 cmovne tmp1,tmp0,N
273#if OPERATION == DIVISION
274 addq Q,Q,Q
275 bis Q,tmp1,Q
276#endif
277 bge cnt,$49
278$46:
279
280
281/* The result is now in RETREG. NOTE! It was written to RETREG using
282 either N or Q as a synonym! */
283
284
285/* Change the sign of the result as needed. */
286#if TYPE == SIGNED
287 subq zero,RETREG,tmp0
288 cmovlt result_sign,tmp0,RETREG
289#endif
290
291
292/* Restore clobbered registers. */
293#if SPECIAL_CALLING_CONVENTION
294#if OPERATION == DIVISION
295 ldq N,0(sp)
296#endif
297 ldq D,8(sp)
298 ldq cnt,16(sp)
299 ldq result_sign,24(sp)
300 ldq tmp0,32(sp)
301
302 lda sp,64(sp)
303#endif
304
305
306/* Sign extend an *unsigned* 32 bit result, as required by the Alpha
307 conventions. */
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. */
311 addl RETREG,0,RETREG
312#endif
313
314
315#if SPECIAL_CALLING_CONVENTION
316 ret zero,($23),1
317#else
318 ret zero,($26),1
319#endif
320 .end FUNCTION_NAME
This page took 0.678262 seconds and 5 git commands to generate.