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