Commit | Line | Data |
---|---|---|
bb8f3f2b BJ |
1 | static char *sccsid ="%W% (Berkeley) %G%"; |
2 | # include "mfile2" | |
3 | # include "ctype.h" | |
4 | /* a lot of the machine dependent parts of the second pass */ | |
5 | ||
6 | # define BITMASK(n) ((1L<<n)-1) | |
7 | ||
8 | where(c){ | |
9 | fprintf( stderr, "%s, line %d: ", filename, lineno ); | |
10 | } | |
11 | ||
12 | lineid( l, fn ) char *fn; { | |
13 | /* identify line l and file fn */ | |
14 | printf( "# line %d, file %s\n", l, fn ); | |
15 | } | |
16 | ||
17 | ||
18 | eobl2(){ | |
19 | OFFSZ spoff; /* offset from stack pointer */ | |
20 | #ifdef FORT | |
21 | spoff = maxoff; | |
22 | if( spoff >= AUTOINIT ) spoff -= AUTOINIT; | |
23 | spoff /= SZCHAR; | |
24 | SETOFF(spoff,4); | |
25 | #ifndef FLEXNAMES | |
26 | printf( " .set .F%d,%ld\n", ftnno, spoff ); | |
27 | #else | |
28 | /* SHOULD BE L%d ... ftnno but must change pc/f77 */ | |
29 | printf( " .set LF%d,%ld\n", ftnno, spoff ); | |
30 | #endif | |
31 | #else | |
32 | extern int ftlab1, ftlab2; | |
33 | ||
34 | spoff = maxoff; | |
35 | if( spoff >= AUTOINIT ) spoff -= AUTOINIT; | |
36 | spoff /= SZCHAR; | |
37 | SETOFF(spoff,4); | |
38 | printf( "L%d:\n", ftlab1); | |
39 | if( spoff!=0 ) | |
40 | if( spoff < 64 ) | |
41 | printf( " subl2 $%ld,sp\n", spoff); | |
42 | else | |
43 | printf( " movab -%ld(sp),sp\n", spoff); | |
44 | printf( " jbr L%d\n", ftlab2); | |
45 | #endif | |
46 | maxargs = -1; | |
47 | } | |
48 | ||
49 | struct hoptab { int opmask; char * opstring; } ioptab[] = { | |
50 | ||
51 | ASG PLUS, "add", | |
52 | ASG MINUS, "sub", | |
53 | ASG MUL, "mul", | |
54 | ASG DIV, "div", | |
55 | ASG OR, "bis", | |
56 | ASG ER, "xor", | |
57 | ASG AND, "bic", | |
58 | PLUS, "add", | |
59 | MINUS, "sub", | |
60 | MUL, "mul", | |
61 | DIV, "div", | |
62 | OR, "bis", | |
63 | ER, "xor", | |
64 | AND, "bic", | |
65 | -1, "" }; | |
66 | ||
67 | hopcode( f, o ){ | |
68 | /* output the appropriate string from the above table */ | |
69 | ||
70 | register struct hoptab *q; | |
71 | ||
72 | for( q = ioptab; q->opmask>=0; ++q ){ | |
73 | if( q->opmask == o ){ | |
74 | printf( "%s", q->opstring ); | |
75 | /* tbl | |
76 | if( f == 'F' ) printf( "e" ); | |
77 | else if( f == 'D' ) printf( "d" ); | |
78 | tbl */ | |
79 | /* tbl */ | |
80 | switch( f ) { | |
81 | case 'L': | |
82 | case 'W': | |
83 | case 'B': | |
84 | case 'D': | |
85 | case 'F': | |
86 | printf("%c", tolower(f)); | |
87 | break; | |
88 | ||
89 | } | |
90 | /* tbl */ | |
91 | return; | |
92 | } | |
93 | } | |
94 | cerror( "no hoptab for %s", opst[o] ); | |
95 | } | |
96 | ||
97 | char * | |
98 | rnames[] = { /* keyed to register number tokens */ | |
99 | ||
100 | "r0", "r1", | |
101 | "r2", "r3", "r4", "r5", | |
102 | "r6", "r7", "r8", "r9", "r10", "r11", | |
103 | "ap", "fp", "sp", "pc", | |
104 | ||
105 | }; | |
106 | ||
107 | int rstatus[] = { | |
108 | SAREG|STAREG, SAREG|STAREG, | |
109 | SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, | |
110 | SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, | |
111 | SAREG, SAREG, SAREG, SAREG, | |
112 | ||
113 | }; | |
114 | ||
115 | tlen(p) NODE *p; | |
116 | { | |
117 | switch(p->in.type) { | |
118 | case CHAR: | |
119 | case UCHAR: | |
120 | return(1); | |
121 | ||
122 | case SHORT: | |
123 | case USHORT: | |
124 | return(2); | |
125 | ||
126 | case DOUBLE: | |
127 | return(8); | |
128 | ||
129 | default: | |
130 | return(4); | |
131 | } | |
132 | } | |
133 | ||
134 | mixtypes(p, q) NODE *p, *q; | |
135 | { | |
136 | register tp, tq; | |
137 | ||
138 | tp = p->in.type; | |
139 | tq = q->in.type; | |
140 | ||
141 | return( (tp==FLOAT || tp==DOUBLE) != | |
142 | (tq==FLOAT || tq==DOUBLE) ); | |
143 | } | |
144 | ||
145 | prtype(n) NODE *n; | |
146 | { | |
147 | switch (n->in.type) | |
148 | { | |
149 | case DOUBLE: | |
150 | printf("d"); | |
151 | return; | |
152 | ||
153 | case FLOAT: | |
154 | printf("f"); | |
155 | return; | |
156 | ||
157 | case LONG: | |
158 | case ULONG: | |
159 | case INT: | |
160 | case UNSIGNED: | |
161 | printf("l"); | |
162 | return; | |
163 | ||
164 | case SHORT: | |
165 | case USHORT: | |
166 | printf("w"); | |
167 | return; | |
168 | ||
169 | case CHAR: | |
170 | case UCHAR: | |
171 | printf("b"); | |
172 | return; | |
173 | ||
174 | default: | |
175 | if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); | |
176 | else { | |
177 | printf("l"); | |
178 | return; | |
179 | } | |
180 | } | |
181 | } | |
182 | ||
183 | zzzcode( p, c ) register NODE *p; { | |
184 | register m; | |
185 | CONSZ val; | |
186 | switch( c ){ | |
187 | ||
188 | case 'N': /* logical ops, turned into 0-1 */ | |
189 | /* use register given by register 1 */ | |
190 | cbgen( 0, m=getlab(), 'I' ); | |
191 | deflab( p->bn.label ); | |
192 | printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); | |
193 | deflab( m ); | |
194 | return; | |
195 | ||
196 | case 'I': | |
197 | case 'P': | |
198 | cbgen( p->in.op, p->bn.label, c ); | |
199 | return; | |
200 | ||
201 | case 'A': | |
202 | { | |
203 | register NODE *l, *r; | |
204 | ||
205 | if (xdebug) eprint(p, 0, &val, &val); | |
206 | r = getlr(p, 'R'); | |
207 | if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL) | |
208 | { | |
209 | l = resc; | |
210 | l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); | |
211 | } | |
212 | else | |
213 | l = getlr(p, 'L'); | |
214 | if (r->in.op == ICON) | |
215 | if(r->in.name[0] == '\0') | |
216 | { | |
217 | if (r->tn.lval == 0) | |
218 | { | |
219 | printf("clr"); | |
220 | prtype(l); | |
221 | printf(" "); | |
222 | adrput(l); | |
223 | return; | |
224 | } | |
225 | if (r->tn.lval < 0 && r->tn.lval >= -63) | |
226 | { | |
227 | printf("mneg"); | |
228 | prtype(l); | |
229 | r->tn.lval = -r->tn.lval; | |
230 | goto ops; | |
231 | } | |
232 | r->in.type = (r->tn.lval < 0 ? | |
233 | (r->tn.lval >= -128 ? CHAR | |
234 | : (r->tn.lval >= -32768 ? SHORT | |
235 | : INT )) : r->in.type); | |
236 | r->in.type = (r->tn.lval >= 0 ? | |
237 | (r->tn.lval <= 63 ? INT | |
238 | : ( r->tn.lval <= 127 ? CHAR | |
239 | : (r->tn.lval <= 255 ? UCHAR | |
240 | : (r->tn.lval <= 32767 ? SHORT | |
241 | : (r->tn.lval <= 65535 ? USHORT | |
242 | : INT ))))) : r->in.type ); | |
243 | } | |
244 | else | |
245 | { | |
246 | printf("moval"); | |
247 | printf(" "); | |
248 | acon(r); | |
249 | printf(","); | |
250 | adrput(l); | |
251 | return; | |
252 | } | |
253 | ||
254 | if (l->in.op == REG && l->in.type != FLOAT && l->in.type != DOUBLE) | |
255 | { | |
256 | if( tlen(l) < tlen(r) ) | |
257 | { | |
258 | if (!mixtypes(l,r)) | |
259 | { | |
260 | !ISUNSIGNED(l->in.type)? | |
261 | printf("cvt"): | |
262 | printf("movz"); | |
263 | prtype(l); | |
264 | printf("l"); | |
265 | goto ops; | |
266 | } | |
267 | else | |
268 | { | |
269 | printf("cvt"); | |
270 | prtype(r); | |
271 | prtype(l); | |
272 | printf(" "); | |
273 | adrput(r); | |
274 | printf(","); | |
275 | adrput(l); | |
276 | printf("cvt"); | |
277 | prtype(l); | |
278 | printf("l"); | |
279 | printf(" "); | |
280 | adrput(l); | |
281 | printf(","); | |
282 | adrput(l); | |
283 | return; | |
284 | } | |
285 | } | |
286 | else | |
287 | { | |
288 | l->in.type = INT; | |
289 | } | |
290 | } | |
291 | if (!mixtypes(l,r)) | |
292 | { | |
293 | if (tlen(l) == tlen(r)) | |
294 | { | |
295 | printf("mov"); | |
296 | prtype(l); | |
297 | goto ops; | |
298 | } | |
299 | else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) | |
300 | { | |
301 | printf("movz"); | |
302 | } | |
303 | else | |
304 | { | |
305 | printf("cvt"); | |
306 | } | |
307 | } | |
308 | else | |
309 | { | |
310 | printf("cvt"); | |
311 | } | |
312 | prtype(r); | |
313 | prtype(l); | |
314 | ops: | |
315 | printf(" "); | |
316 | adrput(r); | |
317 | printf(","); | |
318 | adrput(l); | |
319 | return; | |
320 | } | |
321 | ||
322 | case 'B': /* get oreg value in temp register for left shift */ | |
323 | { | |
324 | register NODE *r; | |
325 | if (xdebug) eprint(p, 0, &val, &val); | |
326 | r = p->in.right; | |
327 | if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) | |
328 | printf("movl"); | |
329 | else { | |
330 | printf("cvt"); | |
331 | prtype(r); | |
332 | printf("l"); | |
333 | } | |
334 | return; | |
335 | } | |
336 | ||
337 | case 'C': /* num words pushed on arg stack */ | |
338 | { | |
339 | extern int gc_numbytes; | |
340 | extern int xdebug; | |
341 | ||
342 | if (xdebug) printf("->%d<-",gc_numbytes); | |
343 | ||
344 | printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); | |
345 | return; | |
346 | } | |
347 | ||
348 | case 'D': /* INCR and DECR */ | |
349 | zzzcode(p->in.left, 'A'); | |
350 | printf("\n "); | |
351 | ||
352 | case 'E': /* INCR and DECR, FOREFF */ | |
353 | if (p->in.right->tn.lval == 1) | |
354 | { | |
355 | printf("%s", (p->in.op == INCR ? "inc" : "dec") ); | |
356 | prtype(p->in.left); | |
357 | printf(" "); | |
358 | adrput(p->in.left); | |
359 | return; | |
360 | } | |
361 | printf("%s", (p->in.op == INCR ? "add" : "sub") ); | |
362 | prtype(p->in.left); | |
363 | printf("2 "); | |
364 | adrput(p->in.right); | |
365 | printf(","); | |
366 | adrput(p->in.left); | |
367 | return; | |
368 | ||
369 | case 'F': /* register type of right operand */ | |
370 | { | |
371 | register NODE *n; | |
372 | extern int xdebug; | |
373 | register int ty; | |
374 | ||
375 | n = getlr( p, 'R' ); | |
376 | ty = n->in.type; | |
377 | ||
378 | if (xdebug) printf("->%d<-", ty); | |
379 | ||
380 | if ( ty==DOUBLE) printf("d"); | |
381 | else if ( ty==FLOAT ) printf("f"); | |
382 | else printf("l"); | |
383 | return; | |
384 | } | |
385 | ||
386 | case 'L': /* type of left operand */ | |
387 | case 'R': /* type of right operand */ | |
388 | { | |
389 | register NODE *n; | |
390 | extern int xdebug; | |
391 | ||
392 | n = getlr ( p, c); | |
393 | if (xdebug) printf("->%d<-", n->in.type); | |
394 | ||
395 | prtype(n); | |
396 | return; | |
397 | } | |
398 | ||
399 | case 'Z': /* complement mask for bit instr */ | |
400 | printf("$%ld", ~p->in.right->tn.lval); | |
401 | return; | |
402 | ||
403 | case 'U': /* 32 - n, for unsigned right shifts */ | |
404 | printf("$%d", 32 - p->in.right->tn.lval ); | |
405 | return; | |
406 | ||
407 | case 'T': /* rounded structure length for arguments */ | |
408 | { | |
409 | int size; | |
410 | ||
411 | size = p->stn.stsize; | |
412 | SETOFF( size, 4); | |
413 | printf("$%d", size); | |
414 | return; | |
415 | } | |
416 | ||
417 | case 'S': /* structure assignment */ | |
418 | { | |
419 | register NODE *l, *r; | |
420 | register size; | |
421 | ||
422 | if( p->in.op == STASG ){ | |
423 | l = p->in.left; | |
424 | r = p->in.right; | |
425 | ||
426 | } | |
427 | else if( p->in.op == STARG ){ /* store an arg into a temporary */ | |
428 | l = getlr( p, '3' ); | |
429 | r = p->in.left; | |
430 | } | |
431 | else cerror( "STASG bad" ); | |
432 | ||
433 | if( r->in.op == ICON ) r->in.op = NAME; | |
434 | else if( r->in.op == REG ) r->in.op = OREG; | |
435 | else if( r->in.op != OREG ) cerror( "STASG-r" ); | |
436 | ||
437 | size = p->stn.stsize; | |
438 | ||
439 | if( size <= 0 || size > 65535 ) | |
440 | cerror("structure size <0=0 or >65535"); | |
441 | ||
442 | switch(size) { | |
443 | case 1: | |
444 | printf(" movb "); | |
445 | break; | |
446 | case 2: | |
447 | printf(" movw "); | |
448 | break; | |
449 | case 4: | |
450 | printf(" movl "); | |
451 | break; | |
452 | case 8: | |
453 | printf(" movq "); | |
454 | break; | |
455 | default: | |
456 | printf(" movc3 $%d,", size); | |
457 | break; | |
458 | } | |
459 | adrput(r); | |
460 | printf(","); | |
461 | adrput(l); | |
462 | printf("\n"); | |
463 | ||
464 | if( r->in.op == NAME ) r->in.op = ICON; | |
465 | else if( r->in.op == OREG ) r->in.op = REG; | |
466 | ||
467 | } | |
468 | break; | |
469 | ||
470 | default: | |
471 | cerror( "illegal zzzcode" ); | |
472 | } | |
473 | } | |
474 | ||
475 | rmove( rt, rs, t ){ | |
476 | printf( " %s %s,%s\n", | |
477 | (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), | |
478 | rnames[rs], rnames[rt] ); | |
479 | } | |
480 | ||
481 | struct respref | |
482 | respref[] = { | |
483 | INTAREG|INTBREG, INTAREG|INTBREG, | |
484 | INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, | |
485 | INTEMP, INTEMP, | |
486 | FORARG, FORARG, | |
487 | INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, | |
488 | 0, 0 }; | |
489 | ||
490 | setregs(){ /* set up temporary registers */ | |
491 | fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ | |
492 | ; | |
493 | } | |
494 | ||
495 | szty(t){ /* size, in registers, needed to hold thing of type t */ | |
496 | return( (t==DOUBLE||t==FLOAT) ? 2 : 1 ); | |
497 | } | |
498 | ||
499 | rewfld( p ) NODE *p; { | |
500 | return(1); | |
501 | } | |
502 | ||
503 | callreg(p) NODE *p; { | |
504 | return( R0 ); | |
505 | } | |
506 | ||
507 | base( p ) register NODE *p; { | |
508 | register int o = p->in.op; | |
509 | ||
510 | if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ | |
511 | if( o==REG ) return( p->tn.rval ); | |
512 | if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) | |
513 | return( p->in.left->tn.rval ); | |
514 | if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) | |
515 | return( p->tn.rval + 0200*1 ); | |
516 | if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); | |
517 | if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); | |
518 | if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG | |
519 | && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) | |
520 | return( p->in.left->in.left->tn.rval + 0200*(1+2) ); | |
521 | return( -1 ); | |
522 | } | |
523 | ||
524 | offset( p, tyl ) register NODE *p; int tyl; { | |
525 | ||
526 | if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval ); | |
527 | if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && | |
528 | (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0') | |
529 | && (1<<p->in.right->tn.lval)==tyl)) | |
530 | return( p->in.left->tn.rval ); | |
531 | return( -1 ); | |
532 | } | |
533 | ||
534 | makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { | |
535 | register NODE *t; | |
536 | register int i; | |
537 | NODE *f; | |
538 | ||
539 | p->in.op = OREG; | |
540 | f = p->in.left; /* have to free this subtree later */ | |
541 | ||
542 | /* init base */ | |
543 | switch (q->in.op) { | |
544 | case ICON: | |
545 | case REG: | |
546 | case OREG: | |
547 | t = q; | |
548 | break; | |
549 | ||
550 | case MINUS: | |
551 | q->in.right->tn.lval = -q->in.right->tn.lval; | |
552 | case PLUS: | |
553 | t = q->in.right; | |
554 | break; | |
555 | ||
556 | case INCR: | |
557 | case ASG MINUS: | |
558 | t = q->in.left; | |
559 | break; | |
560 | ||
561 | case UNARY MUL: | |
562 | t = q->in.left->in.left; | |
563 | break; | |
564 | ||
565 | default: | |
566 | cerror("illegal makeor2"); | |
567 | } | |
568 | ||
569 | p->tn.lval = t->tn.lval; | |
570 | #ifndef FLEXNAMES | |
571 | for(i=0; i<NCHNAM; ++i) | |
572 | p->in.name[i] = t->in.name[i]; | |
573 | #else | |
574 | p->in.name = t->in.name; | |
575 | #endif | |
576 | ||
577 | /* init offset */ | |
578 | p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); | |
579 | ||
580 | tfree(f); | |
581 | return; | |
582 | } | |
583 | ||
584 | canaddr( p ) NODE *p; { | |
585 | register int o = p->in.op; | |
586 | ||
587 | if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); | |
588 | return(0); | |
589 | } | |
590 | ||
591 | shltype( o, p ) register NODE *p; { | |
592 | return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) ); | |
593 | } | |
594 | ||
595 | flshape( p ) register NODE *p; { | |
596 | return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || | |
597 | (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); | |
598 | } | |
599 | ||
600 | shtemp( p ) register NODE *p; { | |
601 | if( p->in.op == STARG ) p = p->in.left; | |
602 | return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); | |
603 | } | |
604 | ||
605 | shumul( p ) register NODE *p; { | |
606 | register o; | |
607 | extern int xdebug; | |
608 | ||
609 | if (xdebug) { | |
610 | printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); | |
611 | printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); | |
612 | } | |
613 | ||
614 | ||
615 | o = p->in.op; | |
616 | if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); | |
617 | ||
618 | if( ( o == INCR || o == ASG MINUS ) && | |
619 | ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && | |
620 | p->in.right->in.name[0] == '\0' ) | |
621 | { | |
622 | switch (p->in.left->in.type) | |
623 | { | |
624 | case CHAR|PTR: | |
625 | case UCHAR|PTR: | |
626 | o = 1; | |
627 | break; | |
628 | ||
629 | case SHORT|PTR: | |
630 | case USHORT|PTR: | |
631 | o = 2; | |
632 | break; | |
633 | ||
634 | case INT|PTR: | |
635 | case UNSIGNED|PTR: | |
636 | case LONG|PTR: | |
637 | case ULONG|PTR: | |
638 | case FLOAT|PTR: | |
639 | o = 4; | |
640 | break; | |
641 | ||
642 | case DOUBLE|PTR: | |
643 | o = 8; | |
644 | break; | |
645 | ||
646 | default: | |
647 | if ( ISPTR(p->in.left->in.type) ) { | |
648 | o = 4; | |
649 | break; | |
650 | } | |
651 | else return(0); | |
652 | } | |
653 | return( p->in.right->tn.lval == o ? STARREG : 0); | |
654 | } | |
655 | ||
656 | return( 0 ); | |
657 | } | |
658 | ||
659 | adrcon( val ) CONSZ val; { | |
660 | printf( "$" ); | |
661 | printf( CONFMT, val ); | |
662 | } | |
663 | ||
664 | conput( p ) register NODE *p; { | |
665 | switch( p->in.op ){ | |
666 | ||
667 | case ICON: | |
668 | acon( p ); | |
669 | return; | |
670 | ||
671 | case REG: | |
672 | printf( "%s", rnames[p->tn.rval] ); | |
673 | return; | |
674 | ||
675 | default: | |
676 | cerror( "illegal conput" ); | |
677 | } | |
678 | } | |
679 | ||
680 | insput( p ) register NODE *p; { | |
681 | cerror( "insput" ); | |
682 | } | |
683 | ||
684 | upput( p ) register NODE *p; { | |
685 | cerror( "upput" ); | |
686 | } | |
687 | ||
688 | adrput( p ) register NODE *p; { | |
689 | register int r; | |
690 | /* output an address, with offsets, from p */ | |
691 | ||
692 | if( p->in.op == FLD ){ | |
693 | p = p->in.left; | |
694 | } | |
695 | switch( p->in.op ){ | |
696 | ||
697 | case NAME: | |
698 | acon( p ); | |
699 | return; | |
700 | ||
701 | case ICON: | |
702 | /* addressable value of the constant */ | |
703 | printf( "$" ); | |
704 | acon( p ); | |
705 | return; | |
706 | ||
707 | case REG: | |
708 | printf( "%s", rnames[p->tn.rval] ); | |
709 | return; | |
710 | ||
711 | case OREG: | |
712 | r = p->tn.rval; | |
713 | if( R2TEST(r) ){ /* double indexing */ | |
714 | register int flags; | |
715 | ||
716 | flags = R2UPK3(r); | |
717 | if( flags & 1 ) printf("*"); | |
718 | if( flags & 4 ) printf("-"); | |
719 | if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); | |
720 | if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); | |
721 | if( flags & 2 ) printf("+"); | |
722 | printf( "[%s]", rnames[R2UPK2(r)] ); | |
723 | return; | |
724 | } | |
725 | if( r == AP ){ /* in the argument region */ | |
726 | if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" ); | |
727 | printf( CONFMT, p->tn.lval ); | |
728 | printf( "(ap)" ); | |
729 | return; | |
730 | } | |
731 | if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); | |
732 | printf( "(%s)", rnames[p->tn.rval] ); | |
733 | return; | |
734 | ||
735 | case UNARY MUL: | |
736 | /* STARNM or STARREG found */ | |
737 | if( tshape(p, STARNM) ) { | |
738 | printf( "*" ); | |
739 | adrput( p->in.left); | |
740 | } | |
741 | else { /* STARREG - really auto inc or dec */ | |
742 | register NODE *q; | |
743 | ||
744 | /* tbl | |
745 | p = p->in.left; | |
746 | p->in.left->in.op = OREG; | |
747 | if( p->in.op == INCR ) { | |
748 | adrput( p->in.left ); | |
749 | printf( "+" ); | |
750 | } | |
751 | else { | |
752 | printf( "-" ); | |
753 | adrput( p->in.left ); | |
754 | } | |
755 | tbl */ | |
756 | printf("%s(%s)%s", (p->in.left->in.op==INCR ? "" : "-"), | |
757 | rnames[p->in.left->in.left->tn.rval], | |
758 | (p->in.left->in.op==INCR ? "+" : "") ); | |
759 | p->in.op = OREG; | |
760 | p->tn.rval = p->in.left->in.left->tn.rval; | |
761 | q = p->in.left; | |
762 | p->tn.lval = (p->in.left->in.op == INCR ? -p->in.left->in.right->tn.lval : 0); | |
763 | #ifndef FLEXNAMES | |
764 | p->in.name[0] = '\0'; | |
765 | #else | |
766 | p->in.name = ""; | |
767 | #endif | |
768 | tfree(q); | |
769 | } | |
770 | return; | |
771 | ||
772 | default: | |
773 | cerror( "illegal address" ); | |
774 | return; | |
775 | ||
776 | } | |
777 | ||
778 | } | |
779 | ||
780 | acon( p ) register NODE *p; { /* print out a constant */ | |
781 | ||
782 | if( p->in.name[0] == '\0' ){ | |
783 | printf( CONFMT, p->tn.lval); | |
784 | } | |
785 | else if( p->tn.lval == 0 ) { | |
786 | #ifndef FLEXNAMES | |
787 | printf( "%.8s", p->in.name ); | |
788 | #else | |
789 | printf( "%s", p->in.name ); | |
790 | #endif | |
791 | } | |
792 | else { | |
793 | #ifndef FLEXNAMES | |
794 | printf( "%.8s+", p->in.name ); | |
795 | #else | |
796 | printf( "%s+", p->in.name ); | |
797 | #endif | |
798 | printf( CONFMT, p->tn.lval ); | |
799 | } | |
800 | } | |
801 | ||
802 | /* | |
803 | aacon( p ) register NODE *p; { /* print out a constant */ | |
804 | /* | |
805 | ||
806 | if( p->in.name[0] == '\0' ){ | |
807 | printf( CONFMT, p->tn.lval); | |
808 | return( 0 ); | |
809 | } | |
810 | else if( p->tn.lval == 0 ) { | |
811 | #ifndef FLEXNAMES | |
812 | printf( "$%.8s", p->in.name ); | |
813 | #else | |
814 | printf( "$%s", p->in.name ); | |
815 | #endif | |
816 | return( 1 ); | |
817 | } | |
818 | else { | |
819 | printf( "$(" ); | |
820 | printf( CONFMT, p->tn.lval ); | |
821 | printf( "+" ); | |
822 | #ifndef FLEXNAMES | |
823 | printf( "%.8s)", p->in.name ); | |
824 | #else | |
825 | printf( "%s)", p->in.name ); | |
826 | #endif | |
827 | return(1); | |
828 | } | |
829 | } | |
830 | */ | |
831 | ||
832 | genscall( p, cookie ) register NODE *p; { | |
833 | /* structure valued call */ | |
834 | return( gencall( p, cookie ) ); | |
835 | } | |
836 | ||
837 | /* tbl */ | |
838 | int gc_numbytes; | |
839 | /* tbl */ | |
840 | ||
841 | gencall( p, cookie ) register NODE *p; { | |
842 | /* generate the call given by p */ | |
843 | register NODE *p1, *ptemp; | |
844 | register temp, temp1; | |
845 | register m; | |
846 | ||
847 | if( p->in.right ) temp = argsize( p->in.right ); | |
848 | else temp = 0; | |
849 | ||
850 | if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ | |
851 | /* set aside room for structure return */ | |
852 | ||
853 | if( p->stn.stsize > temp ) temp1 = p->stn.stsize; | |
854 | else temp1 = temp; | |
855 | } | |
856 | ||
857 | if( temp > maxargs ) maxargs = temp; | |
858 | SETOFF(temp1,4); | |
859 | ||
860 | if( p->in.right ){ /* make temp node, put offset in, and generate args */ | |
861 | ptemp = talloc(); | |
862 | ptemp->in.op = OREG; | |
863 | ptemp->tn.lval = -1; | |
864 | ptemp->tn.rval = SP; | |
865 | #ifndef FLEXNAMES | |
866 | ptemp->in.name[0] = '\0'; | |
867 | #else | |
868 | ptemp->in.name = ""; | |
869 | #endif | |
870 | ptemp->in.rall = NOPREF; | |
871 | ptemp->in.su = 0; | |
872 | genargs( p->in.right, ptemp ); | |
873 | ptemp->in.op = FREE; | |
874 | } | |
875 | ||
876 | p1 = p->in.left; | |
877 | if( p1->in.op != ICON ){ | |
878 | if( p1->in.op != REG ){ | |
879 | if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ | |
880 | if( p1->in.op != NAME ){ | |
881 | order( p1, INAREG ); | |
882 | } | |
883 | } | |
884 | } | |
885 | } | |
886 | ||
887 | /* | |
888 | if( p1->in.op == REG && p->tn.rval == R5 ){ | |
889 | cerror( "call register overwrite" ); | |
890 | } | |
891 | */ | |
892 | /* tbl | |
893 | setup gc_numbytes so reference to ZC works */ | |
894 | ||
895 | gc_numbytes = temp; | |
896 | /* tbl */ | |
897 | ||
898 | p->in.op = UNARY CALL; | |
899 | m = match( p, INTAREG|INTBREG ); | |
900 | /* tbl | |
901 | switch( temp ) { | |
902 | case 0: | |
903 | break; | |
904 | case 2: | |
905 | printf( " tst (sp)+\n" ); | |
906 | break; | |
907 | case 4: | |
908 | printf( " cmp (sp)+,(sp)+\n" ); | |
909 | break; | |
910 | default: | |
911 | printf( " add $%d,sp\n", temp); | |
912 | } | |
913 | tbl */ | |
914 | return(m != MDONE); | |
915 | } | |
916 | ||
917 | /* tbl */ | |
918 | char * | |
919 | ccbranches[] = { | |
920 | " jeql L%d\n", | |
921 | " jneq L%d\n", | |
922 | " jleq L%d\n", | |
923 | " jlss L%d\n", | |
924 | " jgeq L%d\n", | |
925 | " jgtr L%d\n", | |
926 | " jlequ L%d\n", | |
927 | " jlssu L%d\n", | |
928 | " jgequ L%d\n", | |
929 | " jgtru L%d\n", | |
930 | }; | |
931 | /* tbl */ | |
932 | ||
933 | cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ | |
934 | ||
935 | /* tbl */ | |
936 | if( o == 0 ) printf( " jbr L%d\n", lab ); | |
937 | /* tbl */ | |
938 | else { | |
939 | if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); | |
940 | printf( ccbranches[o-EQ], lab ); | |
941 | } | |
942 | } | |
943 | ||
944 | nextcook( p, cookie ) NODE *p; { | |
945 | /* we have failed to match p with cookie; try another */ | |
946 | if( cookie == FORREW ) return( 0 ); /* hopeless! */ | |
947 | if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); | |
948 | if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); | |
949 | return( FORREW ); | |
950 | } | |
951 | ||
952 | lastchance( p, cook ) NODE *p; { | |
953 | /* forget it! */ | |
954 | return(0); | |
955 | } | |
956 | ||
957 | optim2( p ) register NODE *p; { | |
958 | /* do local tree transformations and optimizations */ | |
959 | ||
960 | register NODE *r; | |
961 | ||
962 | switch( p->in.op ) { | |
963 | ||
964 | case AND: | |
965 | /* commute L and R to eliminate compliments and constants */ | |
966 | if( (p->in.left->in.op==ICON&&p->in.left->in.name[0]==0) || p->in.left->in.op==COMPL ) { | |
967 | r = p->in.left; | |
968 | p->in.left = p->in.right; | |
969 | p->in.right = r; | |
970 | } | |
971 | case ASG AND: | |
972 | /* change meaning of AND to ~R&L - bic on pdp11 */ | |
973 | r = p->in.right; | |
974 | if( r->in.op==ICON && r->in.name[0]==0 ) { /* compliment constant */ | |
975 | r->tn.lval = ~r->tn.lval; | |
976 | } | |
977 | else if( r->in.op==COMPL ) { /* ~~A => A */ | |
978 | r->in.op = FREE; | |
979 | p->in.right = r->in.left; | |
980 | } | |
981 | else { /* insert complement node */ | |
982 | p->in.right = talloc(); | |
983 | p->in.right->in.op = COMPL; | |
984 | p->in.right->in.rall = NOPREF; | |
985 | p->in.right->in.type = r->in.type; | |
986 | p->in.right->in.left = r; | |
987 | p->in.right->in.right = NULL; | |
988 | } | |
989 | break; | |
990 | ||
991 | } | |
992 | } | |
993 | ||
994 | NODE * addroreg(l) | |
995 | /* OREG was built in clocal() | |
996 | * for an auto or formal parameter | |
997 | * now its address is being taken | |
998 | * local code must unwind it | |
999 | * back to PLUS/MINUS REG ICON | |
1000 | * according to local conventions | |
1001 | */ | |
1002 | { | |
1003 | cerror("address of OREG taken"); | |
1004 | } | |
1005 | ||
1006 | ||
1007 | ||
1008 | # ifndef ONEPASS | |
1009 | main( argc, argv ) char *argv[]; { | |
1010 | return( mainp2( argc, argv ) ); | |
1011 | } | |
1012 | # endif | |
1013 | ||
1014 | ||
1015 | /* added by jwf */ | |
1016 | struct functbl { | |
1017 | int fop; | |
1018 | TWORD ftype; | |
1019 | char *func; | |
1020 | } opfunc[] = { | |
1021 | DIV, TANY, "udiv", | |
1022 | MOD, TANY, "urem", | |
1023 | ASG DIV, TANY, "udiv", | |
1024 | ASG MOD, TANY, "urem", | |
1025 | 0, 0, 0 }; | |
1026 | ||
1027 | hardops(p) register NODE *p; { | |
1028 | /* change hard to do operators into function calls. */ | |
1029 | register NODE *q; | |
1030 | register struct functbl *f; | |
1031 | register o; | |
1032 | register TWORD t; | |
1033 | ||
1034 | o = p->in.op; | |
1035 | t = p->in.type; | |
1036 | if( t!=UNSIGNED && t!=ULONG ) return; | |
1037 | ||
1038 | for( f=opfunc; f->fop; f++ ) { | |
1039 | if( o==f->fop ) goto convert; | |
1040 | } | |
1041 | return; | |
1042 | ||
1043 | /* need to rewrite tree for ASG OP */ | |
1044 | /* must change ASG OP to a simple OP */ | |
1045 | convert: | |
1046 | if( asgop( o ) ) { | |
1047 | q = talloc(); | |
1048 | switch( p->in.op ) { | |
1049 | case ASG DIV: | |
1050 | q->in.op = DIV; | |
1051 | break; | |
1052 | case ASG MOD: | |
1053 | q->in.op = MOD; | |
1054 | break; | |
1055 | } | |
1056 | q->in.rall = NOPREF; | |
1057 | q->in.type = p->in.type; | |
1058 | q->in.left = tcopy(p->in.left); | |
1059 | q->in.right = p->in.right; | |
1060 | p->in.op = ASSIGN; | |
1061 | p->in.right = q; | |
1062 | zappost(q->in.left); /* remove post-INCR(DECR) from new node */ | |
1063 | fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */ | |
1064 | p = q; | |
1065 | ||
1066 | } | |
1067 | ||
1068 | /* build comma op for args to function */ | |
1069 | q = talloc(); | |
1070 | q->in.op = CM; | |
1071 | q->in.rall = NOPREF; | |
1072 | q->in.type = INT; | |
1073 | q->in.left = p->in.left; | |
1074 | q->in.right = p->in.right; | |
1075 | p->in.op = CALL; | |
1076 | p->in.right = q; | |
1077 | ||
1078 | /* put function name in left node of call */ | |
1079 | p->in.left = q = talloc(); | |
1080 | q->in.op = ICON; | |
1081 | q->in.rall = NOPREF; | |
1082 | q->in.type = INCREF( FTN + p->in.type ); | |
1083 | #ifndef FLEXNAMES | |
1084 | strcpy( q->in.name, f->func ); | |
1085 | #else | |
1086 | q->in.name = f->func; | |
1087 | #endif | |
1088 | q->tn.lval = 0; | |
1089 | q->tn.rval = 0; | |
1090 | ||
1091 | return; | |
1092 | ||
1093 | } | |
1094 | ||
1095 | zappost(p) NODE *p; { | |
1096 | /* look for ++ and -- operators and remove them */ | |
1097 | ||
1098 | register o, ty; | |
1099 | register NODE *q; | |
1100 | o = p->in.op; | |
1101 | ty = optype( o ); | |
1102 | ||
1103 | switch( o ){ | |
1104 | ||
1105 | case INCR: | |
1106 | case DECR: | |
1107 | q = p->in.left; | |
1108 | p->in.right->in.op = FREE; /* zap constant */ | |
1109 | ncopy( p, q ); | |
1110 | q->in.op = FREE; | |
1111 | return; | |
1112 | ||
1113 | } | |
1114 | ||
1115 | if( ty == BITYPE ) zappost( p->in.right ); | |
1116 | if( ty != LTYPE ) zappost( p->in.left ); | |
1117 | } | |
1118 | ||
1119 | fixpre(p) NODE *p; { | |
1120 | ||
1121 | register o, ty; | |
1122 | o = p->in.op; | |
1123 | ty = optype( o ); | |
1124 | ||
1125 | switch( o ){ | |
1126 | ||
1127 | case ASG PLUS: | |
1128 | p->in.op = PLUS; | |
1129 | break; | |
1130 | case ASG MINUS: | |
1131 | p->in.op = MINUS; | |
1132 | break; | |
1133 | } | |
1134 | ||
1135 | if( ty == BITYPE ) fixpre( p->in.right ); | |
1136 | if( ty != LTYPE ) fixpre( p->in.left ); | |
1137 | } | |
1138 | ||
1139 | myreader(p) register NODE *p; { | |
1140 | walkf( p, hardops ); /* convert ops to function calls */ | |
1141 | canon( p ); /* expands r-vals for fileds */ | |
1142 | walkf( p, optim2 ); | |
1143 | /* jwf toff = 0; /* stack offset swindle */ | |
1144 | } | |
1145 | ||
1146 |