Commit | Line | Data |
---|---|---|
8cd657f4 JF |
1 | #include "global.h" |
2 | ||
3 | #define b 0x40000000 | |
4 | #define toint(p) ((int) (p)) | |
5 | ||
6 | divbig(dividend, divisor, quotient, remainder) | |
7 | lispval dividend, divisor, *quotient, *remainder; | |
8 | { | |
9 | register *ujp, *vip; | |
10 | int *sp(), *alloca(), d, negflag = 0, m, n, carry, rem, qhat, j; | |
11 | int borrow, negrem = 0; | |
12 | int *utop = sp(), *ubot, *vbot, *qbot; | |
13 | register lispval work; lispval export(); | |
14 | ||
15 | /* copy dividend */ | |
16 | for(work = dividend; work; work = work ->CDR) | |
17 | stack(work->I); | |
18 | ubot = sp(); | |
19 | if(*ubot < 0) { /* knuth's division alg works only for pos | |
20 | bignums */ | |
21 | negflag ^= 1; | |
22 | negrem = 1; | |
23 | dsmult(utop-1,ubot,-1); | |
24 | } | |
25 | stack(0); | |
26 | ubot = sp(); | |
27 | ||
28 | ||
29 | /*copy divisor */ | |
30 | for(work = divisor; work; work = work->CDR) | |
31 | stack(work->I); | |
32 | ||
33 | vbot = sp(); | |
34 | stack(0); | |
35 | if(*vbot < 0) { | |
36 | negflag ^= 1; | |
37 | dsmult(ubot-1,vbot,-1); | |
38 | } | |
39 | ||
40 | /* check validity of data */ | |
41 | n = ubot - vbot; | |
42 | m = utop - ubot - n - 1; | |
43 | if (n == 1) { | |
44 | /* do destructive division by a single. */ | |
45 | rem = dsdiv(utop-1,ubot,*vbot); | |
46 | if(negrem) | |
47 | rem = -rem; | |
48 | if(negflag) | |
49 | dsmult(utop-1,ubot,-1); | |
50 | if(remainder) | |
51 | *remainder = inewint(rem); | |
52 | if(quotient) | |
53 | *quotient = export(utop,ubot); | |
54 | return; | |
55 | } | |
56 | if (m < 0) { | |
57 | if (remainder) | |
58 | *remainder = dividend; | |
59 | if(quotient) | |
60 | *quotient = inewint(0); | |
61 | return; | |
62 | } | |
63 | qbot = alloca(toint(utop) + toint(vbot) - 2 * toint(ubot)); | |
64 | d1: | |
65 | d = b /(*vbot +1); | |
66 | dsmult(utop-1,ubot,d); | |
67 | dsmult(ubot-1,vbot,d); | |
68 | ||
69 | d2: for(j=0,ujp=ubot; j <= m; j++,ujp++) { | |
70 | ||
71 | d3: | |
72 | qhat = calqhat(ujp,vbot); | |
73 | d4: | |
74 | if((borrow = mlsb(ujp + n, ujp, ubot, -qhat)) < 0) { | |
75 | adback(ujp + n, ujp, ubot); | |
76 | qhat--; | |
77 | } | |
78 | qbot[j] = qhat; | |
79 | } | |
80 | d8: if(remainder) { | |
81 | dsdiv(utop, utop - n, d); | |
82 | if(negrem) dsmult(utop-1,utop-n,-1); | |
83 | *remainder = export(utop,utop-n); | |
84 | } | |
85 | if(quotient) { | |
86 | if(negflag) | |
87 | dsmult(qbot+m,qbot,-1); | |
88 | *quotient = export(qbot + m + 1, qbot); | |
89 | } | |
90 | } | |
91 | /*static*/ calqhat(ujp,v1p) | |
92 | register int *ujp, *v1p; | |
93 | { | |
94 | asm(" movl $0x3fffffff,r0"); | |
95 | asm(" cmpl (r10),(r11)"); | |
96 | asm(" beql on1"); | |
97 | asm(" emul (r11),$0x40000000,4(r11),r1"); | |
98 | asm(" ediv (r10),r1,r0,r5"); | |
99 | asm("on1:"); | |
100 | asm(" emul r0,4(r10),$0,r1"); | |
101 | asm(" emul r5,$0x40000000,8(r11),r3"); | |
102 | asm(" subl2 r3,r1"); | |
103 | asm(" sbwc r4,r2"); | |
104 | asm(" bleq out1"); | |
105 | asm(" decl r0"); | |
106 | asm("out1:"); | |
107 | } | |
108 | /*static*/ mlsb(utop,ubot,vtop,nqhat) | |
109 | register int *utop, *ubot, *vtop; | |
110 | register int nqhat; | |
111 | { | |
112 | asm(" clrl r0"); | |
113 | asm("loop2: addl2 (r11),r0"); | |
114 | asm(" emul r8,-(r9),r0,r2"); | |
115 | asm(" extzv $0,$30,r2,(r11)"); | |
116 | asm(" extv $30,$32,r2,r0"); | |
117 | asm(" acbl r10,$-4,r11,loop2"); | |
118 | } | |
119 | /*static*/ adback(utop,ubot,vtop) | |
120 | register int *utop, *ubot, *vtop; | |
121 | { | |
122 | asm(" clrl r0"); | |
123 | asm("loop3: addl2 -(r9),r0"); | |
124 | asm(" addl2 (r11),r0"); | |
125 | asm(" extzv $0,$30,r0,(r11)"); | |
126 | asm(" extv $30,$2,r0,r0"); | |
127 | asm(" acbl r10,$-4,r11,loop3"); | |
128 | } | |
129 | /*static*/ dsdiv(top,bot,div) | |
130 | register int* bot; | |
131 | { | |
132 | asm(" clrl r0"); | |
133 | asm("loop4: emul r0,$0x40000000,(r11),r1"); | |
134 | asm(" ediv 12(ap),r1,(r11),r0"); | |
135 | asm(" acbl 4(ap),$4,r11,loop4"); | |
136 | } | |
137 | /*static*/ dsmult(top,bot,mult) | |
138 | register int* top; | |
139 | { | |
140 | asm(" clrl r0"); | |
141 | asm("loop5: emul 12(ap),(r11),r0,r1"); | |
142 | asm(" extzv $0,$30,r1,(r11)"); | |
143 | asm(" extv $30,$32,r1,r0"); | |
144 | asm(" acbl 8(ap),$-4,r11,loop5"); | |
145 | asm(" movl r1,4(r11)"); | |
146 | } | |
147 | /*static*/ lispval export(top,bot) | |
148 | register lispval bot; | |
149 | { | |
150 | register r10, r9, r8, r7, r6; | |
151 | asm(" movl 4(ap),r10"); | |
152 | asm(" movl $0xC0000000,r4"); | |
153 | asm(" jmp Bexport"); | |
154 | } | |
155 | ||
156 | #define MAXINT 0x8000000L | |
157 | ||
158 | Ihau(fix) | |
159 | register int fix; | |
160 | { | |
161 | register count; | |
162 | if(fix==MAXINT) | |
163 | return(32); | |
164 | if(fix < 0) | |
165 | fix = -fix; | |
166 | for(count = 0; fix; count++) | |
167 | fix /= 2; | |
168 | return(count); | |
169 | } | |
170 | lispval | |
171 | Lhau() | |
172 | { | |
173 | register count; | |
174 | register lispval handy; | |
175 | register dum1,dum2; | |
176 | register struct argent *lbot, *np; | |
177 | lispval Labsval(); | |
178 | ||
179 | handy = lbot->val; | |
180 | top: | |
181 | switch(TYPE(handy)) { | |
182 | case INT: | |
183 | count = Ihau(handy->i); | |
184 | break; | |
185 | case SDOT: | |
186 | lbot->val = Labsval(); | |
187 | for(count = 0; handy->CDR!=((lispval) 0); handy = handy->CDR) | |
188 | count += 30; | |
189 | count += Ihau(handy->I); | |
190 | break; | |
191 | default: | |
192 | handy = errorh(Vermisc,"Haulong: bad argument",nil, | |
193 | TRUE,997,handy); | |
194 | goto top; | |
195 | } | |
196 | return(inewint(count)); | |
197 | } | |
198 | lispval | |
199 | Lhaipar() | |
200 | { | |
201 | int *sp(); | |
202 | register lispval work; | |
203 | register n; | |
204 | register int *top = sp() - 1; | |
205 | register int *bot; | |
206 | register struct argent *lbot, *np; | |
207 | int mylen; | |
208 | ||
209 | /*chkarg(2);*/ | |
210 | work = lbot->val; | |
211 | /* copy data onto stack */ | |
212 | on1: | |
213 | switch(TYPE(work)) { | |
214 | case INT: | |
215 | stack(work->i); | |
216 | break; | |
217 | case SDOT: | |
218 | for(; work!=((lispval) 0); work = work->CDR) | |
219 | stack(work->I); | |
220 | break; | |
221 | default: | |
222 | work = errorh(Vermisc,"Haipart: bad first argument",nil, | |
223 | TRUE,996,work); | |
224 | goto on1; | |
225 | } | |
226 | bot = sp(); | |
227 | if(*bot < 0) { | |
228 | stack(0); | |
229 | dsmult(top,bot,-1); | |
230 | bot--; | |
231 | } | |
232 | for(; *bot==0 && bot < top; bot++); | |
233 | /* recalculate haulong internally */ | |
234 | mylen = (top - bot) * 30 + Ihau(*bot); | |
235 | /* get second argument */ | |
236 | work = lbot[1].val; | |
237 | while(TYPE(work)!=INT) | |
238 | work = errorh(Vermisc,"Haipart: 2nd arg not int",nil, | |
239 | TRUE,995,work); | |
240 | n = work->i; | |
241 | if(n >= mylen || -n >= mylen) | |
242 | goto done; | |
243 | if(n >= 0) { | |
244 | /* Here we want n most significant bits | |
245 | so chop off mylen - n bits */ | |
246 | stack(0); | |
247 | n = mylen - n; | |
248 | for(n; n >= 30; n -= 30) | |
249 | top--; | |
250 | if(top < bot) | |
251 | error("Internal error in haipart #1",FALSE); | |
252 | dsdiv(top,bot,1<<n); | |
253 | ||
254 | } else { | |
255 | /* here we want abs(n) low order bits */ | |
256 | stack(0); | |
257 | bot = top + 1; | |
258 | for(; n <= 0; n += 30) | |
259 | bot--; | |
260 | n = 30 - n; | |
261 | *bot &= ~ (-1<<n); | |
262 | } | |
263 | done: | |
264 | return(export(top + 1,bot)); | |
265 | } |