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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [zlib/] [udiv.c] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 54 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    udiv.c
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7
// Purpose:     This is a temporary file--a crutch if you will--until a similar
8
//              capability is merged into GCC.  Right now, GCC has no way of
9
//      dividing two 64-bit numbers, and this routine provides that capability.
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
18
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// You should have received a copy of the GNU General Public License along
30
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
31
// target there if the PDF file isn't present.)  If not, see
32
// <http://www.gnu.org/licenses/> for a copy.
33
//
34
// License:     GPL, v3, as defined and found on www.gnu.org,
35
//              http://www.gnu.org/licenses/gpl.html
36
//
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40
//
41
#include <stdint.h>
42
 
43
 
44
 
45
#ifdef  __ZIPCPU__
46
#include "zipcpu.h"
47
#else
48
uint32_t zip_bitrev(const uint32_t a) {
49
        uint32_t        r, b = a;
50
        r = 0;
51
        for(int i=0; i<32; i++) {
52
                r = (r<<1) | (b&1);
53
                b >>= 1;
54
        } return r;
55
}
56
#endif
57
 
58
extern  int     cltz(unsigned long);
59
 
60
#ifdef  __ZIPCPU__
61
#define ASMCLTZ
62
#endif
63
 
64
#ifdef  ASMCLTZ
65
asm("\t.section\t.text\n\t.global\tcltz\n"
66
"\t.type\tcltz,@function\n"
67
"cltz:\n"
68
        "\tMOV  R1,R3\n"
69
        "\tCLR  R1\n"
70
        "\tCMP  0,R3\n"
71
        "\tMOV.Z R2,R3\n"
72
        "\tADD.Z 32,R1\n"
73
        "\tBREV R3\n"
74
        "\tTEST 0x0ffff,R3\n"
75
        "\tADD.Z 16,R1\n"
76
        "\tLSR.Z 16,R3\n"
77
        "\tTEST 0x0ff,R3\n"
78
        "\tADD.Z 8,R1\n"
79
        "\tLSR.Z 8,R3\n"
80
        "\tTEST 0x0f,R3\n"
81
        "\tADD.Z 4,R1\n"
82
        "\tLSR.Z 4,R3\n"
83
        "\tTEST 0x03,R3\n"
84
        "\tADD.Z 2,R1\n"
85
        "\tLSR.Z 2,R3\n"
86
        "\tTEST 0x01,R3\n"
87
        "\tADD.Z 1,R1\n"
88
        "\tRETN\n");
89
#else
90
int
91
cltz(unsigned long v) {
92
        uint32_t        hv;
93
        int             cnt = 0;
94
 
95
        hv = v >> 32;
96
        if (hv == 0) {
97
                cnt += 32;
98
                hv = v & 0x0ffffffff;
99
        }
100
 
101
        hv = zip_bitrev(hv);
102
        if ((hv & 0x0ffff)==0) {
103
                cnt += 16;
104
                hv = hv >> 16;
105
        }
106
        if ((hv & 0x0ff)==0) {
107
                cnt += 8;
108
                hv = hv >> 8;
109
        }
110
        if ((hv & 0x0f)==0) {
111
                cnt += 4;
112
                hv = hv >> 4;
113
        }
114
        if ((hv & 0x03)==0) {
115
                cnt += 2;
116
                hv = hv >> 2;
117
        }
118
        if ((hv & 0x01)==0)
119
                cnt ++;
120
        return cnt;
121
}
122
#endif
123
 
124
unsigned long
125
__udivdi3(unsigned long a, unsigned long b) {
126
        unsigned long   r;
127
 
128
        if (a < b)
129
                return 0;
130
        if (((b>>32)==0)&&((a>>32)==0)) {
131
                uint32_t        ia, ib, ir;
132
 
133
                ia = (uint32_t) a;
134
                ib = (uint32_t) b;
135
                ir = ia / ib;
136
                r = (unsigned long)ir;
137
                return r;
138
        }
139
 
140
        int     la = cltz(a), lb = cltz(b);
141
        a <<= la;
142
        unsigned long   m;
143
        if ((lb - la < 32)&&(((b<<la)&0x0ffffffff)==0)) {
144
                // Problem is now to divide
145
                //      [a * 2^(la-32)] / [b * 2^(la-32)] * 2^(la-la)
146
                //
147
                uint32_t        ia, ib, ir;
148
                b <<= la;
149
                ia = (uint32_t)(a>>32);
150
                ib = (uint32_t)(b>>32);
151
                ir = ia / ib;
152
                r = ir;
153
                return r;
154
        } else {
155
                // Problem is now to divide
156
                //      [a * 2^(la)] / [b * 2^(lb)] * 2^(lb-la)
157
                //
158
                r = 0;
159
                b <<= lb;
160
                m = (1ul<<(lb-la));
161
                while(m > 0) {
162
                        if (a >= b) {
163
                                r |= m;
164
                                a -= b;
165
                        }
166
                        m>>= 1;
167
                        b >>= 1;
168
                } return r;
169
        }
170
}
171
 
172
//
173
// A possible assembly version of __divdi3
174
//
175
//      SUB     8,SP
176
//      SW      R0,(SP)
177
//      SW      R5,4(SP)
178
//      LDI     0,R5
179
//      CMP     0,R1
180
//      BGE     .La_is_nonneg
181
//      XOR     1,R5
182
//      XOR     -1,R1
183
//      XOR     -1,R2
184
//      ADD     1,R2
185
//      ADD.C   1,R1
186
//.La_is_nonneg
187
//      CMP     0,R3
188
//      BGE     .Lb_is_nonneg
189
//      XOR     1,R5
190
//      XOR     -1,R3
191
//      XOR     -1,R3
192
//      ADD     1,R4
193
//      ADD.C   1,R3
194
//.Lb_is_nonneg
195
//      TEST    R5
196
//      MOV     .Lnegate_upon_return(PC),R0
197
//      MOV.Z   .Lsimple_return(PC),R0
198
//      BRA     __udivdi3
199
//.Lnegate_upon_return
200
//      XOR     -1,R2
201
//      XOR     -1,R1
202
//      ADD     1,R2
203
//      ADD.C   1,R1
204
//.Lsimple_return
205
//
206
//      LW      (SP),R0,(SP)
207
//      LW      4(SP),R5)
208
//      ADD     8,SP
209
//      RETN
210
//
211
long __divdi3(long a, long b) {
212
        int     s = 0;
213
        long    r;
214
 
215
        if (a < 0) {
216
                s = 1; a = -a;
217
        }
218
 
219
        if (b < 0) {
220
                s ^= 1; b = -b;
221
        }
222
 
223
        r = (long)__udivdi3((unsigned long)a, (unsigned long)b);
224
        if (s)
225
                r = -r;
226
        return r;
227
}

powered by: WebSVN 2.1.0

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