|
|
1.1 root 1: #include "cpass2.h"
2: #include "ctype.h"
3: #ifndef lint
4: static char sccsid[] = "@(#)local2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
5: #endif
6:
7: /*
8: * Copyright (c) 1985 by Sun Microsystems, Inc.
9: */
10:
11: # ifdef FORT
12: int ftlab1, ftlab2;
13: # endif
14: /* a lot of the machine dependent parts of the second pass */
15: #ifdef FORT
16: # define fltfun 0
17: #else
18: extern int fltfun;
19: #endif
20: # define BITMASK(n) ((1L<<(n))-1)
21:
22:
23: int toff = 0; /* number of stack locations used for args */
24: int maxtoff;
25: void stmove();
26: void eval_field();
27: void shiftreg();
28: void incraddr();
29:
30: /* everything you never wanted to know about condition codes */
31:
32: char *
33: ccodes[] = { "eq", "ne", "le", "lt", "ge", "gt", "ls", "cs", "cc", "hi" };
34:
35: char *
36: fccodes[] = { "eq", "neq", "le", "lt", "ge", "gt" };
37:
38: char *
39: fnegccodes[] = { "neq", "eq", "nle", "nlt", "nge", "ngt" };
40:
41: /* logical relations when compared in reverse order (cmp R,L) */
42:
43: #ifdef FORT
44: short revrel[] = { EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
45: #else
46: extern short revrel[];
47: #endif
48:
49: /* negated logical relations -- integer comparisons only */
50:
51: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;
52:
53: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
54:
55: zzzcode( p, c, cookie ) NODE *p;
56: {
57:
58: register m,temp;
59: NODE *s;
60:
61: switch( c ){
62: /* BCDEFGHIJKLMNOPRSTVWXabcdfglmrtv` '0-~ */
63:
64: case 'C':
65: switch (p->in.left->in.op) {
66:
67: case ICON: print_str("\tjbsr\t");
68: acon(p->in.left);
69: return;
70:
71: case REG:
72: if (indexreg(p->in.left)){
73: /* already in an address register */
74: print_str("\tjsr\t");
75: adrput(p->in.left);
76: putchar('@');
77: return;
78: } /* else fall through */
79:
80: case NAME:
81: case OREG: print_str("\tmovl\t");
82: adrput(p->in.left);
83: print_str(",a0\n\tjsr\ta0@");
84: return;
85:
86: default: cerror("bad subroutine name");
87: }
88:
89: case 'E': /* load doubles with overly complex addressing */
90: {
91: /*
92: * accomplished by simplifying addressing, then
93: * falling through to case 'D'.
94: */
95: expand(p, cookie, " lea AR,A2\n");
96: /*
97: * we would like, at this point, just to paint over
98: * p with the place where we have the address calculated
99: * and be done with it. too bad we can't: reclaim
100: * needs to look at it. So we must RECUR here
101: */
102: resc[1].tn.op = OREG;
103: resc[1].tn.lval = 0;
104: resc[1].tn.type = INCREF(DOUBLE);
105: zzzcode( &resc[1], 'D', cookie );
106: return;
107: }
108:
109:
110: case 'D': /* load-store doubles with auto-incr/decr addressing */
111: {
112: /* cases are: ASSIGN, or rewrite LEAF-node */
113: # define FORW 0
114: # define REVR 1
115: static char * lrewrite[] = { "\tmovl\tA.,A1\n\tmovl\tU.,U1\n",
116: "\tmovl\tU.,U1\n\tmovl\tA.,A1\n"};
117: static char * asreg[] = { "\tmovl\tAR,AL\n\tmovl\tUR,UL\n",
118: "\tmovl\tUR,UL\n\tmovl\tAR,AL\n"};
119: char **rstring;
120: NODE * q;
121: if (p->in.op == ASSIGN){
122: rstring = asreg; q = p->in.left;
123: } else {
124: rstring = lrewrite; q = p;
125: }
126: if (q->in.op == UNARY MUL && q->in.left->in.op == ASG MINUS)
127: expand( p, cookie, rstring[REVR] );
128: else
129: expand( p, cookie, rstring[FORW] );
130: # undef FORW
131: # undef REVR
132: }
133: return;
134:
135: case 'K':
136: /*
137: * 68881 floating point source operand
138: * This is essentially the same as AR, but
139: * in addition we check for the opportunity
140: * to use floating-point immediate mode.
141: * Only supported by the assembler in
142: * coprocessor instructions.
143: */
144: switch(optype(p->in.op)) {
145: case LTYPE:
146: break;
147: case UTYPE:
148: if (p->in.op != UNARY MUL)
149: p = p->in.left;
150: break;
151: case BITYPE:
152: p = p->in.right;
153: break;
154: }
155: if (p->in.op == FCON) {
156: floatimmed(p);
157: } else {
158: adrput(p);
159: }
160: return;
161:
162: case 'L':
163: m = p->in.left->in.type;
164: goto suffix;
165:
166: case 'R':
167: m = p->in.right->in.type;
168: goto suffix;
169:
170: case 'B':
171: m = p->in.type; /* fall into suffix: */
172:
173: suffix:
174: switch(m) {
175: case CHAR:
176: case UCHAR:
177: c = 'b';
178: break;
179: case SHORT:
180: case USHORT:
181: c = 'w';
182: break;
183: default:
184: c = 'l';
185: break;
186: }
187: putchar(c);
188: return;
189:
190: case 'F':
191: /*
192: * print type characters for the source operand of
193: * a 68881 floating point instruction.
194: */
195: switch(optype(p->in.op)) {
196: case LTYPE:
197: break;
198: case UTYPE:
199: if (p->in.op != UNARY MUL)
200: p = p->in.left;
201: break;
202: case BITYPE:
203: p = p->in.right;
204: break;
205: }
206: /*
207: * at this point, p is assumed to have matched
208: * the shape SFLOAT_SRCE (cf. special())
209: */
210: if (p->in.op == SCONV)
211: p = p->in.left;
212: goto float_suffix;
213:
214: case 'G':
215: /*
216: * print type character for the left subtree
217: */
218: p = p->in.left;
219: if (p->in.op == SCONV)
220: p = p->in.left;
221: goto float_suffix;
222:
223: case '.':
224: float_suffix:
225: if (p->in.op == REG && iscreg(p->tn.rval)) {
226: /*
227: * source is coprocessor reg; data
228: * is in extended precision
229: */
230: putchar('x');
231: return;
232: }
233: /*
234: * print type character for the root node
235: */
236: switch(BTYPE(p->in.type)) {
237: case CHAR:
238: c = 'b';
239: break;
240: case SHORT:
241: c = 'w';
242: break;
243: case FLOAT:
244: c = 's';
245: break;
246: case DOUBLE:
247: c = 'd';
248: break;
249: case UCHAR:
250: case USHORT:
251: /*
252: * the 68881 sign-extends integer operands
253: */
254: cerror("compiler botched unsigned operand");
255: /*NOTREACHED*/
256: default:
257: c = 'l';
258: break;
259: }
260: putchar(c);
261: return;
262:
263: case 'N': /* logical ops, turned into 0-1 */
264: /* use register given by RESC1 */
265: branch(m=getlab());
266: /* FALL THROUGH */
267:
268: make_boolean:
269: deflab( p->bn.label );
270: temp = getlr( p, '1' )->tn.rval;
271: printf( " clrl %s\n", rnames[temp]);
272: markused(temp);
273: deflab( m );
274: return;
275:
276: case 'H':
277: cbgen(p->in.op, p->in.left->in.type, p->bn.label,
278: p->bn.reversed, FCCODES);
279: return;
280:
281: case 'I':
282: cbgen(p->in.op, p->in.left->in.type, p->bn.label,
283: p->bn.reversed, CCODES);
284: return;
285:
286: /* stack management macros */
287: case '-':
288: print_str( "sp@-" );
289: case 'P':
290: toff += 4;
291: if (toff > maxtoff) maxtoff = toff;
292: return;
293:
294: case '0':
295: toff = 0; return;
296:
297: case '~':
298: /* complimented CR */
299: p->in.right->tn.lval = ~p->in.right->tn.lval;
300: conput( getlr( p, 'R' ) );
301: p->in.right->tn.lval = ~p->in.right->tn.lval;
302: return;
303:
304: case 'M':
305: /* negated CR */
306: p->in.right->tn.lval = -p->in.right->tn.lval;
307: case 'O':
308: conput( getlr( p, 'R' ) );
309: p->in.right->tn.lval = -p->in.right->tn.lval;
310: return;
311:
312: case 'T':
313: /* Truncate longs for type conversions:
314: INT|UNSIGNED -> CHAR|UCHAR|SHORT|USHORT
315: increment offset to second word */
316:
317: m = p->in.type;
318: p = p->in.left;
319: switch( p->in.op ){
320: case NAME:
321: case OREG:
322: if (p->in.type==SHORT || p->in.type==USHORT)
323: p->tn.lval += (m==CHAR || m==UCHAR) ? 1 : 0;
324: else p->tn.lval += (m==CHAR || m==UCHAR) ? 3 : 2;
325: return;
326: case REG:
327: return;
328: default:
329: cerror( "Illegal ZT type conversion" );
330: return;
331:
332: }
333:
334: case 't':
335: /*
336: * Lengthen little (unsigned) things. Try to be smart
337: * about instruction sequences.
338: */
339: s = p->in.left;
340: m = s->in.type;
341: if (ISUNSIGNED(m)){
342: /* zero-extending into temp register */
343: if ( istnode(s) && s->tn.rval == resc[0].tn.rval ){
344: /* must use andl instructions */
345: print_str_str( " andl #0x", (m==UCHAR)?"ff":"ffff");
346: } else {
347: print_str_str_nl( " moveq #0,", rnames[ resc[0].tn.rval ] );
348: printf( " mov%c ", (m==UCHAR)?'b':'w');
349: adrput( s );
350: }
351: putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] );
352: } else {
353: /* sign-extending into temp register */
354: if (!(istnode(s) && s->tn.rval == resc[0].tn.rval) ){
355: /* not already in its register */
356: printf( " mov%c ", (m==CHAR)?'b':'w');
357: adrput( s );
358: putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] );
359: }
360: /* sign-extend */
361: if (m == CHAR)
362: print_str_str_nl( " extw ", rnames[resc[0].tn.rval]);
363: if (p->in.type != SHORT && p->in.type != USHORT)
364: print_str_str_nl( " extl ", rnames[resc[0].tn.rval]);
365: }
366: return;
367:
368: case 'W': /* structure size */
369: if( p->in.op == STASG )
370: print_d(p->stn.stsize);
371: else cerror( "Not a structure" );
372: return;
373:
374: case 'S': /* structure assignment */
375: stmove( p, cookie );
376: return;
377:
378: case 'X':{ /* indexed effective address */
379: NODE fake,*lp,*rp;
380: int flags;
381: lp = p->in.left;
382: rp = p->in.right;
383: R2PACKFLGS(flags, rp->in.type == SHORT, 0, 0);
384: fake.in.op = OREG;
385: fake.tn.rval = R2PACK(lp->in.left->tn.rval, rp->tn.rval, flags);
386: fake.tn.name = "\0";
387: fake.tn.lval = lp->in.right->tn.lval;
388: oregput(&fake);
389: return;
390: }
391:
392: case 'a':
393: /* assign something to a bit field */
394: case 'b':
395: /* extract a bit field */
396: case 'c':
397: /* compare bit field with constant for CC only */
398: eval_field( p, c, cookie);
399: return;
400:
401: case 'f': /* floating-point operation */
402: /* since the floating-point format may be changed with a
403: * compile-time switch, we need to go think about this
404: */
405: floatcode( p, cookie );
406: fltused++;
407: return;
408: case 'g': /* floating-point conversion to normal register */
409: /* anything that looks like a floating type conversion
410: * or a floating-register load or store comes here.
411: */
412: floatconv( p, c, cookie );
413: fltused++;
414: return;
415:
416: case 'm': /* multiplication by a constant */
417: conmul( p, cookie );
418: return;
419:
420: case 'd': /* division by a constant */
421: condiv( p, cookie );
422: return;
423:
424: case 'r': /* remainder by a constant */
425: conrem( p, cookie );
426: return;
427:
428: case ' ': /* leaf-type for effect only */
429: /*
430: * usually this will generate NO code.
431: * the exception is INCR or ASG MINUS, as in
432: * *p++, *--p;
433: * these are recognized as side effects of addressing
434: * modes, so have not been dealt with by higher functions.
435: */
436: if (p->in.op == UNARY MUL){
437: if (p->in.left->in.op == INCR){
438: printf(" addql #%d, %s\n",
439: tlen(p), rnames[p->in.left->in.left->tn.rval]);
440: } else if (p->in.left->in.op == ASG MINUS){
441: printf(" subql #%d, %s\n",
442: tlen(p), rnames[p->in.left->in.left->tn.rval]);
443: }
444: }
445: return;
446:
447: case 'l': /* lea or addl instruction, as appropriate */
448: if (p->in.left->tn.rval == resc[0].tn.rval){
449: /* really a += */
450: expand( p, cookie, " addZR AR,A1\n");
451: } else {
452: /* really is a 3-address lea */
453: expand( p, cookie, " lea AL@(0,AR:ZR),A1\n");
454: }
455: return;
456:
457: case 'v': /* generate trapv for signed arithmetic */
458: trapv(p->in.type);
459: return;
460:
461: case 'V': /* generate bound-testing code */
462: bound_test(p, cookie);
463: return;
464:
465: default:
466: cerror( "illegal zzzcode" );
467: }
468: }
469:
470: #define checkout if (resc[opno].tn.op != REG) cerror("struct-assign botch")
471:
472: NODE *
473: cpytmp( l, opno ) NODE *l;
474: {
475: NODE *new;
476: print_str( (l->in.op == REG)||(ISPTR(l->in.type))? " movl " : " lea ");
477: adrput( l );
478: checkout;
479: new = &resc[opno];
480: new->tn.type = ISPTR(l->in.type)?l->in.type:INCREF(l->in.type);
481: markused(new->tn.rval);
482: putchar(','); print_str_nl(rnames[new->tn.rval] );
483: return new;
484: }
485:
486:
487: void
488: stmove( p , cookie ) register NODE *p;
489: {
490: register NODE *l, *r;
491: register size, i;
492: extern NODE resc[];
493: int opno = 1;
494: int rcopy;
495: int xsize;
496: int labl;
497: int loopcode;
498: register char *cnt, *lhs, *rhs;
499:
500: char **moves;
501: # define MOVBSTRNG 0
502: # define MOVWSTRNG 1
503: # define MOVLSTRNG 2
504: static char * asgstrings[] = {
505: " movb AR,AL\n",
506: " movw AR,AL\n",
507: " movl AR,AL\n",
508: };
509: static char * argstrings[] = {
510: " movb AR,sp@-\n",
511: " movw AR,sp@-\n",
512: " movl AR,sp@-\n",
513: };
514:
515: if( p->in.op == STASG ){
516: l = p->in.left;
517: r = p->in.right;
518: moves = asgstrings;
519: } else if( p->in.op == STARG ){ /* store an arg onto the stack */
520: /*
521: * "r" and "l" are obviously misnomers here.
522: * they should be "from" and, perhaps, "to".
523: */
524: r = p->in.left;
525: checkout;
526: l = &resc[opno++];
527: markused(l->tn.rval);
528: moves = argstrings;
529: } else
530: cerror( "STASG bad" );
531:
532: if ( r->in.op == ICON )
533: r->in.op = NAME;
534: /*
535: * avoid complicated memory operands
536: */
537: if (l->in.op == OREG && R2TEST(l->tn.rval)) {
538: l = cpytmp( l, opno++ );
539: }
540: if (r->in.op == OREG && R2TEST(r->tn.rval)) {
541: r = cpytmp( r, opno++ );
542: }
543: size = p->stn.stsize;
544: xsize = size + (size&1); /* must be even */
545:
546: /*
547: * now we make a totally arbitrary decision about
548: * when to loop, and when to emit straight-line code.
549: */
550:
551: if (size <= 8){
552: /* straight-line */
553: NODE xxx;
554:
555: /* the MIT strategy -- gross, no? */
556: if( l->in.op != REG && ISPTR(l->in.type))
557: l = cpytmp( l, opno++ );
558: if( r->in.op != REG && ISPTR(r->in.type))
559: r = cpytmp( r, opno++ );
560: xxx.in.op = STASG;
561: xxx.in.left = l;
562: xxx.in.right = r;
563: if( r->tn.op == REG ){
564: r->tn.op = OREG;
565: r->tn.type = DECREF(r->tn.type);
566: }
567: if( l->in.op == REG ) l->in.op = OREG;
568: r->tn.lval += size;
569: l->tn.lval += size;
570:
571: switch (size&03){
572: /* do special cases */
573: case 1:
574: case 3:
575: r->tn.lval -= 1;
576: l->tn.lval -= 1;
577: expand( &xxx, cookie, moves[MOVBSTRNG] );
578: if ((size&03) == 1) break;
579: /* case 3 falls through */
580: case 2:
581: r->tn.lval -= 2;
582: l->tn.lval -= 2;
583: expand( &xxx, cookie, moves[MOVWSTRNG] );
584: }
585: size -= size&03;
586: /* assert( size%4 == 0 ) */
587: while( size ){ /* simple load/store loop */
588: r->tn.lval -= 4;
589: l->tn.lval -= 4;
590: size -= 4;
591: expand( &xxx, cookie, moves[MOVLSTRNG] );
592: }
593: } else {
594: /* loop code */
595: loopcode = size >= 20;
596: if (loopcode) {
597: cnt = rnames[resc[0].tn.rval];
598: printf(" mov%c #%d,%s\n", (size<(1<<16))?'w':'l',
599: size/4-1, cnt);
600: }
601: if ( !istnode(l)){
602: if (l->tn.op==OREG && !R2TEST(l->tn.rval)
603: && istreg(l->tn.rval) && l->tn.lval==0)
604: l->tn.op=REG;
605: else
606: l = cpytmp( l, opno++ );
607: }
608: if ( !istnode(r) ){
609: r = cpytmp( r, opno++ );
610: rcopy = 1; /* this is not our real rhs */
611: } else
612: rcopy = 0;
613: lhs = rnames[l->tn.rval];
614: rhs = rnames[r->tn.rval];
615: if (p->in.op==STARG){
616: /*
617: * structure argument:
618: * push space on stack (lea sp@(size),sp)
619: * copy sp to a temp register we can bomb
620: * go for it.
621: */
622: if (xsize <(1<<16))
623: printf( " lea sp@(-%d),sp\n", xsize);
624: else
625: printf( " subl #%d,sp\n", xsize);
626: printf(" movl sp,%s\n", lhs);
627: }
628: if (loopcode) {
629: print_label(labl= getlab());
630: /* now emit the 2-instruction loop */
631: printf(" movl %s@+,%s@+\n", rhs, lhs);
632: printf(" dbra %s,L%d\n", cnt, labl);
633: if (size>=(1<<16)){
634: /* "long dbra" */
635: printf(" clrw %s\n", cnt);
636: printf(" subql #1,%s\n", cnt);
637: printf(" jcc L%d\n", labl);
638: }
639: } else {
640: /* use autoincrement mode in an unrolled loop */
641: int n;
642: for (n = 0; n < size/4; n++)
643: printf(" movl %s@+,%s@+\n", rhs, lhs);
644: }
645: switch (size&03) {
646: /* oops -- stuff leftover */
647: case 3:
648: printf(" movw %s@+,%s@+\n", rhs, lhs);
649: /* fall thorugh */
650: case 1:
651: printf(" movb %s@,%s@\n", rhs, lhs);
652: break;
653: case 2:
654: printf(" movw %s@,%s@\n", rhs, lhs);
655: break;
656: }
657: if (cookie&(INBREG|INTBREG) && !rcopy){
658: /* oh damn, must repair damage */
659: int temp;
660: temp = p->stn.stsize;
661: p->stn.stsize &= ~0x3;
662: if (size <(1<<16))
663: expand( p, FOREFF, " lea AR@(-ZW),AR\n");
664: else
665: expand( p, FOREFF, " subl #ZW,AR\n");
666: p->stn.stsize = temp;
667: }
668: }
669: if (p->in.op==STARG){
670: /* keep toff up-to-date */
671: if (xsize<3){
672: /* must pad */
673: printf(" subqw #2,sp\n");
674: xsize = 4;
675: }
676: toff += xsize;
677: if (toff>maxtoff) maxtoff= toff;
678: } else {
679: r = p->in.right;
680: if ( r->in.op == NAME )
681: r->in.op = ICON;
682: else if (!(cookie&SANY) && r->tn.op==OREG && !ISPTR(r->tn.type)){
683: /* we get to make up a (choke) address here */
684: if (r->tn.lval == 0){
685: r->in.op = REG;
686: r->tn.type = INCREF(r->tn.type);
687: } else
688: cerror("trapped in a multiple-structue-assigment");
689: }
690: }
691: }
692:
693: #undef checkout
694:
695: /*
696: * alignfield(p, byteoff)
697: * Align an operand for a 68020 bit field operation. If byteoff
698: * is nonzero, subtract it (it was previously added to the offset
699: * part of p->in.left, possibly resulting in an odd offset). Then
700: * longword-align the offset, assuming that names and activation
701: * records are longword-aligned.
702: */
703: static
704: alignfield(p, byteoff)
705: register NODE *p; /* assumed to be FLD op */
706: int byteoff;
707: {
708: register NODE *lp; /* assumed to be operand address */
709: int fieldoff, fieldsize, residue;
710:
711: lp = p->in.left;
712: switch( lp->in.op ){
713: case NAME:
714: case ICON:
715: case OREG:
716: if (byteoff) {
717: /* undo it */
718: lp->tn.lval -= byteoff;
719: }
720: residue = lp->tn.lval % (SZLONG/SZCHAR);
721: if (residue < 0) {
722: /*
723: * careful about AUTOs --
724: * the offsets are negative
725: */
726: residue += (SZLONG/SZCHAR);
727: }
728: fieldoff = UPKFOFF(p->tn.rval) + residue*SZCHAR;
729: fieldsize = UPKFSZ(p->tn.rval);
730: if (fieldoff + fieldsize <= SZLONG) {
731: /*
732: * take bytes away from the operand address,
733: * and put bits back in the field offset.
734: */
735: lp->tn.lval -= residue;
736: p->tn.rval = PKFIELD(fieldsize, fieldoff);
737: }
738: break;
739: default:
740: cerror( "illegal address in alignfield" );
741: break;
742: }
743: }
744:
745: expandfield(p)
746: register NODE *p;
747: {
748: printf( "{#%d:#%d}", UPKFOFF(p->tn.rval), UPKFSZ(p->tn.rval) );
749: }
750:
751: void
752: eval_field( p, c, cookie )
753: NODE *p;
754: char c;
755: {
756: register temp, m;
757: register NODE *l, *r;
758: int lobyte, hibyte;
759: char *regname;
760: NODE *fieldnode;
761: int conval;
762:
763: l = p->in.left;
764: r = p->in.right;
765: fieldnode = (c == 'b') ? p : p->in.left;
766: lobyte = (SZINT - fldshf - 1)/SZCHAR; /* byte containing low-order bit */
767: hibyte = (SZINT -fldshf -fldsz)/SZCHAR;/* byte containing high-order bit */
768: if (fieldnode->in.left->tn.op == REG){
769: if ( ISPTR(fieldnode->in.left->tn.type)){
770: fieldnode->in.left->tn.op = OREG;
771: } else {
772: /* always use longword accesses to registers */
773: hibyte = 0;
774: temp = SZINT;
775: p->in.type = UNSIGNED;
776: goto longonly;
777: }
778: }
779:
780: if (lobyte==hibyte){
781: /* ok to do byte accesses to memory */
782: temp = SZCHAR;
783: p->in.type = UCHAR;
784: } else if ((hibyte&1) || (hibyte < (lobyte-1))){
785: /* must do longword access */
786: hibyte = 0;
787: temp = SZINT;
788: p->in.type = UNSIGNED;
789: } else {
790: /* word access */
791: temp = SZSHORT;
792: p->in.type = USHORT;
793: }
794:
795: /* adjust shift value, paint over left type and address */
796: fldshf = temp - (SZINT-fldshf -(hibyte*SZCHAR));
797: if (hibyte){
798: incraddr( fieldnode, hibyte);
799: }
800:
801: longonly:
802:
803: switch (c){
804: case 'a':
805: /* assignment of a value to a bit field */
806: /* the two cases are: constant r-h-s, and variable r-h-s */
807: /* the constant case has several interesting sub-cases */
808: if (r->tn.op == ICON){
809: /* easy case */
810: conval = r->tn.lval;
811: m = r->tn.lval;
812: if (fldsz == 1) {
813: /* very easy case */
814: print_str_d( (m&1)?" bset #":" bclr #", fldshf); putchar(',');
815: adrput( l );
816: } else {
817: /*
818: * wide field:
819: * depending on field size and alignment, we may
820: * have to do word or longword accesses
821: */
822: if (m==0){
823: /* clearing entire field */
824: if (fldshf==0 && fldsz == temp){
825: /* no masking involved -- whole unit */
826: expand( p, cookie, " clrZB AL");
827: } else {
828: expand( p, cookie, " andZB #N,AL");
829: }
830: } else if ( m==-1 || m==BITMASK(fldsz)){
831: /* setting entire field */
832: if (fldshf==0 && fldsz == temp){
833: /* no masking involved -- whole unit */
834: if (fldsz == SZCHAR) {
835: expand( p, cookie, " st AL");
836: } else {
837: expand( p, cookie, " movZB #CR,AL");
838: }
839: } else {
840: expand( p, cookie, " orZB #M,AL" );
841: }
842: } else {
843: /* -- inserting value -- */
844: if (fldshf==0 && fldsz == temp){
845: /* no masking involved -- whole unit */
846: expand( p, cookie, " movZB #CR,AL");
847: } else {
848: m &= BITMASK(fldsz);
849: r->tn.lval = m<<fldshf;
850: expand(p, cookie, " andZB #N,AL\n orZB #CR,AL");
851: }
852: }
853: }
854: /* restore old ICON value in case we want to use it as
855: the result of the assignment */
856: r->tn.lval = conval;
857: } else {
858: /* non-constant */
859: /* there are only two cases here :
860: shifting and masking, or
861: not shifting or masking
862: */
863: if (fldsz == temp && fldshf == 0){
864: /* direct move */
865: expand( p, cookie, " movZB AR,AL");
866: } else if (use68020) {
867: /* the normal, ugly case, with 68020 instructions */
868: alignfield(fieldnode, hibyte);
869: expand( p, cookie, " bfins AR,AL");
870: expandfield(fieldnode);
871: } else {
872: /* the normal, ugly case, with 68010 instructions */
873: /* clear field in destination */
874: expand( p, cookie, " andZB #N,AL\n");
875: /* move value to temp and adjust */
876: temp = fldshf;
877: fldshf = 0;
878: if (r->tn.op == REG && istreg(r->tn.rval) && (cookie&FOREFF)){
879: /* do it in place */
880: regname = rnames[r->tn.rval];
881: /* mask source to the right number of bits, and */
882: expand( p, cookie, " andZB #M,AR\n");
883: /* shift into place */
884: shiftreg( temp, regname , -1, 0, 'l', UNSIGNED);
885: /* combine source into destination */
886: expand( p, cookie, " orZB AR,AL");
887: } else {
888: /* must copy over */
889: rmove( resc[0].tn.rval, r->tn.rval, UNSIGNED );
890: expand( p, cookie, " andZB #M,A1\n");
891: regname = rnames[ resc[0].tn.rval ];
892: shiftreg( temp, regname , -1, 0, 'l', UNSIGNED);
893: expand( p, cookie, " orZB A1,AL");
894: }
895: }
896: }
897: p->in.type = UNSIGNED;
898: return;
899:
900: case 'b':
901: /* extracting field value -- either for CC or for value */
902: if (cookie & FORCC){
903: compare_with_zero:
904: /* only extracting value to compare it with zero */
905: if (fldsz == 1){
906: /* snap case -- so long as fields are unsigned! */
907: print_str_d( " btst #", fldshf); putchar(',');
908: adrput( l );
909: } else if (fldsz == temp && fldshf == 0){
910: /* direct memory test */
911: expand( p, cookie, " tstZB AL");
912: } else {
913: /*
914: * move value into a register -- and with mask to set CC.
915: * We would have to worry about setting the N condition
916: * here, but our unsigned-ness prevents this from being
917: * a problem.
918: */
919: if (l->tn.op == REG && istreg(l->tn.rval)){
920: expand( p, cookie, " andl #M,AL");
921: } else {
922: expand( p, cookie,
923: " movZB AL,A1\n andZB #M,A1");
924: }
925: }
926: } else {
927: /* extracting value for value's sake */
928: if (l->tn.op == REG && istreg(l->tn.rval)){
929: regname = rnames[ l->tn.rval ];
930: if (use68020 && fldshf != 0) {
931: alignfield(fieldnode, hibyte);
932: expand( p, cookie, " bfextu AL");
933: expandfield(fieldnode);
934: putchar(','); print_str(regname);
935: } else {
936: shiftreg( -fldshf, regname , resc[0].tn.rval, 0, 'l', UNSIGNED);
937: fldshf = 0;
938: expand( p, cookie, " andl #M,AL");
939: }
940: } else {
941: regname = rnames[ resc[0].tn.rval ];
942: if (use68020 && fldshf != 0) {
943: alignfield(fieldnode, hibyte);
944: expand( p, cookie, " bfextu AL");
945: expandfield(fieldnode);
946: putchar(','); print_str(regname);
947: } else {
948: if (temp != SZINT){
949: print_str_str_nl(" moveq #0,", regname );
950: }
951: expand( p, cookie, " movZB AL,A1");
952: if (fldsz != temp || fldshf != 0){
953: putchar('\n');
954: shiftreg( -fldshf, regname, -1, 0, 'l', UNSIGNED);
955: fldshf = 0;
956: expand( p, cookie, " andZB #M,A1");
957: }
958: }
959: }
960: }
961:
962: fieldnode->in.type = UNSIGNED;
963: return;
964:
965: case 'c':
966: /* comparison of field value with constant value for CC only */
967: m = r->tn.lval;
968: if (m==0) goto compare_with_zero;
969: r->tn.lval = m << fldshf;
970: if (temp == fldsz && fldshf == 0 ){
971: /* compare directly to memory */
972: expand(p, cookie, " cmpZB #CR,AL");
973: } else if (l->tn.op == REG && istreg(l->tn.rval) && cookie&FOREFF){
974: /* munge in place */
975: expand( p, cookie," andZB #M,AL\n cmpZB #CR,AL");
976: } else {
977: /* move to register, mask, compare */
978: expand( p, cookie,
979: " movZB AL,A1\n andZB #M,A1\n cmpZB #CR,A1");
980: }
981: }
982:
983: }
984:
985: /* routine used by the field-evaluation code to emit shifting instructions.
986: "val" is the amount to shift, s is the name of the register to shift,
987: and "reg" is the register NUMBER of a helper, if one is available.
988: If val<0, we're doing right shifts
989: If needclr != 0, must clear lower word after swap.
990: */
991: void
992: shiftreg( val, s , reg, needclr, typechar, type )
993: char *s;
994: char typechar;
995: {
996: char *t;
997: char *shift = "lsll";
998: int lshift;
999: if (val < 0 ){
1000: shift = "lsrl";
1001: val = -val;
1002: lshift = 0;
1003: } else{
1004: lshift = 1;
1005: shift[0] = (ISUNSIGNED(type) || ISPTR(type))? 'l' : 'a';
1006: }
1007: shift[3] = typechar; /* ugly hack */
1008: if (val > 16 ){
1009: if (reg >= 0){
1010: printf(" movl #%d,%s\n", val, t=rnames[ reg ]);
1011: printf(" %s %s,%s\n", shift, t, s);
1012: trapv(type);
1013: return;
1014: }
1015: if (!(chk_ovfl && shift[0] == 'a')){
1016: print_str_str_nl(" swap ", s);
1017: if (needclr&&lshift)
1018: print_str_str_nl(" clrw ", s);
1019: val -= 16;
1020: }
1021: }
1022: while (val > 0){
1023: if (val> 8){
1024: printf(" %s #8,%s\n", shift, s);
1025: val -= 8;
1026: } else {
1027: if (val==1 && lshift)
1028: printf(" add%c %s,%s\n", typechar, s,s);
1029: else
1030: printf(" %s #%d,%s\n", shift, val, s);
1031: val = 0;
1032: }
1033: trapv(type);
1034: }
1035: }
1036:
1037: void
1038: incraddr( p , v)
1039: register NODE *p;
1040: long v;
1041: {
1042: /* bump the address p by the value b. */
1043: if( p->in.op == FLD ){
1044: p = p->in.left;
1045: }
1046: switch( p->in.op ){
1047: case NAME:
1048: case ICON:
1049: case OREG:
1050: p->tn.lval += v;
1051: break;
1052: default:
1053: cerror( "illegal incraddr address" );
1054: break;
1055:
1056: }
1057: }
1058:
1059: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1060:
1061: insput( p ) register NODE *p;
1062: {
1063: #ifndef IEEECCODES
1064: printf(ccodes[p->in.op-EQ]);
1065: #else IEEECCODES
1066: if (ISFLOATING(p->in.left->in.type)) {
1067: printf(fccodes[p->in.op-EQ]);
1068: } else {
1069: printf(ccodes[p->in.op-EQ]);
1070: }
1071: #endif IEEECCODES
1072: }
1073:
1074: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1075:
1076: /*
1077: * Generate conditional branches from a relational operator.
1078: * The exact form of the branch depends on:
1079: * 1. whether or not the compared operands have floating point types
1080: * 2. whether or not the coprocessor condition code is used
1081: * 3. whether the operator has been negated.
1082: */
1083:
1084: cbgen( o, type, label, reversed, mode )
1085: int o; /* relational op {EQ, NE, LT, LE, ...} */
1086: TWORD type; /* operand type - determines opcode */
1087: int label; /* destination label */
1088: int reversed; /* =1 if op is to be negated */
1089: int mode; /* if FCCODES, use coprocessor condition codes */
1090: {
1091: char *prefix;
1092: char *opname;
1093:
1094: #ifndef IEEECCODES
1095: if (reversed) {
1096: /* treat !(a < b) as (a >= b) */
1097: o = negrel[o-EQ];
1098: }
1099: if (mode == FCCODES) {
1100: prefix = "fj";
1101: opname = fccodes[o-EQ];
1102: } else {
1103: prefix = "j";
1104: opname = ccodes[o-EQ];
1105: }
1106: #else IEEECCODES
1107: if (ISFLOATING(type)) {
1108: prefix = (mode == FCCODES ? "fj" : "jf");
1109: opname = (reversed ? fnegccodes[o-EQ] : fccodes[o-EQ]);
1110: } else {
1111: prefix = "j";
1112: if (reversed)
1113: o = negrel[o-EQ];
1114: opname = ccodes[o-EQ];
1115: }
1116: #endif IEEECCODES
1117: printf(" %s%s L%d\n", prefix, opname, label);
1118: }
1119:
1120: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1121:
1122: #ifdef FORT
1123: branch(lab)
1124: int lab;
1125: {
1126: printf(" jra L%d\n", lab);
1127: }
1128: #endif FORT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.