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