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