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