Commit | Line | Data |
---|---|---|
bcaf9154 | 1 | #ifndef lint |
1346e8b5 | 2 | static char sccsid[] = "@(#)c22.c 1.9 (Berkeley/CCI) %G%"; |
bcaf9154 SL |
3 | #endif |
4 | ||
5 | /* | |
6 | * C object code improver-- third part | |
7 | */ | |
8 | ||
9 | #include "c2.h" | |
10 | #include <stdio.h> | |
11 | #include <ctype.h> | |
12 | ||
13 | rmove() | |
14 | { | |
15 | register struct node *p; | |
16 | register int r, r1; | |
17 | ||
18 | clearreg(); | |
19 | for (p=first.forw; p!=0; p = p->forw) { | |
20 | if (debug) { | |
21 | printf("Regs: "); | |
22 | for (r=0; r<=NREG; r++) | |
23 | if (regs[r][0]) { | |
24 | r1=regs[r][0]; | |
25 | printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1); | |
26 | } | |
27 | printf("-\n"); | |
28 | } | |
29 | switch (p->op) { | |
30 | ||
31 | case CVT: | |
32 | case MOVZ: | |
33 | splitrand(p); | |
34 | repladdr(p); | |
35 | r = isreg(regs[RT1]); | |
36 | r1 = isreg(regs[RT2]); | |
2532ae25 | 37 | dest(regs[RT2],p->subop, p->op!=CVT || r<0); |
bcaf9154 SL |
38 | if (r>=0 && r1>=0) { |
39 | p->op = MOV; p->subop = LONG; | |
40 | p->pop = 0; | |
41 | nchange++; | |
42 | goto case_mov; | |
43 | } | |
44 | if(p->op == CVT) { | |
45 | if (r1>=0) savereg(r1, regs[RT1], p->subop); | |
46 | } else | |
47 | ccloc[0] = 0; | |
48 | break; | |
49 | ||
50 | case MOV: | |
51 | case_mov: | |
52 | splitrand(p); | |
53 | if ((r = findrand(regs[RT1],p->subop)) >= 0) { | |
54 | if (r == isreg(regs[RT2])) | |
55 | if(p->forw->op!=CBR) { | |
56 | delnode(p); redunm++; nchange++; break; | |
57 | } else { | |
58 | p->op=TST; p->pop=0; | |
59 | while(*p->code++ != ','); | |
60 | redunm++; nchange++; | |
61 | goto case_tst; | |
62 | } | |
63 | } | |
64 | repladdr(p); | |
65 | r = isreg(regs[RT1]); | |
66 | r1 = isreg(regs[RT2]); | |
67 | dest(regs[RT2],p->subop, 1); | |
864f1f35 SL |
68 | if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1)) |
69 | *(short *)(regs[ACC]) = 0; | |
bcaf9154 SL |
70 | if (r>=0) { |
71 | if (r1>=0) { | |
72 | if (r == r1 && p->forw->op!=CBR) { | |
864f1f35 SL |
73 | delnode(p); redunm++; nchange++; |
74 | break; | |
bcaf9154 SL |
75 | } |
76 | if(regs[r][0]) | |
77 | savereg(r1, regs[r]+1, p->subop); | |
864f1f35 SL |
78 | } else |
79 | savereg(r, regs[RT2], p->subop); | |
80 | } else if (r1>=0) | |
81 | savereg(r1, regs[RT1], p->subop); | |
82 | else | |
83 | setcon(regs[RT1], regs[RT2], p->subop); | |
bcaf9154 SL |
84 | break; |
85 | ||
86 | /* .rx,.wx or .rx,.rx,.wx */ | |
87 | case ADD: | |
88 | case SUB: | |
89 | case AND: | |
90 | case OR: | |
91 | case XOR: | |
92 | case MUL: | |
93 | case DIV: | |
94 | #ifdef EMOD | |
95 | case EDIV: | |
96 | case EMOD: | |
97 | #endif EMOD | |
98 | case SHAL: | |
99 | case SHAR: | |
100 | case SHL: | |
101 | case SHR: | |
102 | case ADDA: | |
103 | case SUBA: | |
104 | /* .rx,.wx */ | |
105 | case MFPR: | |
106 | case COM: | |
107 | case NEG: | |
108 | splitrand(p); | |
109 | repladdr(p); | |
110 | dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA); | |
111 | break; | |
112 | ||
113 | /* .mx or .wx */ | |
114 | case STF: | |
115 | if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { | |
116 | delnode(p); | |
117 | nst++; nchange++; break; | |
118 | } | |
119 | savereg(ACC, p->code, p->subop); | |
bcaf9154 SL |
120 | case INC: |
121 | case DEC: | |
122 | case CVFL: | |
123 | dest(p->code,p->subop, 1); | |
864f1f35 SL |
124 | break; |
125 | ||
126 | case CLR: | |
127 | dest(p->code,p->subop, 1); | |
128 | if ((regs[ACC][0]) && equstr(p->code,regs[ACC]+1)) | |
129 | *(short *)(regs[ACC]) = 0; | |
130 | if ((r = isreg(p->code)) < 0) | |
131 | setcon("$0", p->code, p->subop); | |
132 | else | |
133 | savereg(r, "$0", p->subop); | |
bcaf9154 SL |
134 | break; |
135 | ||
136 | /* .rx */ | |
137 | case LDF: | |
138 | if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { | |
139 | delnode(p); | |
140 | nld++; nchange++; break; | |
141 | } | |
142 | savereg(ACC, p->code, p->subop); | |
143 | goto case_tst; | |
144 | case LNF: | |
145 | if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { | |
146 | p->op = NEGF; p->pop = 0; p->code = 0; | |
147 | regs[ACC][0] = 0; | |
148 | break; | |
149 | } | |
150 | case CVLF: | |
151 | case LDFD: | |
152 | case ADDF: | |
153 | case SUBF: | |
154 | case MULF: | |
155 | case DIVF: | |
156 | regs[ACC][0] = 0; | |
157 | case TST: | |
158 | case_tst: | |
159 | case PUSH: | |
160 | splitrand(p); | |
161 | lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */ | |
162 | repladdr(p); | |
163 | lastrand=regs[RT1]; | |
164 | if (p->op==TST && equstr(lastrand, ccloc+1) | |
165 | && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) { | |
166 | delnode(p); nrtst++; nchange++; break; | |
167 | } | |
168 | if (p->op==PUSH && p->subop!=LONG && | |
169 | (isreg(lastrand)>=0 || *lastrand=='$')) { | |
170 | p->subop = LONG; | |
171 | p->pop = 0; | |
172 | nchange++; | |
173 | } | |
174 | if (p->op==TST || p->op==PUSH) | |
175 | setcc(lastrand,p->subop); | |
176 | break; | |
177 | ||
178 | /* .rx,.rx,.rx */ | |
179 | case PROBE: | |
180 | case CASE: | |
181 | /* .rx,.rx */ | |
182 | case MTPR: | |
183 | case CALLS: | |
184 | case CALLF: | |
185 | case CMP: | |
186 | case BIT: | |
187 | case CMPF: | |
188 | case CMPF2: | |
189 | splitrand(p); | |
190 | /* fool repladdr into doing right number of operands */ | |
191 | lastrand=byondrd(p); | |
192 | if (p->op==CALLF || p->op==CALLS) clearreg(); | |
193 | else repladdr(p); | |
194 | case TSTF: | |
195 | ccloc[0]=0; | |
196 | case PUSHD: | |
197 | break; | |
198 | ||
199 | /* acc only */ | |
200 | case CVDF: | |
201 | case NEGF: | |
202 | case SINF: | |
203 | case COSF: | |
204 | case ATANF: | |
205 | case LOGF: | |
206 | case SQRTF: | |
207 | case EXPF: | |
208 | regs[ACC][0] = 0; | |
209 | break; | |
210 | ||
211 | #ifndef EMOD | |
212 | /* .rx,.rx,.wx,.wx */ | |
213 | case EDIV: | |
214 | splitrand(p); | |
215 | lastrand = regs[RT3]; | |
216 | repladdr(p); | |
217 | dest(regs[RT3], p->subop, 1); | |
218 | dest(regs[RT4], p->subop, 0); | |
219 | break; | |
220 | #endif EMOD | |
221 | ||
222 | /* .rx,.rx,.rx,wx */ | |
223 | case EMUL: | |
224 | splitrand(p); | |
225 | lastrand = regs[RT4]; | |
226 | repladdr(p); | |
227 | dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */ | |
228 | break; | |
229 | case CBR: | |
230 | if (p->subop>=JBC) { | |
231 | splitrand(p); | |
232 | lastrand=regs[RT3]; /* 2 operands can be optimized */ | |
233 | repladdr(p); | |
234 | ccloc[0] = 0; | |
235 | } else | |
236 | reduncbr(p); | |
237 | break; | |
238 | ||
239 | case JBR: | |
240 | redunbr(p); | |
241 | ||
242 | default: | |
243 | clearreg(); | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
248 | jumpsw() | |
249 | { | |
250 | register struct node *p, *p1, *pt; | |
251 | register int t, nj; | |
252 | ||
253 | t = 0; | |
254 | nj = 0; | |
255 | for (p=first.forw; p!=0; p = p->forw) | |
256 | p->seq = ++t; | |
257 | for (p=first.forw; p!=0; p = p1) { | |
258 | p1 = p->forw; | |
259 | if (p->op == CBR && p1->op==JBR && p->ref && p1->ref | |
260 | && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) { | |
261 | if (p->ref==p1->ref) | |
262 | continue; | |
263 | p->subop = revbr[p->subop]; | |
264 | p->pop=0; | |
265 | pt = p1->ref; | |
266 | p1->ref = p->ref; | |
267 | p->ref = pt; | |
268 | t = p1->labno; | |
269 | p1->labno = p->labno; | |
270 | p->labno = t; | |
271 | #ifdef COPYCODE | |
272 | if (p->labno == 0) { | |
273 | pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt; | |
274 | } | |
275 | #endif | |
276 | nrevbr++; | |
277 | nj++; | |
278 | } | |
279 | } | |
280 | return(nj); | |
281 | } | |
282 | ||
283 | addaob() | |
284 | { | |
285 | register struct node *p, *p1, *p2, *p3; | |
286 | ||
287 | for (p = &first; (p1 = p->forw)!=0; p = p1) { | |
288 | if (p->op==INC && p->subop==LONG) { | |
289 | if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG | |
290 | && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE | |
291 | && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1 | |
292 | && p3->forw->op==LABEL && p3->forw==p2->ref) { | |
293 | /* change INC LAB: CMP to LAB: INC CMP */ | |
294 | p->back->forw=p1; p1->back=p->back; | |
295 | p->forw=p1->forw; p1->forw->back=p; | |
296 | p->back=p1; p1->forw=p; | |
297 | p1=p->forw; | |
298 | /* adjust beginning value by 1 */ | |
299 | p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG; | |
300 | p2->pop=0; | |
301 | p2->forw=p3; p2->back=p3->back; p3->back->forw=p2; | |
302 | p3->back=p2; p2->code=p->code; p2->labno=0; | |
303 | } | |
304 | if (p1->op==CMP && p1->subop==LONG && | |
305 | (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) { | |
306 | register char *cp1,*cp2; | |
307 | splitrand(p1); if (!equstr(p->code,regs[RT1])) continue; | |
e6c8f4f3 SL |
308 | if ((p2->subop==JLE || p2->subop==JLT) && |
309 | checkaobdisp(p2)){ | |
bcaf9154 SL |
310 | if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0; |
311 | cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */ | |
312 | cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */ | |
313 | p->pop=0; newcode(p); | |
314 | p->labno = p2->labno; delnode(p2); delnode(p1); naob++; | |
315 | } | |
316 | } | |
317 | } | |
318 | } | |
319 | } | |
320 | ||
321 | ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */ | |
322 | register int log; | |
323 | if (n==0 || n&(n-1)) return(-1); log=0; | |
324 | for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);} | |
325 | } | |
326 | ||
327 | equop(p1, p2) | |
328 | register struct node *p1, *p2; | |
329 | { | |
330 | register char *cp1, *cp2; | |
331 | ||
332 | if (p1->op != p2->op || p1->subop != p2->subop) | |
333 | return(0); | |
cdb206a9 DS |
334 | if (p1->op == NIL && p1->subop == 0 && p1->pop != p2->pop) |
335 | return(0); | |
864f1f35 | 336 | if (p1->op != NIL && ord(p1->op) < ord(MOV)) |
bcaf9154 | 337 | return(0); |
cdb206a9 DS |
338 | switch (p1->op) { |
339 | case EROU: case JSW: case TEXT: case DATA: | |
340 | case BSS: case ALIGN: case WGEN: case END: | |
341 | /* sufficient? */ | |
342 | return(0); | |
343 | } | |
bcaf9154 SL |
344 | if (p1->op==MOVA && p1->labno!=p2->labno) return(0); |
345 | cp1 = p1->code; | |
346 | cp2 = p2->code; | |
347 | if (cp1==0 && cp2==0) | |
348 | return(1); | |
349 | if (cp1==0 || cp2==0) | |
350 | return(0); | |
351 | while (*cp1 == *cp2++) | |
352 | if (*cp1++ == 0) | |
353 | return(1); | |
354 | return(0); | |
355 | } | |
356 | ||
357 | delnode(p) register struct node *p; { | |
358 | p->back->forw = p->forw; | |
359 | p->forw->back = p->back; | |
360 | } | |
361 | ||
362 | decref(p) | |
363 | register struct node *p; | |
364 | { | |
365 | if (p && --p->refc <= 0) { | |
366 | nrlab++; nchange++; | |
367 | delnode(p); | |
368 | } | |
369 | } | |
370 | ||
371 | struct node * | |
372 | nonlab(ap) | |
373 | struct node *ap; | |
374 | { | |
375 | register struct node *p; | |
376 | ||
377 | p = ap; | |
378 | while (p && p->op==LABEL) | |
379 | p = p->forw; | |
380 | return(p); | |
381 | } | |
382 | ||
383 | clearuse() { | |
384 | register struct node **i; | |
e6c8f4f3 | 385 | for (i=uses+NREG; i>uses;) *--i=0; |
bcaf9154 SL |
386 | useacc = 0; |
387 | } | |
388 | ||
389 | clearreg() { | |
390 | register char **i; | |
391 | for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; } | |
392 | conloc[0] = 0; ccloc[0] = 0; | |
393 | } | |
394 | ||
395 | savereg(ai, s, type) | |
396 | register char *s; | |
397 | { | |
398 | register char *p, *sp; | |
399 | ||
400 | sp = p = regs[ai]; | |
401 | /* if any indexing, must be parameter or local */ | |
402 | /* indirection (as in "*-4(fp)") is ok, however */ | |
403 | *p++ = type; | |
404 | if (*s=='*' || *s=='$') | |
405 | *p++ = *s++; | |
406 | if (natural(s)) | |
407 | strcpy(p, s); | |
408 | else {*sp = 0; return;} | |
409 | } | |
410 | ||
411 | dest(s,type, ccflg) | |
412 | register char *s; | |
413 | { | |
414 | register int i; | |
415 | ||
416 | if ((i = isreg(s)) >= 0) { | |
417 | *(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */ | |
418 | if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD) | |
419 | *(short *)(regs[i+1]) = 0; | |
420 | } | |
421 | for (i=NREG; --i>=0;) | |
422 | if (regs[i][1]=='*' && equstr(s, regs[i]+2)) | |
423 | *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */ | |
424 | while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */ | |
425 | *(short *)(regs[i]) = 0; | |
426 | ||
427 | if (!natural(s)) {/* wild store, everything except constants vanishes */ | |
428 | for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0; | |
429 | conloc[0] = 0; ccloc[0] = 0; | |
430 | } else { | |
431 | if(ccflg)setcc(s,type); /* natural destinations set condition codes */ | |
432 | if (equstr(s, conloc)) | |
433 | conloc[0] = 0; | |
434 | } | |
435 | } | |
436 | ||
437 | splitrand(p) struct node *p; { | |
438 | /* separate operands at commas, set up 'regs' and 'lastrand' */ | |
439 | register char *p1, *p2; register char **preg; | |
440 | ||
441 | preg=regs+RT1; | |
442 | if (p1=p->code) while (*p1) { | |
443 | lastrand=p2= *preg++; | |
444 | while (*p1) if (','==(*p2++= *p1++)) {--p2; break;} | |
445 | *p2=0; | |
446 | } | |
447 | while (preg<(regs+RT1+5)) *(*preg++)=0; | |
448 | } | |
449 | ||
450 | compat(have, want) | |
451 | register int have, want; | |
452 | { | |
453 | register int hsrc, hdst; | |
454 | extern int bitsize[]; | |
455 | ||
456 | if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */ | |
457 | hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc; | |
458 | if (want>=QUAD) | |
459 | return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]); | |
460 | return(hsrc==want && hdst>=want && hdst<QUAD); | |
461 | } | |
462 | ||
463 | equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));} | |
464 | ||
465 | findrand(as, type) | |
466 | char *as; | |
467 | { | |
468 | register char **i; | |
469 | for (i = regs+NREG; --i>=regs;) { | |
470 | if (**i && equstr(*i+1, as) && compat(**i,type)) | |
471 | return(i-regs); | |
472 | } | |
473 | return(-1); | |
474 | } | |
475 | ||
476 | isreg(s) | |
477 | register char *s; | |
478 | { | |
479 | if (*s++!='r' || !isdigit(*s++)) return(-1); | |
480 | if (*s==0) return(*--s-'0'); | |
481 | if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0'); | |
482 | return(-1); | |
483 | } | |
484 | ||
485 | /* | |
486 | check() | |
487 | { | |
488 | register struct node *p, *lp; | |
489 | ||
490 | lp = &first; | |
491 | for (p=first.forw; p!=0; p = p->forw) { | |
492 | if (p->back != lp) | |
493 | abort(-1); | |
494 | lp = p; | |
495 | } | |
496 | } | |
497 | */ | |
498 | ||
499 | newcode(p) struct node *p; { | |
500 | register char *p1,*p2,**preg; | |
501 | ||
502 | preg=regs+RT1; p2=line; | |
503 | while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';} | |
504 | *--p2=0; | |
505 | p->code=copy(line); | |
506 | } | |
507 | ||
508 | repladdr(p) | |
509 | struct node *p; | |
510 | { | |
511 | register int r; | |
512 | register char *p1; | |
513 | register char **preg; | |
514 | register int nrepl; | |
515 | ||
516 | preg=regs+RT1; nrepl=0; | |
517 | while (lastrand!=(p1= *preg++)) | |
518 | if (0<=(r=findrand(p1,p->subop))) { | |
519 | *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0; | |
520 | nchange++; nrepl++; nsaddr++; | |
521 | } | |
522 | if (nrepl) newcode(p); | |
523 | } | |
524 | ||
525 | /* conditional branches which are never/always taken */ | |
526 | reduncbr(p) | |
527 | register struct node *p; | |
528 | { | |
529 | register struct node *p1; | |
530 | register char *ap1, *ap2; | |
531 | ||
532 | p1 = p->back; | |
533 | if (p1->op==CMP) { | |
534 | splitrand(p1); | |
535 | ap1 = findcon(regs[RT1], p1->subop); | |
536 | ap2 = findcon(regs[RT2], p1->subop); | |
537 | } else { | |
538 | if(!ccloc[0]) | |
539 | return; | |
540 | ap1 = findcon(ccloc+1, ccloc[0]); | |
541 | ap2 = "$0"; | |
542 | } | |
543 | switch (compare(p->subop, ap1, ap2)) { | |
544 | case 0: /* branch never taken */ | |
545 | delnode(p); | |
546 | nredunj++; | |
547 | nchange++; | |
548 | decref(p->ref); | |
549 | if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) { | |
550 | delnode(p1); | |
551 | nrtst++; | |
552 | } | |
553 | break; | |
554 | case 1: /* branch always taken */ | |
555 | p->op = JBR; | |
556 | p->subop = 0; | |
557 | p->pop = 0; | |
558 | nchange++; | |
559 | if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) { | |
560 | delnode(p1); | |
561 | nrtst++; | |
562 | } | |
563 | } | |
564 | } | |
565 | ||
566 | /* a jump to a redundant compare (start of a 'for') */ | |
567 | redunbr(p) | |
568 | register struct node *p; | |
569 | { | |
570 | register struct node *p1; | |
571 | register char *ap1, *ap2; | |
572 | ||
573 | if ((p1 = p->ref) == 0) | |
574 | return; | |
575 | p1 = nonlab(p1); | |
576 | if (p1->op==TST || p1->op==CMP) | |
577 | splitrand(p1); | |
578 | else | |
579 | return; | |
580 | if (p1->forw->op==CBR) { | |
581 | ap1 = findcon(regs[RT1], p1->subop); | |
582 | if (p1->op==TST) | |
583 | ap2 = "$0"; | |
584 | else | |
585 | ap2 = findcon(regs[RT2], p1->subop); | |
586 | p1 = p1->forw; | |
587 | if (compare(p1->subop, ap1, ap2) > 0) { | |
588 | nredunj++; | |
589 | nchange++; | |
590 | decref(p->ref); | |
591 | p->ref = p1->ref; | |
592 | p->labno = p1->labno; | |
593 | #ifdef COPYCODE | |
594 | if (p->labno == 0) | |
595 | p->code = p1->code; | |
596 | if (p->ref) | |
597 | #endif | |
598 | p->ref->refc++; | |
599 | } | |
600 | } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) && | |
601 | equtype(ccloc[0],p1->subop)) { | |
602 | p1=insertl(p1->forw); decref(p->ref); p->ref=p1; | |
1346e8b5 | 603 | p->labno=p1->labno; |
bcaf9154 SL |
604 | nrtst++; nchange++; |
605 | } | |
606 | } | |
607 | ||
608 | char * | |
609 | findcon(p, type) | |
610 | register char *p; | |
611 | { | |
612 | register int r; | |
613 | ||
614 | if (*p=='$') | |
615 | return(p); | |
616 | if ((r = isreg(p)) >= 0 && compat(regs[r][0],type)) | |
617 | return(regs[r]+1); | |
9117f705 | 618 | if (equstr(p, conloc) && equtype(conloc[0], type)) |
bcaf9154 SL |
619 | return(conval+1); |
620 | return(p); | |
621 | } | |
622 | ||
623 | /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */ | |
624 | compare(op, acp1, acp2) | |
625 | char *acp1, *acp2; | |
626 | { | |
627 | register char *cp1, *cp2; | |
628 | register int n1, n2, sign; | |
629 | ||
630 | cp1 = acp1; | |
631 | cp2 = acp2; | |
632 | if (*cp1++ != '$' || *cp2++ != '$') | |
633 | return(-1); | |
634 | n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;} | |
635 | while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';} | |
636 | n1 *= sign; | |
637 | n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;} | |
638 | while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';} | |
639 | n2 *= sign; | |
640 | if (*cp1=='+') | |
641 | cp1++; | |
642 | if (*cp2=='+') | |
643 | cp2++; | |
644 | do { | |
645 | if (*cp1++ != *cp2) | |
646 | return(-1); | |
647 | } while (*cp2++); | |
648 | switch(op) { | |
649 | ||
650 | case JEQ: | |
651 | return(n1 == n2); | |
652 | case JNE: | |
653 | return(n1 != n2); | |
654 | case JLE: | |
655 | return(n1 <= n2); | |
656 | case JGE: | |
657 | return(n1 >= n2); | |
658 | case JLT: | |
659 | return(n1 < n2); | |
660 | case JGT: | |
661 | return(n1 > n2); | |
662 | case JLO: | |
663 | return((unsigned)n1 < (unsigned)n2); | |
664 | case JHI: | |
665 | return((unsigned)n1 > (unsigned)n2); | |
666 | case JLOS: | |
667 | return((unsigned)n1 <= (unsigned)n2); | |
668 | case JHIS: | |
669 | return((unsigned)n1 >= (unsigned)n2); | |
670 | } | |
671 | return(-1); | |
672 | } | |
673 | ||
674 | setcon(cv, cl, type) | |
675 | register char *cv, *cl; | |
676 | { | |
677 | register char *p; | |
678 | ||
679 | if (*cv != '$') | |
680 | return; | |
681 | if (!natural(cl)) | |
682 | return; | |
683 | p = conloc; | |
684 | while (*p++ = *cl++); | |
685 | p = conval; | |
686 | *p++ = type; | |
687 | while (*p++ = *cv++); | |
688 | } | |
689 | ||
690 | setcc(ap,type) | |
691 | char *ap; | |
692 | { | |
693 | register char *p, *p1; | |
694 | ||
695 | p = ap; | |
696 | if (!natural(p)) { | |
697 | ccloc[0] = 0; | |
698 | return; | |
699 | } | |
700 | p1 = ccloc; | |
701 | *p1++ = type; | |
702 | while (*p1++ = *p++); | |
703 | } | |
704 | ||
705 | indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ | |
706 | while (*p) if (*p++=='[') return(1); | |
707 | return(0); | |
708 | } | |
709 | ||
710 | natural(p) | |
711 | register char *p; | |
712 | {/* 1->simple local, parameter, global, or register; 0->otherwise */ | |
713 | ||
714 | if (*p=='*' || *p=='(' || *p=='$') | |
715 | return(0); | |
716 | while (*p++); | |
717 | p--; | |
718 | if (*--p==']' || *p==')' && | |
719 | !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1')) | |
720 | return(0); | |
721 | return(1); | |
722 | } | |
723 | ||
724 | /* | |
725 | ** Tell if an argument is most likely static. | |
726 | */ | |
727 | ||
728 | isstatic(cp) | |
729 | register char *cp; | |
730 | { | |
731 | if (*cp == '_' || *cp == 'L') | |
732 | return (1); | |
733 | return (0); | |
734 | } | |
e6c8f4f3 SL |
735 | |
736 | ||
737 | checkaobdisp(p) | |
738 | register struct node *p; | |
739 | { | |
740 | register struct node *q; | |
741 | register int i; | |
742 | ||
743 | ||
744 | if (!aobflag) return(1); | |
745 | /* backward search */ | |
746 | i = 0; | |
747 | q = p; | |
748 | while (i++ < MAXAOBDISP && ((q= q->back) !=&first)) | |
749 | { | |
750 | if (p->ref == q) | |
751 | return(1); | |
752 | } | |
753 | ||
754 | /* forward search */ | |
755 | i = 0; | |
756 | q = p; | |
757 | while (i++ < MAXAOBDISP && ((q= q->forw) !=0)) | |
758 | { | |
759 | if (p->ref == q) | |
760 | return(1); | |
761 | } | |
762 | return(0); | |
763 | } | |
764 | ||
765 | ||
766 | struct intleavetab intltab[] = { | |
767 | ADDF, FLOAT, 1, | |
768 | ADDF, DOUBLE, 1, | |
769 | SUBF, FLOAT, 1, | |
770 | SUBF, DOUBLE, 1, | |
771 | MULF, FLOAT, 1, | |
772 | MULF, DOUBLE, 1, | |
773 | DIVF, FLOAT, 1, | |
774 | DIVF, DOUBLE, 1, | |
775 | SINF, FLOAT, 1, | |
776 | COSF, FLOAT, 1, | |
777 | ATANF, FLOAT, 1, | |
778 | LOGF, FLOAT, 1, | |
779 | SQRTF, FLOAT, 1, | |
780 | EXPF, FLOAT, 1, | |
781 | LDF, FLOAT, 0, | |
782 | LDF, DOUBLE, 0, | |
783 | LNF, FLOAT, 0, | |
784 | LNF, DOUBLE, 0, | |
785 | STF, FLOAT, 0, | |
786 | CMPF, FLOAT, 0, | |
787 | CMPF, DOUBLE, 0, | |
788 | CMPF2, FLOAT, 0, | |
789 | TSTF, FLOAT, 0, | |
790 | TSTF, DOUBLE, 0, | |
791 | PUSHD, DOUBLE, 0, | |
792 | CVLF, U(LONG,FLOAT), 0, | |
793 | CVFL, U(FLOAT,LONG), 0, | |
794 | LDFD, U(FLOAT,DOUBLE),0, | |
795 | CVDF, U(DOUBLE,FLOAT),0, | |
796 | NEGF, FLOAT, 0, | |
864f1f35 | 797 | NIL, 0, 0}; |
e6c8f4f3 SL |
798 | |
799 | interleave() | |
800 | { | |
801 | register struct node *p, *p1; | |
802 | ||
803 | register struct intleavetab *t; | |
804 | register int r; | |
805 | int count; | |
806 | for (p= first.forw; p!=0; p = p->forw){ | |
807 | count = 0; | |
864f1f35 | 808 | for (t =intltab; t->op != NIL; t++){ |
e6c8f4f3 SL |
809 | if (t->op == p->op && t->subop == p->subop){ |
810 | count = t->intleavect; | |
811 | break; | |
812 | } | |
813 | } | |
814 | if (count < 1) continue; | |
815 | p1 = p->forw; | |
816 | clearuse(); | |
817 | clearreg(); | |
818 | while ((p1 != 0) && (p1->op != CBR) && | |
819 | (p1->subop == FLOAT || p1->subop == DOUBLE || | |
820 | ((p1->subop&0xF0)==DOUBLE<<4) || ((p1->subop&0xF)==DOUBLE )|| | |
821 | ((p1->subop&0xF0)==FLOAT<<4) || (p1->subop&0xF)==FLOAT)) | |
822 | { | |
823 | if (((r = isreg(p1->code)) >= 0)){ | |
824 | uses[r] = p1; | |
825 | if ((p1->subop == DOUBLE) || ((p->subop&0xF0)==DOUBLE<<4) || | |
826 | ((p->subop&0xF)==DOUBLE)) | |
827 | uses[r+1] = p1; | |
828 | } | |
829 | else checkreg(p1,p1->code); | |
830 | p1 = p1->forw; | |
831 | ||
832 | } | |
833 | if (p1 == 0) return; | |
834 | if (!(sideeffect(p, p1))) | |
835 | insertblk(p,p1); | |
836 | } | |
837 | ||
838 | } | |
839 | ||
840 | ||
841 | insertblk(p, p1) | |
842 | struct node *p, *p1; | |
843 | { | |
844 | p1->back->forw = p1->forw; | |
845 | p1->forw->back = p1->back; | |
846 | p1->forw = p->forw; | |
847 | p->forw->back = p1; | |
848 | p->forw = p1; | |
849 | p1->back = p; | |
850 | } | |
851 | ||
864f1f35 | 852 | OpCode termop[] = { |
e6c8f4f3 SL |
853 | JBR, CBR, JMP, LABEL, DLABEL, EROU, JSW, TST, CMP, BIT, |
854 | CALLF, CALLS, CASE, AOBLEQ, AOBLSS, CMPF, CMPF2, TSTF, MOVBLK, MFPR, | |
855 | MTPR, PROBE, MOVO, TEXT, DATA, BSS, ALIGN, END, LGEN, SET, | |
864f1f35 SL |
856 | LCOMM, COMM, NIL |
857 | }; | |
e6c8f4f3 SL |
858 | |
859 | sideeffect(p,p1) | |
860 | struct node *p, *p1; | |
861 | { | |
862 | register struct node *q; | |
863 | register int r; | |
864f1f35 | 864 | register OpCode *t; |
e6c8f4f3 SL |
865 | register char *cp; |
866 | int i; | |
867 | ||
864f1f35 | 868 | if (p1->op == NIL) return(1); /* special instructions */ |
e6c8f4f3 | 869 | |
864f1f35 | 870 | for (t = termop; *t!=NIL; t++){ |
e6c8f4f3 SL |
871 | if (*t == p1->op) return(1); |
872 | } | |
873 | if ((p1->forw != NULL) && (p1->forw->op == CBR)) | |
874 | return(1); | |
875 | splitrand(p1); | |
876 | r = isreg(lastrand); | |
877 | if (uses[r] && r >= 0 ) return(1); | |
878 | if ((p1->op == EDIV) && (r = isreg(regs[RT3]) >= 0) && | |
879 | (uses[r])) return(1); | |
880 | ||
881 | for (q = p1->back ; q!=p; q=q->back) | |
882 | { | |
883 | if ((p1->op == PUSH || p1->op == PUSHA) && | |
884 | (q->op == PUSHD || q->op == PUSH || q->op == PUSHA)) | |
885 | return(1); /* keep args in order */ | |
886 | if (((i = strlen(q->code)) >= 5 && /* cvdl -(sp); pushl r0*/ | |
887 | (strcmp(q->code+i-5,"-(sp)") == 0 )) || | |
888 | (strcmp(lastrand,"-(sp)") == 0)) return(1); | |
889 | if (equstr(q->code, lastrand)) | |
890 | return(1); | |
891 | if (q->op == STF || q->op == CVFL || q->op == CVLF) | |
892 | { | |
893 | if (equstr(q->code, regs[RT1])) return(1); | |
864f1f35 | 894 | if (has3ops(p1) || p1->op == EMUL || p1->op == EDIV) |
e6c8f4f3 SL |
895 | if (equstr(q->code, regs[RT2])) |
896 | return(1); | |
897 | /* handle the case std -56(fp) pushl -60(fp) pushl | |
898 | -56(fp); | |
899 | */ | |
900 | if ((p1->forw != NULL) && (q->op == STF) && | |
901 | (q->subop == DOUBLE)){ | |
902 | if (!strncmp(q->code,p1->forw->code,strlen(q->code))) | |
903 | return(1); | |
904 | } | |
905 | } | |
906 | } | |
907 | return(0); | |
908 | } | |
909 | checkreg(p,s) | |
910 | struct node *p; | |
911 | char *s; | |
912 | { | |
913 | char *cp2; | |
914 | register int r; | |
915 | /* check for (r),[r] */ | |
916 | do if (*s=='(' || *s=='[') {/* get register number */ | |
917 | char t; | |
918 | cp2= ++s; while (*++s!=')' && *s!=']'); t= *s; *s=0; | |
919 | if ((r=isreg(cp2)) >= 0) { | |
920 | uses[r]=p; | |
921 | } | |
922 | *s=t; | |
923 | } while (*++s); | |
924 | } |