1 /* Id: local2.c,v 1.42 2015/01/04 19:17:23 ragge Exp */
2 /* $NetBSD: local2.c,v 1.1.1.7 2016/02/09 20:28:36 plunky Exp $ */
3 /*
4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code and documentation must retain the above
11 * copyright notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditionsand the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed or owned by Caldera
18 * International, Inc.
19 * Neither the name of Caldera International, Inc. nor the names of other
20 * contributors may be used to endorse or promote products derived from
21 * this software without specific prior written permission.
22 *
23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 # include "pass2.h"
38 # include "ctype.h"
39 /* a lot of the machine dependent parts of the second pass */
40
41 static void prtype(NODE *n);
42 static void acon(NODE *p);
43
44 /*
45 * Print out the prolog assembler.
46 * addto and regoff are already calculated.
47 */
48 void
prologue(struct interpass_prolog * ipp)49 prologue(struct interpass_prolog *ipp)
50 {
51 printf(" .word 0x%llx\n", (unsigned long long)ipp->ipp_regs[0]);
52 if (p2maxautooff)
53 printf(" subl2 $%d,%%sp\n", p2maxautooff);
54 if (pflag) {
55 int i = getlab2();
56 printf("\tmovab\t" LABFMT ",%%r0\n", i);
57 printf("\tjsb\t__mcount\n");
58 printf("\t.data\n");
59 printf("\t.align 2\n");
60 printf(LABFMT ":\t.long\t0\n", i);
61 printf("\t.text\n");
62 }
63 }
64
65 /*
66 * Called after all instructions in a function are emitted.
67 * Generates code for epilog here.
68 */
69 void
eoftn(struct interpass_prolog * ipp)70 eoftn(struct interpass_prolog *ipp)
71 {
72 if (ipp->ipp_ip.ip_lbl == 0)
73 return; /* no code needs to be generated */
74 printf(" ret\n");
75 }
76
77 struct hoptab { int opmask; char * opstring; } ioptab[] = {
78
79 { PLUS, "add", },
80 { MINUS, "sub", },
81 { MUL, "mul", },
82 { DIV, "div", },
83 { OR, "bis", },
84 { ER, "xor", },
85 { AND, "bic", },
86 { -1, "" },
87 };
88
89 void
hopcode(f,o)90 hopcode( f, o ){
91 /* output the appropriate string from the above table */
92
93 register struct hoptab *q;
94
95 for( q = ioptab; q->opmask>=0; ++q ){
96 if( q->opmask == o ){
97 printf( "%s", q->opstring );
98 /* tbl
99 if( f == 'F' ) printf( "e" );
100 else if( f == 'D' ) printf( "d" );
101 tbl */
102 /* tbl */
103 switch( f ) {
104 case 'L':
105 case 'W':
106 case 'B':
107 case 'D':
108 case 'F':
109 printf("%c", tolower(f));
110 break;
111
112 }
113 /* tbl */
114 return;
115 }
116 }
117 cerror( "no hoptab for %s", opst[o] );
118 }
119
120 char *
121 rnames[] = { /* keyed to register number tokens */
122
123 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5",
124 "%r6", "%r7", "%r8", "%r9", "%r10", "%r11",
125 "%ap", "%fp", "%sp", "%pc",
126 /* The concatenated regs has the name of the lowest */
127 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5",
128 "%r6", "%r7", "%r8", "%r9", "%r10"
129 };
130
131 int
tlen(NODE * p)132 tlen(NODE *p)
133 {
134 switch(p->n_type) {
135 case CHAR:
136 case UCHAR:
137 return(1);
138
139 case SHORT:
140 case USHORT:
141 return(2);
142
143 case DOUBLE:
144 case LONGLONG:
145 case ULONGLONG:
146 return(8);
147
148 default:
149 return(4);
150 }
151 }
152
153 void
prtype(NODE * n)154 prtype(NODE *n)
155 {
156 static char pt[] = { 0, 0, 'b', 'b', 'w', 'w', 'l', 'l', 0, 0,
157 'q', 'q', 'f', 'd' };
158 TWORD t = n->n_type;
159
160 if (ISPTR(t))
161 t = UNSIGNED;
162
163 if (t > DOUBLE || pt[t] == 0)
164 comperr("prtype: bad type");
165 putchar(pt[t]);
166 }
167
168 /*
169 * Emit conversions as given by the following table. Dest is always reg,
170 * if it should be something else let peephole optimizer deal with it.
171 * This code ensures type correctness in 32-bit registers.
172 * XXX is that necessary?
173 *
174 * From To
175 * char uchar short ushort int uint ll ull float double
176 * char movb movb cvtbw cvtbw cvtbl cvtbl A A cvtbf cvtbd
177 * uchar movb movb movzbw movzbw movzbl movzbl B B G G
178 * short movb movb movw movw cvtwl cvtwl C(A) C(A) cvtwf cvtwd
179 * ushrt movb movb movw movw movzwl movzwl D(B) D(B) H H
180 * int movb movb movw movw movl movl E E cvtlf cvtld
181 * uint movb movb movw movw movl movl F F I I
182 * ll movb movb movw movw movl movl movq movq J K
183 * ull movb movb movw movw movl movl movq movq L M
184 * float cvtfb cvtfb cvtfw cvtfw cvtfl cvtfl N O movf cvtfd
185 * doubl cvtdb cvtdb cvtdw cvtdw cvtdl cvtdl P Q cvtdf movd
186 *
187 * A: cvtbl + sign extend
188 * B: movzbl + zero extend
189 * G: movzbw + cvtwX
190 * H: movzwl + cvtwX
191 * I: cvtld + addX
192 * J: call __floatdisf
193 * K: call __floatdidf
194 * L: xxx + call __floatdisf
195 * M: xxx + call __floatdidf
196 * N: call __fixsfdi
197 * O: call __fixunssfdi
198 * P: call __fixdfdi
199 * Q: call __fixunsdfdi
200 */
201
202 #define MVD 1 /* mov + dest type */
203 #define CVT 2 /* cvt + src type + dst type */
204 #define MVZ 3 /* movz + src type + dst type */
205 #define CSE 4 /* cvt + src type + l + sign extend upper */
206 #define MZE 5 /* movz + src type + l + zero extend upper */
207 #define MLE 6 /* movl + sign extend upper */
208 #define MLZ 7 /* movl + zero extend upper */
209 #define MZC 8 /* movz + cvt */
210
211 static char scary[][10] = {
212 { MVD, MVD, CVT, CVT, CVT, CVT, CSE, CSE, CVT, CVT },
213 { MVD, MVD, MVZ, MVZ, MVZ, MVZ, MZE, MZE, MZC, MZC },
214 { MVD, MVD, MVD, MVD, CVT, CVT, CSE, CSE, CVT, CVT },
215 { MVD, MVD, MVD, MVD, MVZ, MVZ, MZE, MZE, MZC, MZC },
216 { MVD, MVD, MVD, MVD, MVD, MVD, MLE, MLE, CVT, CVT },
217 { MVD, MVD, MVD, MVD, MVD, MVD, MLZ, MLZ, 'I', 'I' },
218 { MVD, MVD, MVD, MVD, MVD, MVD, MVD, MVD, 'J', 'K' },
219 { MVD, MVD, MVD, MVD, MVD, MVD, MVD, MVD, 'L', 'M' },
220 { CVT, CVT, CVT, CVT, CVT, CVT, 'N', 'O', MVD, CVT },
221 { CVT, CVT, CVT, CVT, CVT, CVT, 'P', 'Q', CVT, MVD },
222 };
223
224 static void
sconv(NODE * p)225 sconv(NODE *p)
226 {
227 NODE *l = p->n_left;
228 TWORD ts, td;
229 int o;
230
231 /*
232 * Source node may be in register or memory.
233 * Result is always in register.
234 */
235 ts = l->n_type;
236 if (ISPTR(ts))
237 ts = UNSIGNED;
238 td = p->n_type;
239 ts = ts < LONG ? ts-2 : ts-4;
240 td = td < LONG ? td-2 : td-4;
241
242 o = scary[ts][td];
243 switch (o) {
244 case MLE:
245 case MLZ:
246 expand(p, INAREG|INBREG, "\tmovl\tAL,A1\n");
247 break;
248
249 case MVD:
250 if (l->n_op == REG && regno(l) == regno(getlr(p, '1')))
251 break; /* unneccessary move */
252 expand(p, INAREG|INBREG, "\tmovZR\tAL,A1\n");
253 break;
254
255 case CSE:
256 expand(p, INAREG|INBREG, "\tcvtZLl\tAL,A1\n");
257 break;
258
259 case CVT:
260 expand(p, INAREG|INBREG, "\tcvtZLZR\tAL,A1\n");
261 break;
262
263 case MZE:
264 expand(p, INAREG|INBREG, "\tmovzZLl\tAL,A1\n");
265 break;
266
267 case MVZ:
268 expand(p, INAREG|INBREG, "\tmovzZLZR\tAL,A1\n");
269 break;
270
271 case MZC:
272 expand(p, INAREG|INBREG, "\tmovzZLl\tAL,A1\n");
273 expand(p, INAREG|INBREG, "\tcvtlZR\tA1,A1\n");
274 break;
275
276 case 'I': /* unsigned to double */
277 expand(p, INAREG|INBREG, "\tcvtld\tAL,A1\n");
278 printf("\tjgeq\t1f\n");
279 expand(p, INAREG|INBREG, "\taddd2\t$0d4.294967296e+9,A1\n");
280 printf("1:\n");
281 break;
282 default:
283 comperr("unsupported conversion %d", o);
284 }
285 switch (o) {
286 case MLE:
287 case CSE:
288 expand(p, INBREG, "\tashl\t$-31,A1,U1\n");
289 break;
290 case MLZ:
291 case MZE:
292 expand(p, INAREG|INBREG, "\tclrl\tU1\n");
293 break;
294 }
295 }
296
297 /*
298 * Assign a constant from p to q. Both are expected to be leaves by now.
299 * This is for 64-bit integers.
300 */
301 static void
casg64(NODE * p)302 casg64(NODE *p)
303 {
304 NODE *l, *r;
305 char *str;
306 int mneg = 1;
307
308 l = p->n_left;
309 r = p->n_right;
310
311 #ifdef PCC_DEBUG
312 if (r->n_op != ICON)
313 comperr("casg");
314 #endif
315 if (r->n_name[0] != '\0') {
316 /* named constant, nothing to do */
317 str = "movq\tAR,AL";
318 mneg = 0;
319 } else if (r->n_lval == 0) {
320 str = "clrq\tAL";
321 mneg = 0;
322 } else if (r->n_lval < 0) {
323 if (r->n_lval >= -63) {
324 r->n_lval = -r->n_lval;
325 str = "mnegl\tAR,AL";
326 } else if (r->n_lval >= -128) {
327 str = "cvtbl\tAR,AL";
328 } else if (r->n_lval >= -32768) {
329 str = "cvtwl\tAR,AL";
330 } else if (r->n_lval >= -4294967296LL) {
331 str = "movl\tAR,AL";
332 } else {
333 str = "movq\tAR,AL";
334 mneg = 0;
335 }
336 } else {
337 mneg = 0;
338 if (r->n_lval <= 63 || r->n_lval > 4294967295LL) {
339 str = "movq\tAR,AL";
340 } else if (r->n_lval <= 255) {
341 str = "movzbl\tAR,AL\n\tclrl\tUL";
342 } else if (r->n_lval <= 65535) {
343 str = "movzwl\tAR,AL\n\tclrl\tUL";
344 } else /* if (r->n_lval <= 4294967295) */ {
345 str = "movl\tAR,AL\n\tclrl\tUL";
346 }
347 }
348 expand(p, FOREFF, str);
349 if (mneg)
350 expand(p, FOREFF, "\n\tmnegl $1,UL");
351 }
352
353 /*
354 * Assign a constant from p to q. Both are expected to be leaves by now.
355 * This is only for 32-bit integer types.
356 */
357 static void
casg(NODE * p)358 casg(NODE *p)
359 {
360 NODE *l, *r;
361 char *str;
362
363 l = p->n_left;
364 r = p->n_right;
365
366 #ifdef PCC_DEBUG
367 if (r->n_op != ICON)
368 comperr("casg");
369 #endif
370 if (r->n_name[0] != '\0') {
371 /* named constant, nothing to do */
372 str = "movZL\tAR,AL";
373 } else if (r->n_lval == 0) {
374 str = "clrZL\tAL";
375 } else if (r->n_lval < 0) {
376 if (r->n_lval >= -63) {
377 r->n_lval = -r->n_lval;
378 str = "mnegZL\tAR,AL";
379 } else if (r->n_lval >= -128) {
380 if (l->n_type == CHAR)
381 str = "movb\tAR,AL";
382 else
383 str = "cvtbZL\tAR,AL";
384 } else if (r->n_lval >= -32768) {
385 if (l->n_type == SHORT)
386 str = "movw\tAR,AL";
387 else
388 str = "cvtwZL\tAR,AL";
389 } else
390 str = "movZL\tAR,AL";
391 } else {
392 if (r->n_lval <= 63 || r->n_lval > 65535) {
393 str = "movZL\tAR,AL";
394 } else if (r->n_lval <= 255) {
395 str = l->n_type < SHORT ?
396 "movb\tAR,AL" : "movzbZL\tAR,AL";
397 } else /* if (r->n_lval <= 65535) */ {
398 str = l->n_type < INT ?
399 "movw\tAR,AL" : "movzwZL\tAR,AL";
400 }
401 }
402 expand(p, FOREFF, str);
403 }
404
405 /*
406 * Emit code to compare two longlong numbers.
407 */
408 static void
twollcomp(NODE * p)409 twollcomp(NODE *p)
410 {
411 int u;
412 int s = getlab2();
413 int e = p->n_label;
414 int cb1, cb2;
415
416 u = p->n_op;
417 switch (p->n_op) {
418 case NE:
419 cb1 = 0;
420 cb2 = NE;
421 break;
422 case EQ:
423 cb1 = NE;
424 cb2 = 0;
425 break;
426 case LE:
427 case LT:
428 u += (ULE-LE);
429 /* FALLTHROUGH */
430 case ULE:
431 case ULT:
432 cb1 = GT;
433 cb2 = LT;
434 break;
435 case GE:
436 case GT:
437 u += (ULE-LE);
438 /* FALLTHROUGH */
439 case UGE:
440 case UGT:
441 cb1 = LT;
442 cb2 = GT;
443 break;
444
445 default:
446 cb1 = cb2 = 0; /* XXX gcc */
447 }
448 if (p->n_op >= ULE)
449 cb1 += 4, cb2 += 4;
450 expand(p, 0, " cmpl UL,UR\n");
451 if (cb1) cbgen(cb1, s);
452 if (cb2) cbgen(cb2, e);
453 expand(p, 0, " cmpl AL,AR\n");
454 cbgen(u, e);
455 deflab(s);
456 }
457
458
459 void
zzzcode(NODE * p,int c)460 zzzcode(NODE *p, int c)
461 {
462 NODE *l, *r;
463 TWORD t;
464 int m;
465 char *ch;
466
467 switch (c) {
468 case 'N': /* logical ops, turned into 0-1 */
469 /* use register given by register 1 */
470 cbgen( 0, m=getlab2());
471 deflab( p->n_label );
472 printf( " clrl %s\n", rnames[getlr( p, '1' )->n_rval] );
473 deflab( m );
474 return;
475
476 case 'A': /* Assign a constant directly to a memory position */
477 printf("\t");
478 if (p->n_type < LONG || ISPTR(p->n_type))
479 casg(p);
480 else
481 casg64(p);
482 printf("\n");
483 break;
484
485 case 'B': /* long long compare */
486 twollcomp(p);
487 break;
488
489 case 'C': /* num words pushed on arg stack */
490 printf("$%d", p->n_qual);
491 break;
492
493 case 'D': /* INCR and DECR */
494 zzzcode(p->n_left, 'A');
495 printf("\n ");
496
497 #if 0
498 case 'E': /* INCR and DECR, FOREFF */
499 if (p->n_right->n_lval == 1)
500 {
501 printf("%s", (p->n_op == INCR ? "inc" : "dec") );
502 prtype(p->n_left);
503 printf(" ");
504 adrput(stdout, p->n_left);
505 return;
506 }
507 printf("%s", (p->n_op == INCR ? "add" : "sub") );
508 prtype(p->n_left);
509 printf("2 ");
510 adrput(stdout, p->n_right);
511 printf(",");
512 adrput(p->n_left);
513 return;
514 #endif
515
516 case 'F': /* register type of right operand */
517 {
518 register NODE *n;
519 register int ty;
520
521 n = getlr( p, 'R' );
522 ty = n->n_type;
523
524 if (x2debug) printf("->%d<-", ty);
525
526 if ( ty==DOUBLE) printf("d");
527 else if ( ty==FLOAT ) printf("f");
528 else printf("l");
529 return;
530 }
531
532 case 'G': /* emit conversion instructions */
533 sconv(p);
534 break;
535
536 case 'J': /* jump or ret? */
537 {
538 struct interpass *ip =
539 DLIST_PREV((struct interpass *)p2env.epp, qelem);
540 if (ip->type != IP_DEFLAB ||
541 ip->ip_lbl != getlr(p, 'L')->n_lval)
542 expand(p, FOREFF, "jbr LL");
543 else
544 printf("ret");
545 }
546 break;
547
548 case 'L': /* type of left operand */
549 case 'R': /* type of right operand */
550 {
551 register NODE *n;
552
553 n = getlr ( p, c);
554 if (x2debug) printf("->%d<-", n->n_type);
555
556 prtype(n);
557 return;
558 }
559
560 case 'l': /* print out long long constant as hex */
561 case 'r': /* works around a bug in gas */
562 l = getlr(p, c == 'l' ? 'L' : 'R');
563 if (l->n_op == ICON && ISLONGLONG(l->n_type)) {
564 printf("$0x%llx", l->n_lval);
565 } else
566 adrput(stdout, l);
567 break;
568
569 case 'O': /* print out emulated ops */
570 expand(p, FOREFF, "\tmovq AR,-(%sp)\n");
571 expand(p, FOREFF, "\tmovq AL,-(%sp)\n");
572 if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
573 else if (p->n_op == DIV) ch = "div";
574 else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
575 else if (p->n_op == MOD) ch = "mod";
576 else if (p->n_op == MUL) ch = "mul";
577 else ch = 0, comperr("ZO %d", p->n_op);
578 printf("\tcalls $4,__%sdi3\n", ch);
579 break;
580
581
582 case 'Z': /* complement mask for bit instr */
583 printf("$%lld", ~p->n_right->n_lval);
584 return;
585
586 case 'U': /* 32 - n, for unsigned right shifts */
587 t = DEUNSIGN(p->n_left->n_type);
588 m = t == CHAR ? 8 : t == SHORT ? 16 : 32;
589 printf("$" CONFMT, m - p->n_right->n_lval);
590 return;
591
592 case 'T': /* rounded structure length for arguments */
593 {
594 int size;
595
596 size = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
597 SETOFF( size, 4);
598 printf("$%d", size);
599 return;
600 }
601
602 case 'S': /* structure assignment */
603 {
604 register int size;
605
606 size = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
607 SETOFF(size, 4);
608 l = r = NULL; /* XXX gcc */
609 if( p->n_op == STASG ){
610 l = p->n_left;
611 r = p->n_right;
612
613 }
614 else if( p->n_op == STARG ){
615 /* store an arg into a temporary */
616 printf("\tsubl2 $%d,%%sp\n",
617 size < 4 ? 4 : size);
618 l = mklnode(OREG, 0, SP, INT);
619 r = p->n_left;
620 }
621 else cerror( "STASG bad" );
622
623 if( r->n_op == ICON ) r->n_op = NAME;
624 else if( r->n_op == REG ) r->n_op = OREG;
625 else if( r->n_op != OREG ) cerror( "STASG-r" );
626
627 if (size != 0) {
628 if( size <= 0 || size > 65535 )
629 cerror("structure size <0=0 or >65535");
630
631 switch(size) {
632 case 1:
633 printf(" movb ");
634 break;
635 case 2:
636 printf(" movw ");
637 break;
638 case 4:
639 printf(" movl ");
640 break;
641 case 8:
642 printf(" movq ");
643 break;
644 default:
645 printf(" movc3 $%d,", size);
646 break;
647 }
648 adrput(stdout, r);
649 printf(",");
650 adrput(stdout, l);
651 printf("\n");
652 }
653
654 if( r->n_op == NAME ) r->n_op = ICON;
655 else if( r->n_op == OREG ) r->n_op = REG;
656 if (p->n_op == STARG)
657 tfree(l);
658
659 }
660 break;
661
662 default:
663 comperr("illegal zzzcode '%c'", c);
664 }
665 }
666
667 void
rmove(int rt,int rs,TWORD t)668 rmove(int rt, int rs, TWORD t)
669 {
670 char c = (t == FLOAT ? 'f' : t == DOUBLE ? 'd' :
671 t == LONGLONG || t == ULONGLONG ? 'q' : 'l');
672 printf(" mov%c %s,%s\n", c, rnames[rt], rnames[rs]);
673 }
674
675 int
rewfld(NODE * p)676 rewfld(NODE *p)
677 {
678 return(1);
679 }
680
681 #if 0
682 int
683 callreg(NODE *p)
684 {
685 return( R0 );
686 }
687
688 int
689 base(register NODE *p)
690 {
691 register int o = p->op;
692
693 if( (o==ICON && p->name[0] != '\0')) return( 100 ); /* ie no base reg */
694 if( o==REG ) return( p->rval );
695 if( (o==PLUS || o==MINUS) && p->left->op == REG && p->right->op==ICON)
696 return( p->left->rval );
697 if( o==OREG && !R2TEST(p->rval) && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
698 return( p->rval + 0200*1 );
699 if( o==INCR && p->left->op==REG ) return( p->left->rval + 0200*2 );
700 if( o==ASG MINUS && p->left->op==REG) return( p->left->rval + 0200*4 );
701 if( o==UNARY MUL && p->left->op==INCR && p->left->left->op==REG
702 && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
703 return( p->left->left->rval + 0200*(1+2) );
704 return( -1 );
705 }
706
707 int
708 offset(register NODE *p, int tyl)
709 {
710
711 if( tyl==1 && p->op==REG && (p->type==INT || p->type==UNSIGNED) ) return( p->rval );
712 if( (p->op==LS && p->left->op==REG && (p->left->type==INT || p->left->type==UNSIGNED) &&
713 (p->right->op==ICON && p->right->name[0]=='\0')
714 && (1<<p->right->lval)==tyl))
715 return( p->left->rval );
716 return( -1 );
717 }
718 #endif
719
720 #if 0
721 void
722 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
723 register NODE *t;
724 NODE *f;
725
726 p->n_op = OREG;
727 f = p->n_left; /* have to free this subtree later */
728
729 /* init base */
730 switch (q->n_op) {
731 case ICON:
732 case REG:
733 case OREG:
734 t = q;
735 break;
736
737 case MINUS:
738 q->n_right->n_lval = -q->n_right->n_lval;
739 case PLUS:
740 t = q->n_right;
741 break;
742
743 case UMUL:
744 t = q->n_left->n_left;
745 break;
746
747 default:
748 cerror("illegal makeor2");
749 t = NULL; /* XXX gcc */
750 }
751
752 p->n_lval = t->n_lval;
753 p->n_name = t->n_name;
754
755 /* init offset */
756 p->n_rval = R2PACK( (b & 0177), o, (b>>7) );
757
758 tfree(f);
759 return;
760 }
761
762 int
763 canaddr( p ) NODE *p; {
764 register int o = p->n_op;
765
766 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UMUL && shumul(p->n_left, STARNM|SOREG)) ) return(1);
767 return(0);
768 }
769
770 shltype( o, p ) register NODE *p; {
771 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UMUL && shumul(p->n_left, STARNM|SOREG)) );
772 }
773 #endif
774
775 int
fldexpand(NODE * p,int cookie,char ** cp)776 fldexpand(NODE *p, int cookie, char **cp)
777 {
778 return 0;
779 }
780
781 int
flshape(register NODE * p)782 flshape(register NODE *p)
783 {
784 return( p->n_op == REG || p->n_op == NAME || p->n_op == ICON ||
785 (p->n_op == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)) );
786 }
787
788 int
shtemp(register NODE * p)789 shtemp(register NODE *p)
790 {
791 if( p->n_op == STARG ) p = p->n_left;
792 return( p->n_op==NAME || p->n_op ==ICON || p->n_op == OREG || (p->n_op==UMUL && shumul(p->n_left, STARNM|SOREG)) );
793 }
794
795 /*
796 * Shape matches for UMUL. Cooperates with offstar().
797 */
798 int
shumul(NODE * p,int shape)799 shumul(NODE *p, int shape)
800 {
801
802 if (x2debug)
803 printf("shumul(%p)\n", p);
804
805 /* Turns currently anything into OREG on vax */
806 if (shape & SOREG)
807 return SROREG;
808 return SRNOPE;
809 }
810
811
812 #ifdef notdef
813 int
shumul(p,shape)814 shumul( p, shape ) register NODE *p; int shape; {
815 register int o;
816
817 if (x2debug) {
818 printf("\nshumul:op=%d,lop=%d,rop=%d", p->n_op, p->n_left->n_op, p->n_right->n_op);
819 printf(" prname=%s,plty=%d, prlval=%lld\n", p->n_right->n_name, p->n_left->n_type, p->n_right->n_lval);
820 }
821
822
823 o = p->n_op;
824 if( o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON )
825 if (shape & STARNM)
826 return SRDIR;
827
828 if( ( o == INCR || o == ASG MINUS ) &&
829 ( p->n_left->n_op == REG && p->n_right->n_op == ICON ) &&
830 p->n_right->n_name[0] == '\0' )
831 {
832 switch (p->n_left->n_type)
833 {
834 case CHAR|PTR:
835 case UCHAR|PTR:
836 o = 1;
837 break;
838
839 case SHORT|PTR:
840 case USHORT|PTR:
841 o = 2;
842 break;
843
844 case INT|PTR:
845 case UNSIGNED|PTR:
846 case LONG|PTR:
847 case ULONG|PTR:
848 case FLOAT|PTR:
849 o = 4;
850 break;
851
852 case DOUBLE|PTR:
853 o = 8;
854 break;
855
856 default:
857 if ( ISPTR(p->n_left->n_type) ) {
858 o = 4;
859 break;
860 }
861 else return(0);
862 }
863 return( p->n_right->n_lval == o ? STARREG : 0);
864 }
865
866 return( SRNOPE );
867 }
868 #endif
869
870 void
adrcon(CONSZ val)871 adrcon(CONSZ val)
872 {
873 comperr("adrcon");
874 printf( "$" );
875 printf( CONFMT, val );
876 }
877
878 void
conput(FILE * fp,NODE * p)879 conput(FILE *fp, NODE *p)
880 {
881 switch( p->n_op ){
882
883 case ICON:
884 acon( p );
885 return;
886
887 case REG:
888 printf( "%s", rnames[p->n_rval] );
889 return;
890
891 default:
892 cerror( "illegal conput" );
893 }
894 }
895
896 void
insput(register NODE * p)897 insput(register NODE *p)
898 {
899 cerror( "insput" );
900 }
901
902 /*
903 * Write out the upper address, like the upper register of a 2-register
904 * reference, or the next memory location.
905 */
906 void
upput(NODE * p,int size)907 upput(NODE *p, int size)
908 {
909
910 size /= SZCHAR;
911 switch (p->n_op) {
912 case REG:
913 printf("%s", rnames[regno(p)-16+1]);
914 break;
915
916 case NAME:
917 if (kflag)
918 comperr("upput NAME");
919 case OREG:
920 p->n_lval += size;
921 adrput(stdout, p);
922 p->n_lval -= size;
923 break;
924 case ICON:
925 printf("$" CONFMT, (p->n_lval >> 32) & 0xffffffff);
926 break;
927 default:
928 comperr("upput bad op %d size %d", p->n_op, size);
929 }
930 }
931
932 void
adrput(FILE * fp,NODE * p)933 adrput(FILE *fp, NODE *p)
934 {
935 register int r;
936 /* output an address, with offsets, from p */
937
938 if( p->n_op == FLD ){
939 p = p->n_left;
940 }
941 switch( p->n_op ){
942
943 case NAME:
944 acon( p );
945 return;
946
947 case ICON:
948 /* addressable value of the constant */
949 if (p->n_name[0] == '\0') /* uses xxxab */
950 printf("$");
951 if (ISLONGLONG(p->n_type))
952 printf("0x%llx", p->n_lval);
953 else
954 acon(p);
955 return;
956
957 case REG:
958 printf( "%s", rnames[p->n_rval] );
959 return;
960
961 case OREG:
962 r = p->n_rval;
963 if( R2TEST(r) ){ /* double indexing */
964 register int flags;
965
966 flags = R2UPK3(r);
967 if( flags & 1 ) printf("*");
968 if( flags & 4 ) printf("-");
969 if( p->n_lval != 0 || p->n_name[0] != '\0' ) acon(p);
970 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
971 if( flags & 2 ) printf("+");
972 printf( "[%s]", rnames[R2UPK2(r)] );
973 return;
974 }
975 if( r == AP ){ /* in the argument region */
976 if( p->n_lval <= 0 || p->n_name[0] != '\0' )
977 werror( "bad arg temp" );
978 printf( CONFMT, p->n_lval );
979 printf( "(%%ap)" );
980 return;
981 }
982 if( p->n_lval != 0 || p->n_name[0] != '\0') acon( p );
983 printf( "(%s)", rnames[p->n_rval] );
984 return;
985
986 case UMUL:
987 /* STARNM or STARREG found */
988 if( tshape(p, STARNM) ) {
989 printf( "*" );
990 adrput(0, p->n_left);
991 }
992 else { /* STARREG - really auto inc or dec */
993 register NODE *q;
994
995 /* tbl
996 p = p->n_left;
997 p->n_left->n_op = OREG;
998 if( p->n_op == INCR ) {
999 adrput( p->n_left );
1000 printf( "+" );
1001 }
1002 else {
1003 printf( "-" );
1004 adrput( p->n_left );
1005 }
1006 tbl */
1007 #ifdef notyet
1008 printf("%c(%s)%c", (p->n_left->n_op==INCR ? '\0' : '-'),
1009 rnames[p->n_left->n_left->n_rval],
1010 (p->n_left->n_op==INCR ? '+' : '\0') );
1011 #else
1012 printf("%c(%s)%c", '-',
1013 rnames[p->n_left->n_left->n_rval],
1014 '\0' );
1015 #endif
1016 p->n_op = OREG;
1017 p->n_rval = p->n_left->n_left->n_rval;
1018 q = p->n_left;
1019 #ifdef notyet
1020
1021 p->n_lval = (p->n_left->n_op == INCR ? -p->n_left->n_right->n_lval : 0);
1022 #else
1023 p->n_lval = 0;
1024 #endif
1025 p->n_name[0] = '\0';
1026 tfree(q);
1027 }
1028 return;
1029
1030 default:
1031 cerror( "illegal address" );
1032 return;
1033 }
1034
1035 }
1036
1037 /*
1038 * print out a constant
1039 */
1040 void
acon(NODE * p)1041 acon(NODE *p)
1042 {
1043 int u = (int)p->n_lval;;
1044 CONSZ v = u;
1045
1046 if (p->n_name[0] == '\0') {
1047 printf(CONFMT, v);
1048 } else if( p->n_lval == 0 ) {
1049 printf("%s", p->n_name);
1050 } else {
1051 printf("%s+", p->n_name);
1052 printf(CONFMT, v);
1053 }
1054 }
1055
1056 #if 0
1057 genscall( p, cookie ) register NODE *p; {
1058 /* structure valued call */
1059 return( gencall( p, cookie ) );
1060 }
1061
1062 /* tbl */
1063 int gc_numbytes;
1064 /* tbl */
1065
1066 gencall( p, cookie ) register NODE *p; {
1067 /* generate the call given by p */
1068 register NODE *p1, *ptemp;
1069 register temp, temp1;
1070 register m;
1071
1072 if( p->right ) temp = argsize( p->right );
1073 else temp = 0;
1074
1075 if( p->op == STCALL || p->op == UNARY STCALL ){
1076 /* set aside room for structure return */
1077
1078 if( p->stsize > temp ) temp1 = p->stsize;
1079 else temp1 = temp;
1080 }
1081
1082 if( temp > maxargs ) maxargs = temp;
1083 SETOFF(temp1,4);
1084
1085 if( p->right ){ /* make temp node, put offset in, and generate args */
1086 ptemp = talloc();
1087 ptemp->op = OREG;
1088 ptemp->lval = -1;
1089 ptemp->rval = SP;
1090 ptemp->name[0] = '\0';
1091 ptemp->rall = NOPREF;
1092 ptemp->su = 0;
1093 genargs( p->right, ptemp );
1094 nfree(ptemp);
1095 }
1096
1097 p1 = p->left;
1098 if( p1->op != ICON ){
1099 if( p1->op != REG ){
1100 if( p1->op != OREG || R2TEST(p1->rval) ){
1101 if( p1->op != NAME ){
1102 order( p1, INAREG );
1103 }
1104 }
1105 }
1106 }
1107
1108 /*
1109 if( p1->op == REG && p->rval == R5 ){
1110 cerror( "call register overwrite" );
1111 }
1112 */
1113 /* tbl
1114 setup gc_numbytes so reference to ZC works */
1115
1116 gc_numbytes = temp;
1117 /* tbl */
1118
1119 p->op = UNARY CALL;
1120 m = match( p, INTAREG|INTBREG );
1121 /* tbl
1122 switch( temp ) {
1123 case 0:
1124 break;
1125 case 2:
1126 printf( " tst (%sp)+\n" );
1127 break;
1128 case 4:
1129 printf( " cmp (%sp)+,(%sp)+\n" );
1130 break;
1131 default:
1132 printf( " add $%d,%sp\n", temp);
1133 }
1134 tbl */
1135 return(m != MDONE);
1136 }
1137 #endif
1138
1139 static char *
1140 ccbranches[] = {
1141 "jeql",
1142 "jneq",
1143 "jleq",
1144 "jlss",
1145 "jgeq",
1146 "jgtr",
1147 "jlequ",
1148 "jlssu",
1149 "jgequ",
1150 "jgtru",
1151 };
1152
1153 /*
1154 * printf conditional and unconditional branches
1155 */
1156 void
cbgen(int o,int lab)1157 cbgen(int o, int lab)
1158 {
1159
1160 if (o == 0) {
1161 printf(" jbr " LABFMT "\n", lab);
1162 } else {
1163 if (o > UGT)
1164 comperr("bad conditional branch: %s", opst[o]);
1165 printf("\t%s\t" LABFMT "\n", ccbranches[o-EQ], lab);
1166 }
1167 }
1168
1169 static void
mkcall(NODE * p,char * name)1170 mkcall(NODE *p, char *name)
1171 {
1172 p->n_op = CALL;
1173 p->n_right = mkunode(FUNARG, p->n_left, 0, p->n_left->n_type);
1174 p->n_left = mklnode(ICON, 0, 0, FTN|p->n_type);
1175 p->n_left->n_name = name;
1176 }
1177
1178 /* do local tree transformations and optimizations */
1179 static void
optim2(NODE * p,void * arg)1180 optim2(NODE *p, void *arg)
1181 {
1182 NODE *r, *s;
1183 TWORD lt;
1184
1185 switch (p->n_op) {
1186 case DIV:
1187 case MOD:
1188 if (p->n_type == USHORT || p->n_type == UCHAR) {
1189 r = mkunode(SCONV, p->n_left, 0, UNSIGNED);
1190 r = mkunode(FUNARG, r, 0, UNSIGNED);
1191 s = mkunode(SCONV, p->n_right, 0, UNSIGNED);
1192 s = mkunode(FUNARG, s, 0, UNSIGNED);
1193 r = mkbinode(CM, r, s, INT);
1194 s = mklnode(ICON, 0, 0, FTN|UNSIGNED);
1195 s->n_name = p->n_op == MOD ? "__urem" : "__udiv";
1196 p->n_left = mkbinode(CALL, s, r, UNSIGNED);
1197 p->n_op = SCONV;
1198 } else if (p->n_type == UNSIGNED) {
1199 p->n_left = mkunode(FUNARG, p->n_left, 0, UNSIGNED);
1200 p->n_right = mkunode(FUNARG, p->n_right, 0, UNSIGNED);
1201 p->n_right = mkbinode(CM, p->n_left, p->n_right, INT);
1202 p->n_left = mklnode(ICON, 0, 0, FTN|UNSIGNED);
1203 p->n_left->n_name = p->n_op == MOD ? "__urem" : "__udiv";
1204 p->n_op = CALL;
1205 }
1206 break;
1207
1208 case RS:
1209 if (p->n_type == ULONGLONG) {
1210 p->n_right = mkbinode(CM,
1211 mkunode(FUNARG, p->n_left, 0, p->n_left->n_type),
1212 mkunode(FUNARG, p->n_right, 0, p->n_right->n_type),
1213 INT);
1214 p->n_left = mklnode(ICON, 0, 0, FTN|p->n_type);
1215 p->n_left->n_name = "__lshrdi3";
1216 p->n_op = CALL;
1217 } else if (p->n_type == INT || p->n_type == LONGLONG) {
1218 /* convert >> to << with negative shift count */
1219 /* RS of char & short must use extv */
1220 if (p->n_right->n_op == ICON) {
1221 p->n_right->n_lval = -p->n_right->n_lval;
1222 } else if (p->n_right->n_op == UMINUS) {
1223 r = p->n_right->n_left;
1224 nfree(p->n_right);
1225 p->n_right = r;
1226 } else {
1227 p->n_right = mkunode(UMINUS, p->n_right,
1228 0, p->n_right->n_type);
1229 }
1230 p->n_op = LS;
1231 }
1232 break;
1233
1234 case AND:
1235 /* commute L and R to eliminate compliments and constants */
1236 if ((p->n_left->n_op == ICON && p->n_left->n_name[0] == 0) ||
1237 p->n_left->n_op==COMPL) {
1238 r = p->n_left;
1239 p->n_left = p->n_right;
1240 p->n_right = r;
1241 }
1242 /* change meaning of AND to ~R&L - bic on pdp11 */
1243 r = p->n_right;
1244 if (r->n_op == ICON && r->n_name[0] == 0) {
1245 /* compliment constant */
1246 r->n_lval = ~r->n_lval;
1247 } else if (r->n_op == COMPL) { /* ~~A => A */
1248 s = r->n_left;
1249 nfree(r);
1250 p->n_right = s;
1251 } else { /* insert complement node */
1252 p->n_right = mkunode(COMPL, r, 0, r->n_type);
1253 }
1254 break;
1255 case SCONV:
1256 lt = p->n_left->n_type;
1257 switch (p->n_type) {
1258 case LONGLONG:
1259 if (lt == FLOAT)
1260 mkcall(p, "__fixsfdi");
1261 else if (lt == DOUBLE)
1262 mkcall(p, "__fixdfdi");
1263 break;
1264 case ULONGLONG:
1265 if (lt == FLOAT)
1266 mkcall(p, "__fixunssfdi");
1267 else if (lt == DOUBLE)
1268 mkcall(p, "__fixunsdfdi");
1269 break;
1270 case FLOAT:
1271 if (lt == LONGLONG)
1272 mkcall(p, "__floatdisf");
1273 else if (lt == ULONGLONG) {
1274 p->n_left = mkunode(SCONV, p->n_left,0, DOUBLE);
1275 p->n_type = FLOAT;
1276 mkcall(p->n_left, "__floatundidf");
1277 } else if (lt == UNSIGNED) {
1278 /* insert an extra double-to-float sconv */
1279 p->n_left = mkunode(SCONV, p->n_left,0, DOUBLE);
1280 }
1281 break;
1282 case DOUBLE:
1283 if (lt == LONGLONG)
1284 mkcall(p, "__floatdidf");
1285 else if (lt == ULONGLONG)
1286 mkcall(p, "__floatundidf");
1287 break;
1288
1289 }
1290 break;
1291 }
1292 }
1293
1294 static void
aofname(NODE * p,void * arg)1295 aofname(NODE *p, void *arg)
1296 {
1297 int o = optype(p->n_op);
1298 TWORD t;
1299
1300 if (o == LTYPE || p->n_op == ADDROF)
1301 return;
1302 t = p->n_left->n_type;
1303 if (p->n_left->n_op == NAME && ISLONGLONG(t))
1304 p->n_left = mkunode(UMUL,
1305 mkunode(ADDROF, p->n_left, 0, INCREF(t)), 0, t);
1306 if (o == BITYPE && p->n_right->n_op == NAME &&
1307 ISLONGLONG(p->n_right->n_type)) {
1308 t = p->n_right->n_type;
1309 p->n_right = mkunode(UMUL,
1310 mkunode(ADDROF, p->n_right, 0, INCREF(t)), 0, t);
1311 }
1312 }
1313
1314 void
myreader(struct interpass * ipole)1315 myreader(struct interpass *ipole)
1316 {
1317 struct interpass *ip;
1318
1319 DLIST_FOREACH(ip, ipole, qelem) {
1320 if (ip->type != IP_NODE)
1321 continue;
1322 if (kflag)
1323 walkf(ip->ip_node, aofname, 0);
1324 walkf(ip->ip_node, optim2, 0);
1325 }
1326 }
1327
1328 void
mycanon(NODE * p)1329 mycanon(NODE *p)
1330 {
1331 }
1332
1333 void
myoptim(struct interpass * ip)1334 myoptim(struct interpass *ip)
1335 {
1336 }
1337
1338 /*
1339 * Return argument size in regs.
1340 */
1341 static int
argsiz(NODE * p)1342 argsiz(NODE *p)
1343 {
1344 TWORD t = p->n_type;
1345
1346 if (t == STRTY || t == UNIONTY)
1347 return (attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0)+3)/4;
1348 return szty(t);
1349 }
1350
1351 /*
1352 * Last chance to do something before calling a function.
1353 */
1354 void
lastcall(NODE * p)1355 lastcall(NODE *p)
1356 {
1357 NODE *op = p;
1358 int size = 0;
1359
1360 /* Calculate argument sizes */
1361 p->n_qual = 0;
1362 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1363 return;
1364 for (p = p->n_right; p->n_op == CM; p = p->n_left)
1365 size += argsiz(p->n_right);
1366 if (p->n_op != ASSIGN)
1367 size += argsiz(p);
1368 op->n_qual = size; /* XXX */
1369 }
1370
1371 /*
1372 * Return a class suitable for a specific type.
1373 */
1374 int
gclass(TWORD t)1375 gclass(TWORD t)
1376 {
1377 return (szty(t) == 2 ? CLASSB : CLASSA);
1378 }
1379
1380 /*
1381 * For class c, find worst-case displacement of the number of
1382 * registers in the array r[] indexed by class.
1383 */
1384 int
COLORMAP(int c,int * r)1385 COLORMAP(int c, int *r)
1386 {
1387 int num;
1388 int a,b;
1389
1390 a = r[CLASSA];
1391 b = r[CLASSB];
1392 switch (c) {
1393 case CLASSA:
1394 /* there are 12 classa, so min 6 classb are needed to block */
1395 num = b * 2;
1396 num += a;
1397 return num < 12;
1398 case CLASSB:
1399 if (b > 3) return 0;
1400 if (b > 2 && a) return 0;
1401 if (b > 1 && a > 2) return 0;
1402 if (b && a > 3) return 0;
1403 if (a > 5) return 0;
1404 return 1;
1405 }
1406 comperr("COLORMAP");
1407 return 0; /* XXX gcc */
1408 }
1409
1410 /*
1411 * Special shapes.
1412 */
1413 int
special(NODE * p,int shape)1414 special(NODE *p, int shape)
1415 {
1416 return SRNOPE;
1417 }
1418
1419 /*
1420 * Target-dependent command-line options.
1421 */
1422 void
mflags(char * str)1423 mflags(char *str)
1424 {
1425 }
1426 /*
1427 * Do something target-dependent for xasm arguments.
1428 * Supposed to find target-specific constraints and rewrite them.
1429 */
1430 int
myxasm(struct interpass * ip,NODE * p)1431 myxasm(struct interpass *ip, NODE *p)
1432 {
1433 char *c;
1434 int i;
1435
1436 /* Discard o<> constraints since they will not be generated */
1437 for (c = p->n_name; *c; c++) {
1438 if (*c == 'o' || *c == '<' || *c == '>') {
1439 for (i = 0; c[i]; i++)
1440 c[i] = c[i+1];
1441 c--;
1442 }
1443 }
1444 return 0;
1445 }
1446
1447 int
xasmconstregs(char * s)1448 xasmconstregs(char *s)
1449 {
1450 int i;
1451
1452 for (i = 0; i < 16; i++)
1453 if (strcmp(&rnames[i][1], s) == 0)
1454 return i;
1455 return -1;
1456 }
1457