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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [sysdeps/] [linux/] [alpha/] [divrem.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
2
   Contributed by David Mosberger (davidm@cs.arizona.edu).
3
   This file is part of the GNU C Library.
4
 
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
 
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
 
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
19
 
20
/* The current Alpha chips don't provide hardware for integer
21
   division.  The C compiler expects the functions
22
 
23
        __divqu: 64-bit unsigned long divide
24
        __remqu: 64-bit unsigned long remainder
25
        __divqs/__remqs: signed 64-bit
26
        __divlu/__remlu: unsigned 32-bit
27
        __divls/__remls: signed 32-bit
28
 
29
   These are not normal C functions: instead of the normal calling
30
   sequence, these expect their arguments in registers t10 and t11, and
31
   return the result in t12 (aka pv).  Register AT may be clobbered
32
   (assembly temporary), anything else must be saved.  */
33
 
34
#include <features.h>
35
 
36
#ifdef __linux__
37
# include <asm/gentrap.h>
38
# include <asm/pal.h>
39
#else
40
# include <machine/pal.h>
41
#endif
42
 
43
#define mask                    v0
44
#define divisor                 t0
45
#define compare                 AT
46
#define tmp1                    t2
47
#define tmp2                    t3
48
#define retaddr                 t9
49
#define arg1                    t10
50
#define arg2                    t11
51
#define result                  t12
52
 
53
#define v0      $0      /* function return value */
54
 
55
#define t0      $1      /* temporary registers (caller-saved) */
56
#define t1      $2
57
#define t2      $3
58
#define t3      $4
59
#define t4      $5
60
#define t5      $6
61
#define t6      $7
62
#define t7      $8
63
 
64
#define s0      $9      /* saved-registers (callee-saved registers) */
65
#define s1      $10
66
#define s2      $11
67
#define s3      $12
68
#define s4      $13
69
#define s5      $14
70
#define s6      $15
71
#define fp      s6      /* frame-pointer (s6 in frame-less procedures) */
72
 
73
#define a0      $16     /* argument registers (caller-saved) */
74
#define a1      $17
75
#define a2      $18
76
#define a3      $19
77
#define a4      $20
78
#define a5      $21
79
 
80
#define t8      $22     /* more temps (caller-saved) */
81
#define t9      $23
82
#define t10     $24
83
#define t11     $25
84
#define ra      $26     /* return address register */
85
#define t12     $27
86
 
87
#define pv      t12     /* procedure-variable register */
88
#define AT      $at     /* assembler temporary */
89
#define gp      $29     /* global pointer */
90
#define sp      $30     /* stack pointer */
91
#define zero    $31     /* reads as zero, writes are noops */
92
 
93
 
94
 
95
#if IS_REM
96
# define DIV_ONLY(x,y...)
97
# define REM_ONLY(x,y...)       x,##y
98
# define modulus                result
99
# define quotient               t1
100
# define GETSIGN(x)             mov arg1, x
101
# define STACK                  32
102
#else
103
# define DIV_ONLY(x,y...)       x,##y
104
# define REM_ONLY(x,y...)
105
# define modulus                t1
106
# define quotient               result
107
# define GETSIGN(x)             xor arg1, arg2, x
108
# define STACK                  48
109
#endif
110
 
111
#if SIZE == 8
112
# define LONGIFY(x,y)           mov x,y
113
# define SLONGIFY(x,y)          mov x,y
114
# define _SLONGIFY(x)
115
# define NEG(x,y)               negq x,y
116
#else
117
# define LONGIFY(x,y)           zapnot x,15,y
118
# define SLONGIFY(x,y)          sextl x,y
119
# define _SLONGIFY(x)           sextl x,x
120
# define NEG(x,y)               negl x,y
121
#endif
122
 
123
        .set noreorder
124
        .set noat
125
 
126
        .ent UFUNC_NAME
127
        .globl UFUNC_NAME
128
 
129
        .align 3
130
UFUNC_NAME:
131
        lda     sp, -STACK(sp)
132
        .frame  sp, STACK, retaddr, 0
133
#ifdef PROF
134
        stq     ra, 0(sp)
135
        stq     pv, 8(sp)
136
        stq     gp, 16(sp)
137
 
138
        br      AT, 1f
139
1:      ldgp    gp, 0(AT)
140
 
141
        mov     retaddr, ra
142
        lda     AT, _mcount
143
        jsr     AT, (AT), _mcount
144
 
145
        ldq     ra, 0(sp)
146
        ldq     pv, 8(sp)
147
        ldq     gp, 16(sp)
148
#endif
149
        .prologue 0
150
 
151
$udiv:
152
        stq     t0, 0(sp)
153
        LONGIFY (arg2, divisor)
154
        stq     t1, 8(sp)
155
        LONGIFY (arg1, modulus)
156
        stq     v0, 16(sp)
157
        clr     quotient
158
        stq     tmp1, 24(sp)
159
        ldiq    mask, 1
160
        DIV_ONLY(stq tmp2,32(sp))
161
 
162
        beq     divisor, $divbyzero
163
 
164
        .align 3
165
#if SIZE == 8
166
        /* Shift divisor left.  */
167
1:      cmpult  divisor, modulus, compare
168
        blt     divisor, 2f
169
        addq    divisor, divisor, divisor
170
        addq    mask, mask, mask
171
        bne     compare, 1b
172
        unop
173
2:
174
#else
175
        /* Shift divisor left using 3-bit shifts as we can't overflow.
176
           This results in looping three times less here, but up to
177
           two more times later.  Thus using a large shift isn't worth it.  */
178
1:      cmpult  divisor, modulus, compare
179
        s8addq  divisor, zero, divisor
180
        s8addq  mask, zero, mask
181
        bne     compare, 1b
182
#endif
183
 
184
        /* Now go back to the right.  */
185
3:      DIV_ONLY(addq quotient, mask, tmp2)
186
        srl     mask, 1, mask
187
        cmpule  divisor, modulus, compare
188
        subq    modulus, divisor, tmp1
189
        DIV_ONLY(cmovne compare, tmp2, quotient)
190
        srl     divisor, 1, divisor
191
        cmovne  compare, tmp1, modulus
192
        bne     mask, 3b
193
 
194
$done:  ldq     t0, 0(sp)
195
        ldq     t1, 8(sp)
196
        ldq     v0, 16(sp)
197
        ldq     tmp1, 24(sp)
198
        DIV_ONLY(ldq tmp2, 32(sp))
199
        lda     sp, STACK(sp)
200
        ret     zero, (retaddr), 1
201
 
202
$divbyzero:
203
        mov     a0, tmp1
204
        ldiq    a0, GEN_INTDIV
205
        call_pal PAL_gentrap
206
        mov     tmp1, a0
207
        clr     result                  /* If trap returns, return zero.  */
208
        br      $done
209
 
210
        .end UFUNC_NAME
211
 
212
        .ent SFUNC_NAME
213
        .globl SFUNC_NAME
214
 
215
        .align 3
216
SFUNC_NAME:
217
        lda     sp, -STACK(sp)
218
        .frame  sp, STACK, retaddr, 0
219
#ifdef PROF
220
        stq     ra, 0(sp)
221
        stq     pv, 8(sp)
222
        stq     gp, 16(sp)
223
 
224
        br      AT, 1f
225
1:      ldgp    gp, 0(AT)
226
 
227
        mov     retaddr, ra
228
        jsr     AT, _mcount
229
 
230
        ldq     ra, 0(sp)
231
        ldq     pv, 8(sp)
232
        ldq     gp, 16(sp)
233
#endif
234
        .prologue 0
235
 
236
        or      arg1, arg2, AT
237
        _SLONGIFY(AT)
238
        bge     AT, $udiv               /* don't need to mess with signs */
239
 
240
        /* Save originals and find absolute values.  */
241
        stq     arg1, 0(sp)
242
        NEG     (arg1, AT)
243
        stq     arg2, 8(sp)
244
        cmovge  AT, AT, arg1
245
        stq     retaddr, 16(sp)
246
        NEG     (arg2, AT)
247
        stq     tmp1, 24(sp)
248
        cmovge  AT, AT, arg2
249
 
250
        /* Do the unsigned division.  */
251
        bsr     retaddr, UFUNC_NAME
252
 
253
        /* Restore originals and adjust the sign of the result.  */
254
        ldq     arg1, 0(sp)
255
        ldq     arg2, 8(sp)
256
        GETSIGN (AT)
257
        NEG     (result, tmp1)
258
        _SLONGIFY(AT)
259
        ldq     retaddr, 16(sp)
260
        cmovlt  AT, tmp1, result
261
        ldq     tmp1, 24(sp)
262
 
263
        lda     sp, STACK(sp)
264
        ret     zero, (retaddr), 1
265
 
266
        .end    SFUNC_NAME

powered by: WebSVN 2.1.0

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