OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [alpha/] [lib1funcs.asm] - Blame information for rev 841

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* 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, 51 Franklin Street, Fifth Floor,
26
Boston, MA 02110-1301, USA.  */
27
 
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
177
FUNCTION_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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.