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