* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / pdp10 / local2.c
blob3383c5dd2396004c38b68d0621eeb78255d7df9b
1 /* $Id: local2.c,v 1.102 2008/11/22 16:12:25 ragge Exp $ */
2 /*
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 # include "pass2.h"
31 # include <ctype.h>
33 # define putstr(s) fputs((s), stdout)
35 void acon(FILE *, NODE *p);
36 int argsize(NODE *p);
37 void genargs(NODE *p);
39 static int offlab;
40 int offarg;
41 static int addto;
42 static int regoff[16];
44 void
45 deflab(int label)
47 printf(LABFMT ":\n", label);
50 void
51 prologue(struct interpass_prolog *ipp)
53 int i, j;
55 if (ipp->ipp_vis)
56 printf(" .globl %s\n", ipp->ipp_name);
57 printf("%s:\n", ipp->ipp_name);
58 addto = p2maxautooff;
59 if (addto >= AUTOINIT/SZCHAR)
60 addto -= AUTOINIT/SZCHAR;
61 addto /= SZINT/SZCHAR; /* use words here */
62 printf(" push %s,%s\n",rnames[STKREG], rnames[FPREG]);
63 printf(" move %s,%s\n", rnames[FPREG],rnames[STKREG]);
65 for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
66 if (i & 1)
67 regoff[j] = addto++;
69 if (addto)
70 printf(" addi %s,0%o\n", rnames[STKREG], addto);
72 for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
73 if (i & 1)
74 printf(" movem %s,%d(%s)\n",
75 rnames[j], regoff[j], rnames[STKREG]);
79 void
80 eoftn(struct interpass_prolog *ipp)
82 int i, j;
84 if (ipp->ipp_ip.ip_lbl == 0)
85 return; /* no code needs to be generated */
86 for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
87 if (i & 1)
88 printf(" move %s,%d(%s)\n",
89 rnames[j], regoff[j], rnames[STKREG]);
91 printf(" move %s,%s\n", rnames[STKREG], rnames[FPREG]);
92 printf(" pop %s,%s\n", rnames[STKREG], rnames[FPREG]);
93 printf(" popj %s,\n", rnames[STKREG]);
96 #if 0
97 void
98 prologue(int regs, int autos)
100 int i, addto;
102 offlab = getlab2();
103 if (regs < 0 || autos < 0) {
105 * non-optimized code, jump to epilogue for code generation.
107 ftlab1 = getlab2();
108 ftlab2 = getlab2();
109 printf(" jrst L%d\n", ftlab1);
110 printf("L%d:\n", ftlab2);
111 } else {
113 * We here know what register to save and how much to
114 * add to the stack.
116 autos = autos + (SZINT-1);
117 addto = (autos - AUTOINIT)/SZINT + (MAXRVAR-regs);
118 if (addto || gflag) {
119 printf(" push %s,%s\n",rnames[017], rnames[016]);
120 printf(" move %s,%s\n", rnames[016],rnames[017]);
121 for (i = regs; i < MAXRVAR; i++) {
122 int db = ((i+1) < MAXRVAR);
123 printf(" %smovem %s,0%o(%s)\n",
124 db ? "d" : "",
125 rnames[i+1], i+1-regs, rnames[016]);
126 if (db)
127 i++;
129 if (addto)
130 printf(" addi %s,0%o\n", rnames[017], addto);
131 } else
132 offarg = 1;
137 * End of block.
139 void
140 eoftn(int regs, int autos, int retlab)
142 register OFFSZ spoff; /* offset from stack pointer */
143 int i;
145 spoff = autos + (SZINT-1);
146 if (spoff >= AUTOINIT)
147 spoff -= AUTOINIT;
148 spoff /= SZINT;
149 /* return from function code */
150 printf("L%d:\n", retlab);
151 if (gflag || isoptim == 0 || autos != AUTOINIT || regs != MAXRVAR) {
152 for (i = regs; i < MAXRVAR; i++) {
153 int db = ((i+1) < MAXRVAR);
154 printf(" %smove %s,0%o(%s)\n", db ? "d" : "",
155 rnames[i+1], i+1-regs, rnames[016]);
156 if (db)
157 i++;
159 printf(" move %s,%s\n", rnames[017], rnames[016]);
160 printf(" pop %s,%s\n", rnames[017], rnames[016]);
162 printf(" popj %s,\n", rnames[017]);
164 /* Prolog code */
165 if (isoptim == 0) {
166 printf("L%d:\n", ftlab1);
167 printf(" push %s,%s\n", rnames[017], rnames[016]);
168 printf(" move %s,%s\n", rnames[016], rnames[017]);
169 for (i = regs; i < MAXRVAR; i++) {
170 int db = ((i+1) < MAXRVAR);
171 printf(" %smovem %s,0%o(%s)\n", db ? "d" : "",
172 rnames[i+1], i+1-regs, rnames[016]);
173 spoff++;
174 if (db)
175 i++, spoff++;
177 if (spoff)
178 printf(" addi %s,0%llo\n", rnames[017], spoff);
179 printf(" jrst L%d\n", ftlab2);
181 printf(" .set " LABFMT ",0%o\n", offlab, MAXRVAR-regs);
182 offarg = isoptim = 0;
184 #endif
187 * add/sub/...
189 * Param given:
190 * R - Register
191 * M - Memory
192 * C - Constant
194 void
195 hopcode(int f, int o)
197 cerror("hopcode: f %d %d", f, o);
200 char *
201 rnames[] = { /* keyed to register number tokens */
202 "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
203 "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
204 "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
205 "%10", "%11", "%12", "%13", "%14", "%15",
209 tlen(p) NODE *p;
211 switch(p->n_type) {
212 case CHAR:
213 case UCHAR:
214 return(1);
216 case SHORT:
217 case USHORT:
218 return(SZSHORT/SZCHAR);
220 case DOUBLE:
221 return(SZDOUBLE/SZCHAR);
223 case INT:
224 case UNSIGNED:
225 case LONG:
226 case ULONG:
227 return(SZINT/SZCHAR);
229 case LONGLONG:
230 case ULONGLONG:
231 return SZLONGLONG/SZCHAR;
233 default:
234 if (!ISPTR(p->n_type))
235 cerror("tlen type %d not pointer");
236 return SZPOINT(0)/SZCHAR;
240 static char *
241 binskip[] = {
242 "e", /* jumpe */
243 "n", /* jumpn */
244 "le", /* jumple */
245 "l", /* jumpl */
246 "ge", /* jumpge */
247 "g", /* jumpg */
251 * Extract the higher 36 bits from a longlong.
253 static CONSZ
254 gethval(CONSZ lval)
256 CONSZ hval = (lval >> 35) & 03777777777LL;
258 if ((hval & 03000000000LL) == 03000000000LL) {
259 hval |= 0777000000000LL;
260 } else if ((hval & 03000000000LL) == 02000000000LL) {
261 hval &= 01777777777LL;
262 hval |= 0400000000000LL;
264 return hval;
268 * Do a binary comparision, and jump accordingly.
270 static void
271 twocomp(NODE *p)
273 int o = p->n_op;
274 extern int negrel[];
275 int isscon = 0, iscon = p->n_right->n_op == ICON;
277 if (o < EQ || o > GT)
278 cerror("bad binary conditional branch: %s", opst[o]);
280 if (iscon && p->n_right->n_name[0] != 0) {
281 printf(" cam%s ", binskip[negrel[o-EQ]-EQ]);
282 adrput(stdout, getlr(p, 'L'));
283 putchar(',');
284 printf("[ .long ");
285 adrput(stdout, getlr(p, 'R'));
286 putchar(']');
287 printf("\n jrst L%d\n", p->n_label);
288 return;
290 if (iscon)
291 isscon = p->n_right->n_lval >= 0 &&
292 p->n_right->n_lval < 01000000;
294 printf(" ca%c%s ", iscon && isscon ? 'i' : 'm',
295 binskip[negrel[o-EQ]-EQ]);
296 adrput(stdout, getlr(p, 'L'));
297 putchar(',');
298 if (iscon && (isscon == 0)) {
299 printf("[ .long ");
300 adrput(stdout, getlr(p, 'R'));
301 putchar(']');
302 } else
303 adrput(stdout, getlr(p, 'R'));
304 printf("\n jrst L%d\n", p->n_label);
308 * Compare byte/word pointers.
309 * XXX - do not work for highest bit set in address
311 static void
312 ptrcomp(NODE *p)
314 printf(" rot "); adrput(stdout, getlr(p, 'L')); printf(",6\n");
315 printf(" rot "); adrput(stdout, getlr(p, 'R')); printf(",6\n");
316 twocomp(p);
320 * Do a binary comparision of two long long, and jump accordingly.
321 * XXX - can optimize for constants.
323 static void
324 twollcomp(NODE *p)
326 int o = p->n_op;
327 int iscon = p->n_right->n_op == ICON;
328 int m = 0; /* XXX gcc */
330 if (o < EQ || o > GT)
331 cerror("bad long long conditional branch: %s", opst[o]);
333 /* Special strategy for equal/not equal */
334 if (o == EQ || o == NE) {
335 if (o == EQ)
336 m = getlab2();
337 printf(" came ");
338 upput(getlr(p, 'L'), SZLONG);
339 putchar(',');
340 if (iscon)
341 printf("[ .long ");
342 upput(getlr(p, 'R'), SZLONG);
343 if (iscon)
344 putchar(']');
345 printf("\n jrst L%d\n", o == EQ ? m : p->n_label);
346 printf(" cam%c ", o == EQ ? 'n' : 'e');
347 adrput(stdout, getlr(p, 'L'));
348 putchar(',');
349 if (iscon)
350 printf("[ .long ");
351 adrput(stdout, getlr(p, 'R'));
352 if (iscon)
353 putchar(']');
354 printf("\n jrst L%d\n", p->n_label);
355 if (o == EQ)
356 printf("L%d:\n", m);
357 return;
359 /* First test highword */
360 printf(" cam%ce ", o == GT || o == GE ? 'l' : 'g');
361 adrput(stdout, getlr(p, 'L'));
362 putchar(',');
363 if (iscon)
364 printf("[ .long ");
365 adrput(stdout, getlr(p, 'R'));
366 if (iscon)
367 putchar(']');
368 printf("\n jrst L%d\n", p->n_label);
370 /* Test equality */
371 printf(" came ");
372 adrput(stdout, getlr(p, 'L'));
373 putchar(',');
374 if (iscon)
375 printf("[ .long ");
376 adrput(stdout, getlr(p, 'R'));
377 if (iscon)
378 putchar(']');
379 printf("\n jrst L%d\n", m = getlab2());
381 /* Test lowword. Only works with pdp10 format for longlongs */
382 printf(" cam%c%c ", o == GT || o == GE ? 'l' : 'g',
383 o == LT || o == GT ? 'e' : ' ');
384 upput(getlr(p, 'L'), SZLONG);
385 putchar(',');
386 if (iscon)
387 printf("[ .long ");
388 upput(getlr(p, 'R'), SZLONG);
389 if (iscon)
390 putchar(']');
391 printf("\n jrst L%d\n", p->n_label);
392 printf("L%d:\n", m);
396 * Print the correct instruction for constants.
398 static void
399 constput(NODE *p)
401 CONSZ val = p->n_right->n_lval;
402 int reg = p->n_left->n_rval;
404 /* Only numeric constant */
405 if (p->n_right->n_name[0] == '\0') {
406 if (val == 0) {
407 printf("movei %s,0", rnames[reg]);
408 } else if ((val & 0777777000000LL) == 0) {
409 printf("movei %s,0%llo", rnames[reg], val);
410 } else if ((val & 0777777) == 0) {
411 printf("hrlzi %s,0%llo", rnames[reg], val >> 18);
412 } else {
413 printf("move %s,[ .long 0%llo]", rnames[reg],
414 szty(p->n_right->n_type) > 1 ? val :
415 val & 0777777777777LL);
417 /* Can have more tests here, hrloi etc */
418 return;
419 } else {
420 printf("xmovei %s,%s", rnames[reg], p->n_right->n_name);
421 if (val)
422 printf("+" CONFMT, val);
427 * Return true if the constant can be bundled in an instruction (immediate).
429 static int
430 oneinstr(NODE *p)
432 if (p->n_name[0] != '\0')
433 return 0;
434 if ((p->n_lval & 0777777000000ULL) != 0)
435 return 0;
436 return 1;
440 * Emit a halfword or byte instruction, from OREG to REG.
441 * Sign extension must also be done here.
443 static void
444 emitshort(NODE *p)
446 CONSZ off = p->n_lval;
447 TWORD type = p->n_type;
448 int reg = p->n_rval;
449 int issigned = !ISUNSIGNED(type);
450 int ischar = type == CHAR || type == UCHAR;
451 int reg1 = getlr(p, '1')->n_rval;
453 if (off < 0) { /* argument, use move instead */
454 printf(" move ");
455 } else if (off == 0 && p->n_name[0] == 0) {
456 printf(" ldb %s,%s\n", rnames[reg1], rnames[reg]);
457 /* XXX must sign extend here even if not necessary */
458 switch (type) {
459 case CHAR:
460 printf(" lsh %s,033\n", rnames[reg1]);
461 printf(" ash %s,-033\n", rnames[reg1]);
462 break;
463 case SHORT:
464 printf(" hrre %s,%s\n",
465 rnames[reg1], rnames[reg1]);
466 break;
468 return;
469 } else if (ischar) {
470 if (off >= 0700000000000LL && p->n_name[0] != '\0') {
471 cerror("emitsh");
472 /* reg contains index integer */
473 // if (!istreg(reg))
474 // cerror("emitshort !istreg");
475 printf(" adjbp %s,[ .long 0%llo+%s ]\n",
476 rnames[reg], off, p->n_name);
477 printf(" ldb ");
478 adrput(stdout, getlr(p, '1'));
479 printf(",%s\n", rnames[reg]);
480 goto signe;
482 printf(" ldb ");
483 adrput(stdout, getlr(p, '1'));
484 if (off)
485 printf(",[ .long 0%02o11%02o%06o ]\n",
486 (int)(27-(9*(off&3))), reg, (int)off/4);
487 else
488 printf(",%s\n", rnames[reg]);
489 signe: if (issigned) {
490 printf(" lsh ");
491 adrput(stdout, getlr(p, '1'));
492 printf(",033\n ash ");
493 adrput(stdout, getlr(p, '1'));
494 printf(",-033\n");
496 return;
497 } else {
498 printf(" h%cr%c ", off & 1 ? 'r' : 'l',
499 issigned ? 'e' : 'z');
501 p->n_lval /= (ischar ? 4 : 2);
502 adrput(stdout, getlr(p, '1'));
503 putchar(',');
504 adrput(stdout, getlr(p, 'L'));
505 putchar('\n');
509 * Store a short from a register. Destination is a OREG.
511 static void
512 storeshort(NODE *p)
514 NODE *l = p->n_left;
515 CONSZ off = l->n_lval;
516 int reg = l->n_rval;
517 int ischar = BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR;
519 if (l->n_op == NAME) {
520 if (ischar) {
521 printf(" dpb ");
522 adrput(stdout, getlr(p, 'R'));
523 printf(",[ .long 0%02o%010o+%s ]\n",
524 070+((int)off&3), (int)(off/4), l->n_name);
525 return;
527 printf(" hr%cm ", off & 1 ? 'r' : 'l');
528 l->n_lval /= 2;
529 adrput(stdout, getlr(p, 'R'));
530 putchar(',');
531 adrput(stdout, getlr(p, 'L'));
532 putchar('\n');
533 return;
536 if (off || reg == FPREG) { /* Can emit halfword instructions */
537 if (off < 0) { /* argument, use move instead */
538 printf(" movem ");
539 } else if (ischar) {
540 printf(" dpb ");
541 adrput(stdout, getlr(p, '1'));
542 printf(",[ .long 0%02o11%02o%06o ]\n",
543 (int)(27-(9*(off&3))), reg, (int)off/4);
544 return;
545 } else {
546 printf(" hr%cm ", off & 1 ? 'r' : 'l');
548 l->n_lval /= 2;
549 adrput(stdout, getlr(p, 'R'));
550 putchar(',');
551 adrput(stdout, getlr(p, 'L'));
552 } else {
553 printf(" dpb ");
554 adrput(stdout, getlr(p, 'R'));
555 putchar(',');
556 l = getlr(p, 'L');
557 l->n_op = REG;
558 adrput(stdout, l);
559 l->n_op = OREG;
561 putchar('\n');
565 * Multiply a register with a constant.
567 static void
568 imuli(NODE *p)
570 NODE *r = p->n_right;
572 if (r->n_lval >= 0 && r->n_lval <= 0777777) {
573 printf(" imuli ");
574 adrput(stdout, getlr(p, 'L'));
575 printf(",0%llo\n", r->n_lval);
576 } else {
577 printf(" imul ");
578 adrput(stdout, getlr(p, 'L'));
579 printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
584 * Divide a register with a constant.
586 static void
587 idivi(NODE *p)
589 NODE *r = p->n_right;
591 if (r->n_lval >= 0 && r->n_lval <= 0777777) {
592 printf(" idivi ");
593 adrput(stdout, getlr(p, '1'));
594 printf(",0%llo\n", r->n_lval);
595 } else {
596 printf(" idiv ");
597 adrput(stdout, getlr(p, '1'));
598 printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
603 * move a constant into a register.
605 static void
606 xmovei(NODE *p)
609 * Trick: If this is an unnamed constant, just move it directly,
610 * otherwise use xmovei to get section number.
612 if (p->n_name[0] == '\0' || p->n_lval > 0777777) {
613 printf(" ");
614 zzzcode(p, 'D');
615 putchar(' ');
616 adrput(stdout, getlr(p, '1'));
617 putchar(',');
618 zzzcode(p, 'E');
619 } else {
620 printf(" xmovei ");
621 adrput(stdout, getlr(p, '1'));
622 printf(",%s", p->n_name);
623 if (p->n_lval != 0)
624 printf("+0%llo", p->n_lval);
626 putchar('\n');
629 static void
630 printcon(NODE *p)
632 CONSZ cz;
634 p = p->n_left;
635 if (p->n_lval >= 0700000000000LL) {
636 /* converted to pointer in clocal() */
637 conput(0, p);
638 return;
640 if (p->n_lval == 0 && p->n_name[0] == '\0') {
641 putchar('0');
642 return;
644 if (BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR)
645 cz = (p->n_lval/4) | ((p->n_lval & 3) << 30);
646 else
647 cz = (p->n_lval/2) | (((p->n_lval & 1) + 5) << 30);
648 cz |= 0700000000000LL;
649 printf("0%llo", cz);
650 if (p->n_name[0] != '\0')
651 printf("+%s", p->n_name);
654 static void
655 putcond(NODE *p)
657 char *c = 0; /* XXX gcc */
659 switch (p->n_op) {
660 case EQ: c = "e"; break;
661 case NE: c = "n"; break;
662 case LE: c = "le"; break;
663 case LT: c = "l"; break;
664 case GT: c = "g"; break;
665 case GE: c = "ge"; break;
666 default:
667 cerror("putcond");
669 printf("%s", c);
672 void
673 zzzcode(NODE *p, int c)
675 NODE *l;
676 CONSZ hval;
678 switch (c) {
679 case 'A': /* ildb right arg */
680 adrput(stdout, p->n_left->n_left);
681 break;
683 case 'B': /* remove from stack after subroutine call */
684 if (p->n_qual)
685 printf(" subi %%17,0%o\n", p->n_qual);
686 break;
688 case 'C':
689 constput(p);
690 break;
692 case 'D': /* Find out which type of const load insn to use */
693 if (p->n_op != ICON)
694 cerror("zzzcode not ICON");
695 if (p->n_name[0] == '\0') {
696 if ((p->n_lval <= 0777777) && (p->n_lval > 0))
697 printf("movei");
698 else if ((p->n_lval & 0777777) == 0)
699 printf("hrlzi");
700 else
701 printf("move");
702 } else
703 printf("move");
704 break;
706 case 'E': /* Print correct constant expression */
707 if (p->n_name[0] == '\0') {
708 if ((p->n_lval <= 0777777) && (p->n_lval > 0)){
709 printf("0%llo", p->n_lval);
710 } else if ((p->n_lval & 0777777) == 0) {
711 printf("0%llo", p->n_lval >> 18);
712 } else {
713 if (p->n_lval < 0)
714 printf("[ .long -0%llo]", -p->n_lval);
715 else
716 printf("[ .long 0%llo]", p->n_lval);
718 } else {
719 if (p->n_lval == 0)
720 printf("[ .long %s]", p->n_name);
721 else
722 printf("[ .long %s+0%llo]",
723 p->n_name, p->n_lval);
725 break;
727 case 'G': /* structure argument */
728 printf(" addl %%17,0%o\n", p->n_stsize/(SZINT/SZCHAR));
729 printf(" foo...\n");
730 break;
732 case 'P':
733 p = getlr(p, 'R');
734 /* FALLTHROUGH */
735 case 'O':
737 * Print long long expression.
739 hval = gethval(p->n_lval);
740 printf("[ .long 0%llo,0%llo", hval,
741 (p->n_lval & 0377777777777LL) | (hval & 0400000000000LL));
742 if (p->n_name[0] != '\0')
743 printf("+%s", p->n_name);
744 printf(" ]");
745 break;
747 case 'F': /* Print an "opsimp" instruction based on its const type */
748 hopcode(oneinstr(p->n_right) ? 'C' : 'R', p->n_op);
749 break;
751 case 'H': /* Print a small constant */
752 p = p->n_right;
753 printf("0%llo", p->n_lval & 0777777);
754 break;
756 case 'Q': /* two-param long long comparisions */
757 twollcomp(p);
758 break;
760 case 'R': /* two-param conditionals */
761 twocomp(p);
762 break;
764 case 'U':
765 emitshort(p);
766 break;
768 case 'V':
769 storeshort(p);
770 break;
772 case 'Z':
773 ptrcomp(p);
774 break;
776 case 'a':
777 imuli(p);
778 break;
780 case 'b':
781 idivi(p);
782 break;
784 case 'c':
785 xmovei(p);
786 break;
788 case 'd':
789 printcon(p);
790 break;
792 case 'e':
793 putcond(p);
794 break;
796 case 'g':
797 if (p->n_right->n_op != OREG || p->n_right->n_lval != 0)
798 comperr("bad Zg oreg");
799 printf("%s", rnames[p->n_right->n_rval]);
800 break;
802 #if 0
803 case '1': /* double upput */
804 p = getlr(p, '1');
805 p->n_rval += 2;
806 adrput(stdout, p);
807 p->n_rval -= 2;
808 break;
809 #endif
811 case 'i': /* Write instruction for short load from name */
812 l = getlr(p, 'L');
813 printf(" h%cr%c %s,%s+" CONFMT "\n",
814 l->n_lval & 1 ? 'r' : 'l',
815 ISUNSIGNED(p->n_type) ? 'z' : 'e',
816 rnames[getlr(p, '1')->n_rval],
817 l->n_name, l->n_lval >> 1);
818 break;
820 default:
821 cerror("zzzcode %c", c);
825 /* set up temporary registers */
826 void
827 setregs()
829 fregs = 7; /* 7 free regs on PDP10 (1-7) */
832 /*ARGSUSED*/
834 rewfld(NODE *p)
836 return(1);
840 fldexpand(NODE *p, int cookie, char **cp)
842 return 0;
846 flshape(NODE *p)
848 register int o = p->n_op;
850 return (o == REG || o == NAME || o == ICON ||
851 (o == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)));
854 /* INTEMP shapes must not contain any temporary registers */
856 shtemp(NODE *p)
858 return(0);
862 shumul(NODE *p, int order)
864 register int o;
866 if (x2debug) {
867 int val;
868 printf("shumul(%p)\n", p);
869 eprint(p, 0, &val, &val);
872 o = p->n_op;
873 #if 0
874 if (o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON)
875 return(STARNM);
876 #endif
878 #if 0
879 if ((o == INCR) &&
880 (p->n_left->n_op == REG && p->n_right->n_op == ICON) &&
881 p->n_right->n_name[0] == '\0') {
882 switch (p->n_type) {
883 case CHAR|PTR:
884 case UCHAR|PTR:
885 o = 1;
886 break;
888 case SHORT|PTR:
889 case USHORT|PTR:
890 o = 2;
891 break;
893 case INT|PTR:
894 case UNSIGNED|PTR:
895 case LONG|PTR:
896 case ULONG|PTR:
897 case FLOAT|PTR:
898 o = 4;
899 break;
901 case DOUBLE|PTR:
902 case LONGLONG|PTR:
903 case ULONGLONG|PTR:
904 o = 8;
905 break;
907 default:
908 if (ISPTR(p->n_type) &&
909 ISPTR(DECREF(p->n_type))) {
910 o = 4;
911 break;
912 } else
913 return(0);
915 return( 0);
917 #endif
918 return( SRNOPE );
921 void
922 adrcon(CONSZ val)
924 cerror("adrcon: val %llo\n", val);
927 void
928 conput(FILE *fp, NODE *p)
930 switch (p->n_op) {
931 case ICON:
932 if (p->n_lval != 0) {
933 acon(stdout, p);
934 if (p->n_name[0] != '\0')
935 putchar('+');
937 if (p->n_name[0] != '\0')
938 printf("%s", p->n_name);
939 if (p->n_name[0] == '\0' && p->n_lval == 0)
940 putchar('0');
941 return;
943 case REG:
944 putstr(rnames[p->n_rval]);
945 return;
947 default:
948 cerror("illegal conput");
952 /*ARGSUSED*/
953 void
954 insput(NODE *p)
956 cerror("insput");
960 * Write out the upper address, like the upper register of a 2-register
961 * reference, or the next memory location.
963 void
964 upput(NODE *p, int size)
967 size /= SZLONG;
968 switch (p->n_op) {
969 case REG:
970 putstr(rnames[p->n_rval + size]);
971 break;
973 case NAME:
974 case OREG:
975 p->n_lval += size;
976 adrput(stdout, p);
977 p->n_lval -= size;
978 break;
979 case ICON:
980 printf(CONFMT, p->n_lval >> (36 * size));
981 break;
982 default:
983 cerror("upput bad op %d size %d", p->n_op, size);
987 void
988 adrput(FILE *fp, NODE *p)
990 int r;
991 /* output an address, with offsets, from p */
993 if (p->n_op == FLD)
994 p = p->n_left;
996 switch (p->n_op) {
998 case NAME:
999 if (p->n_name[0] != '\0')
1000 fputs(p->n_name, fp);
1001 if (p->n_lval != 0)
1002 fprintf(fp, "+" CONFMT, p->n_lval & 0777777777777LL);
1003 return;
1005 case OREG:
1006 r = p->n_rval;
1007 #if 0
1008 if (R2TEST(r)) { /* double indexing */
1009 register int flags;
1011 flags = R2UPK3(r);
1012 if (flags & 1)
1013 putc('*', fp);
1014 if (flags & 4)
1015 putc('-', fp);
1016 if (p->n_lval != 0 || p->n_name[0] != '\0')
1017 acon(p);
1018 if (R2UPK1(r) != 100)
1019 printf("(%s)", rnames[R2UPK1(r)]);
1020 if (flags & 2)
1021 putchar('+');
1022 printf("[%s]", rnames[R2UPK2(r)]);
1023 return;
1025 #endif
1026 if (R2TEST(r))
1027 cerror("adrput: unwanted double indexing: r %o", r);
1028 if (p->n_rval != FPREG && p->n_lval < 0 && p->n_name[0]) {
1029 fprintf(fp, "%s", p->n_name);
1030 acon(fp, p);
1031 fprintf(fp, "(%s)", rnames[p->n_rval]);
1032 return;
1034 if (p->n_lval < 0 && p->n_rval == FPREG && offarg) {
1035 p->n_lval -= offarg-2; acon(fp, p); p->n_lval += offarg-2;
1036 } else if (p->n_lval != 0)
1037 acon(fp, p);
1038 if (p->n_name[0] != '\0')
1039 fprintf(fp, "%s%s", p->n_lval ? "+" : "", p->n_name);
1040 if (p->n_lval > 0 && p->n_rval == FPREG && offlab)
1041 fprintf(fp, "+" LABFMT, offlab);
1042 if (p->n_lval < 0 && p->n_rval == FPREG && offarg)
1043 fprintf(fp, "(017)");
1044 else
1045 fprintf(fp, "(%s)", rnames[p->n_rval]);
1046 return;
1047 case ICON:
1048 /* addressable value of the constant */
1049 if (p->n_lval > 0) {
1050 acon(fp, p);
1051 if (p->n_name[0] != '\0')
1052 putc('+', fp);
1054 if (p->n_name[0] != '\0')
1055 fprintf(fp, "%s", p->n_name);
1056 if (p->n_lval < 0)
1057 acon(fp, p);
1058 if (p->n_name[0] == '\0' && p->n_lval == 0)
1059 putc('0', fp);
1060 return;
1062 case REG:
1063 fputs(rnames[p->n_rval], fp);
1064 return;
1066 default:
1067 cerror("illegal address, op %d", p->n_op);
1068 return;
1074 * print out a constant
1076 void
1077 acon(FILE *fp, NODE *p)
1079 if (p->n_lval < 0 && p->n_lval > -0777777777777ULL)
1080 fprintf(fp, "-" CONFMT, -p->n_lval);
1081 else
1082 fprintf(fp, CONFMT, p->n_lval);
1085 /* printf conditional and unconditional branches */
1086 void
1087 cbgen(int o,int lab)
1092 * Do some local optimizations that must be done after optim is called.
1094 static void
1095 optim2(NODE *p, void *arg)
1097 int op = p->n_op;
1098 int m, ml;
1099 NODE *l;
1101 /* Remove redundant PCONV's */
1102 if (op == PCONV) {
1103 l = p->n_left;
1104 m = BTYPE(p->n_type);
1105 ml = BTYPE(l->n_type);
1106 if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT ||
1107 m == DOUBLE || m == STRTY || m == UNIONTY ||
1108 m == UNSIGNED || m == ULONG || m == ULONGLONG) &&
1109 (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT ||
1110 ml == DOUBLE || ml == STRTY || ml == UNIONTY ||
1111 ml == UNSIGNED || ml == ULONG ||
1112 ml == ULONGLONG) && ISPTR(l->n_type)) {
1113 *p = *l;
1114 nfree(l);
1115 op = p->n_op;
1116 } else
1117 if (ISPTR(DECREF(p->n_type)) &&
1118 (l->n_type == INCREF(STRTY))) {
1119 *p = *l;
1120 nfree(l);
1121 op = p->n_op;
1122 } else
1123 if (ISPTR(DECREF(l->n_type)) &&
1124 (p->n_type == INCREF(INT) ||
1125 p->n_type == INCREF(STRTY) ||
1126 p->n_type == INCREF(UNSIGNED))) {
1127 *p = *l;
1128 nfree(l);
1129 op = p->n_op;
1133 /* Add constands, similar to the one in optim() */
1134 if (op == PLUS && p->n_right->n_op == ICON) {
1135 l = p->n_left;
1136 if (l->n_op == PLUS && l->n_right->n_op == ICON &&
1137 (p->n_right->n_name[0] == '\0' ||
1138 l->n_right->n_name[0] == '\0')) {
1139 l->n_right->n_lval += p->n_right->n_lval;
1140 if (l->n_right->n_name[0] == '\0')
1141 l->n_right->n_name = p->n_right->n_name;
1142 nfree(p->n_right);
1143 *p = *l;
1144 nfree(l);
1148 /* Convert "PTR undef" (void *) to "PTR uchar" */
1149 /* XXX - should be done in MI code */
1150 if (BTYPE(p->n_type) == VOID)
1151 p->n_type = (p->n_type & ~BTMASK) | UCHAR;
1152 if (op == ICON) {
1153 if ((p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR))
1154 && p->n_lval == 0 && p->n_name[0] != '\0')
1155 p->n_lval = 0700000000000LL;
1156 if ((p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT))
1157 && p->n_lval == 0 && p->n_name[0] != '\0')
1158 p->n_lval = 0750000000000LL;
1160 if (op == MINUS) {
1161 if ((p->n_left->n_type == (PTR|CHAR) ||
1162 p->n_left->n_type == (PTR|UCHAR)) &&
1163 (p->n_right->n_type == (PTR|CHAR) ||
1164 p->n_right->n_type == (PTR|UCHAR))) {
1165 l = talloc();
1166 l->n_op = SCONV;
1167 l->n_type = INT;
1168 l->n_left = p->n_right;
1169 p->n_right = l;
1170 l = talloc();
1171 l->n_op = SCONV;
1172 l->n_type = INT;
1173 l->n_left = p->n_left;
1174 p->n_left = l;
1179 void
1180 myreader(struct interpass *ipole)
1182 struct interpass *ip;
1184 DLIST_FOREACH(ip, ipole, qelem) {
1185 if (ip->type != IP_NODE)
1186 continue;
1187 walkf(ip->ip_node, optim2, 0);
1190 if (x2debug) {
1191 printf("myreader final tree:\n");
1192 printip(ipole);
1197 * Remove some PCONVs after OREGs are created.
1199 static void
1200 pconv2(NODE *p, void *arg)
1202 NODE *q;
1204 if (p->n_op == PLUS) {
1205 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
1206 if (p->n_right->n_op != ICON)
1207 return;
1208 if (p->n_left->n_op != PCONV)
1209 return;
1210 if (p->n_left->n_left->n_op != OREG)
1211 return;
1212 q = p->n_left->n_left;
1213 nfree(p->n_left);
1214 p->n_left = q;
1216 * This will be converted to another OREG later.
1222 void
1223 mycanon(NODE *p)
1225 walkf(p, pconv2, 0);
1229 * Remove last goto.
1231 void
1232 myoptim(struct interpass *ip)
1237 * Return a class suitable for a specific type.
1240 gclass(TWORD t)
1242 return (szty(t) == 2 ? CLASSB : CLASSA);
1245 static int
1246 argsiz(NODE *p)
1248 TWORD t = p->n_type;
1250 if (t == STRTY || t == UNIONTY)
1251 return p->n_stsize/(SZINT/SZCHAR);
1252 return szty(t);
1256 * Calculate argument sizes.
1258 void
1259 lastcall(NODE *p)
1261 NODE *op = p;
1262 int size = 0;
1264 p->n_qual = 0;
1265 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1266 return;
1267 for (p = p->n_right; p->n_op == CM; p = p->n_left)
1268 if (p->n_right->n_op != ASSIGN)
1269 size += argsiz(p->n_right);
1270 if (p->n_op != ASSIGN)
1271 size += argsiz(p);
1272 op->n_qual = size; /* XXX */
1275 void
1276 rmove(int s, int d, TWORD t)
1278 printf(" %smove %s,%s\n",
1279 (s > 017 ? "d" : ""), rnames[d], rnames[s]);
1283 * For class c, find worst-case displacement of the number of
1284 * registers in the array r[] indexed by class.
1287 COLORMAP(int c, int *r)
1289 int num;
1291 switch (c) {
1292 case CLASSA:
1293 /* there are 13 classa, so min 6 classb are needed to block */
1294 num = r[CLASSB] * 2;
1295 num += r[CLASSA];
1296 return num < 13;
1297 case CLASSB:
1298 /* 7 classa may block all classb */
1299 num = r[CLASSB] + r[CLASSA];
1300 return num < 7;
1302 comperr("COLORMAP");
1303 return 0; /* XXX gcc */
1307 * Target-dependent command-line options.
1309 void
1310 mflags(char *str)
1314 * Do something target-dependent for xasm arguments.
1315 * Supposed to find target-specific constraints and rewrite them.
1318 myxasm(struct interpass *ip, NODE *p)
1320 return 0;