source: mainline/uspace/app/pcc/arch/pdp10/local2.c@ 6037308

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6037308 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 27.0 KB
RevLine 
[a7de7182]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.
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 * 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
16 *
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.
27 */
28
29
30# include "pass2.h"
31# include <ctype.h>
32
33# define putstr(s) fputs((s), stdout)
34
35void acon(FILE *, NODE *p);
36int argsize(NODE *p);
37void genargs(NODE *p);
38
39static int offlab;
40int offarg;
41static int addto;
42static int regoff[16];
43
44void
45deflab(int label)
46{
47 printf(LABFMT ":\n", label);
48}
49
50void
51prologue(struct interpass_prolog *ipp)
52{
53 int i, j;
54
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]);
64
65 for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
66 if (i & 1)
67 regoff[j] = addto++;
68 }
69 if (addto)
70 printf(" addi %s,0%o\n", rnames[STKREG], addto);
71
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]);
76 }
77}
78
79void
80eoftn(struct interpass_prolog *ipp)
81{
82 int i, j;
83
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]);
90 }
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]);
94}
95
96#if 0
97void
98prologue(int regs, int autos)
99{
100 int i, addto;
101
102 offlab = getlab2();
103 if (regs < 0 || autos < 0) {
104 /*
105 * non-optimized code, jump to epilogue for code generation.
106 */
107 ftlab1 = getlab2();
108 ftlab2 = getlab2();
109 printf(" jrst L%d\n", ftlab1);
110 printf("L%d:\n", ftlab2);
111 } else {
112 /*
113 * We here know what register to save and how much to
114 * add to the stack.
115 */
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++;
128 }
129 if (addto)
130 printf(" addi %s,0%o\n", rnames[017], addto);
131 } else
132 offarg = 1;
133 }
134}
135
136/*
137 * End of block.
138 */
139void
140eoftn(int regs, int autos, int retlab)
141{
142 register OFFSZ spoff; /* offset from stack pointer */
143 int i;
144
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++;
158 }
159 printf(" move %s,%s\n", rnames[017], rnames[016]);
160 printf(" pop %s,%s\n", rnames[017], rnames[016]);
161 }
162 printf(" popj %s,\n", rnames[017]);
163
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++;
176 }
177 if (spoff)
178 printf(" addi %s,0%llo\n", rnames[017], spoff);
179 printf(" jrst L%d\n", ftlab2);
180 }
181 printf(" .set " LABFMT ",0%o\n", offlab, MAXRVAR-regs);
182 offarg = isoptim = 0;
183}
184#endif
185
186/*
187 * add/sub/...
188 *
189 * Param given:
190 * R - Register
191 * M - Memory
192 * C - Constant
193 */
194void
195hopcode(int f, int o)
196{
197 cerror("hopcode: f %d %d", f, o);
198}
199
200char *
201rnames[] = { /* 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",
206};
207
208int
209tlen(p) NODE *p;
210{
211 switch(p->n_type) {
212 case CHAR:
213 case UCHAR:
214 return(1);
215
216 case SHORT:
217 case USHORT:
218 return(SZSHORT/SZCHAR);
219
220 case DOUBLE:
221 return(SZDOUBLE/SZCHAR);
222
223 case INT:
224 case UNSIGNED:
225 case LONG:
226 case ULONG:
227 return(SZINT/SZCHAR);
228
229 case LONGLONG:
230 case ULONGLONG:
231 return SZLONGLONG/SZCHAR;
232
233 default:
234 if (!ISPTR(p->n_type))
235 cerror("tlen type %d not pointer");
236 return SZPOINT(0)/SZCHAR;
237 }
238}
239
240static char *
241binskip[] = {
242 "e", /* jumpe */
243 "n", /* jumpn */
244 "le", /* jumple */
245 "l", /* jumpl */
246 "ge", /* jumpge */
247 "g", /* jumpg */
248};
249
250/*
251 * Extract the higher 36 bits from a longlong.
252 */
253static CONSZ
254gethval(CONSZ lval)
255{
256 CONSZ hval = (lval >> 35) & 03777777777LL;
257
258 if ((hval & 03000000000LL) == 03000000000LL) {
259 hval |= 0777000000000LL;
260 } else if ((hval & 03000000000LL) == 02000000000LL) {
261 hval &= 01777777777LL;
262 hval |= 0400000000000LL;
263 }
264 return hval;
265}
266
267/*
268 * Do a binary comparision, and jump accordingly.
269 */
270static void
271twocomp(NODE *p)
272{
273 int o = p->n_op;
274 extern int negrel[];
275 int isscon = 0, iscon = p->n_right->n_op == ICON;
276
277 if (o < EQ || o > GT)
278 cerror("bad binary conditional branch: %s", opst[o]);
279
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;
289 }
290 if (iscon)
291 isscon = p->n_right->n_lval >= 0 &&
292 p->n_right->n_lval < 01000000;
293
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);
305}
306
307/*
308 * Compare byte/word pointers.
309 * XXX - do not work for highest bit set in address
310 */
311static void
312ptrcomp(NODE *p)
313{
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);
317}
318
319/*
320 * Do a binary comparision of two long long, and jump accordingly.
321 * XXX - can optimize for constants.
322 */
323static void
324twollcomp(NODE *p)
325{
326 int o = p->n_op;
327 int iscon = p->n_right->n_op == ICON;
328 int m = 0; /* XXX gcc */
329
330 if (o < EQ || o > GT)
331 cerror("bad long long conditional branch: %s", opst[o]);
332
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;
358 }
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);
369
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());
380
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);
393}
394
395/*
396 * Print the correct instruction for constants.
397 */
398static void
399constput(NODE *p)
400{
401 CONSZ val = p->n_right->n_lval;
402 int reg = p->n_left->n_rval;
403
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);
416 }
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);
423 }
424}
425
426/*
427 * Return true if the constant can be bundled in an instruction (immediate).
428 */
429static int
430oneinstr(NODE *p)
431{
432 if (p->n_name[0] != '\0')
433 return 0;
434 if ((p->n_lval & 0777777000000ULL) != 0)
435 return 0;
436 return 1;
437}
438
439/*
440 * Emit a halfword or byte instruction, from OREG to REG.
441 * Sign extension must also be done here.
442 */
443static void
444emitshort(NODE *p)
445{
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;
452
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;
467 }
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;
481 }
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]);
489signe: 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");
495 }
496 return;
497 } else {
498 printf(" h%cr%c ", off & 1 ? 'r' : 'l',
499 issigned ? 'e' : 'z');
500 }
501 p->n_lval /= (ischar ? 4 : 2);
502 adrput(stdout, getlr(p, '1'));
503 putchar(',');
504 adrput(stdout, getlr(p, 'L'));
505 putchar('\n');
506}
507
508/*
509 * Store a short from a register. Destination is a OREG.
510 */
511static void
512storeshort(NODE *p)
513{
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;
518
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;
526 }
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;
534 }
535
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');
547 }
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;
560 }
561 putchar('\n');
562}
563
564/*
565 * Multiply a register with a constant.
566 */
567static void
568imuli(NODE *p)
569{
570 NODE *r = p->n_right;
571
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);
580 }
581}
582
583/*
584 * Divide a register with a constant.
585 */
586static void
587idivi(NODE *p)
588{
589 NODE *r = p->n_right;
590
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);
599 }
600}
601
602/*
603 * move a constant into a register.
604 */
605static void
606xmovei(NODE *p)
607{
608 /*
609 * Trick: If this is an unnamed constant, just move it directly,
610 * otherwise use xmovei to get section number.
611 */
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);
625 }
626 putchar('\n');
627}
628
629static void
630printcon(NODE *p)
631{
632 CONSZ cz;
633
634 p = p->n_left;
635 if (p->n_lval >= 0700000000000LL) {
636 /* converted to pointer in clocal() */
637 conput(0, p);
638 return;
639 }
640 if (p->n_lval == 0 && p->n_name[0] == '\0') {
641 putchar('0');
642 return;
643 }
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);
652}
653
654static void
655putcond(NODE *p)
656{
657 char *c = 0; /* XXX gcc */
658
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");
668 }
669 printf("%s", c);
670}
671
672void
673zzzcode(NODE *p, int c)
674{
675 NODE *l;
676 CONSZ hval;
677
678 switch (c) {
679 case 'A': /* ildb right arg */
680 adrput(stdout, p->n_left->n_left);
681 break;
682
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;
687
688 case 'C':
689 constput(p);
690 break;
691
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;
705
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);
717 }
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);
724 }
725 break;
726
727 case 'G': /* structure argument */
728 printf(" addl %%17,0%o\n", p->n_stsize/(SZINT/SZCHAR));
729 printf(" foo...\n");
730 break;
731
732 case 'P':
733 p = getlr(p, 'R');
734 /* FALLTHROUGH */
735 case 'O':
736 /*
737 * Print long long expression.
738 */
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;
746
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;
750
751 case 'H': /* Print a small constant */
752 p = p->n_right;
753 printf("0%llo", p->n_lval & 0777777);
754 break;
755
756 case 'Q': /* two-param long long comparisions */
757 twollcomp(p);
758 break;
759
760 case 'R': /* two-param conditionals */
761 twocomp(p);
762 break;
763
764 case 'U':
765 emitshort(p);
766 break;
767
768 case 'V':
769 storeshort(p);
770 break;
771
772 case 'Z':
773 ptrcomp(p);
774 break;
775
776 case 'a':
777 imuli(p);
778 break;
779
780 case 'b':
781 idivi(p);
782 break;
783
784 case 'c':
785 xmovei(p);
786 break;
787
788 case 'd':
789 printcon(p);
790 break;
791
792 case 'e':
793 putcond(p);
794 break;
795
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;
801
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
810
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;
819
820 default:
821 cerror("zzzcode %c", c);
822 }
823}
824
825/* set up temporary registers */
826void
827setregs()
828{
829 fregs = 7; /* 7 free regs on PDP10 (1-7) */
830}
831
832/*ARGSUSED*/
833int
834rewfld(NODE *p)
835{
836 return(1);
837}
838
839int
840fldexpand(NODE *p, int cookie, char **cp)
841{
842 return 0;
843}
844
845int
846flshape(NODE *p)
847{
848 register int o = p->n_op;
849
850 return (o == REG || o == NAME || o == ICON ||
851 (o == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)));
852}
853
854/* INTEMP shapes must not contain any temporary registers */
855int
856shtemp(NODE *p)
857{
858 return(0);
859}
860
861int
862shumul(NODE *p, int order)
863{
864 register int o;
865
866 if (x2debug) {
867 int val;
868 printf("shumul(%p)\n", p);
869 eprint(p, 0, &val, &val);
870 }
871
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
877
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;
887
888 case SHORT|PTR:
889 case USHORT|PTR:
890 o = 2;
891 break;
892
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;
900
901 case DOUBLE|PTR:
902 case LONGLONG|PTR:
903 case ULONGLONG|PTR:
904 o = 8;
905 break;
906
907 default:
908 if (ISPTR(p->n_type) &&
909 ISPTR(DECREF(p->n_type))) {
910 o = 4;
911 break;
912 } else
913 return(0);
914 }
915 return( 0);
916 }
917#endif
918 return( SRNOPE );
919}
920
921void
922adrcon(CONSZ val)
923{
924 cerror("adrcon: val %llo\n", val);
925}
926
927void
928conput(FILE *fp, NODE *p)
929{
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('+');
936 }
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;
942
943 case REG:
944 putstr(rnames[p->n_rval]);
945 return;
946
947 default:
948 cerror("illegal conput");
949 }
950}
951
952/*ARGSUSED*/
953void
954insput(NODE *p)
955{
956 cerror("insput");
957}
958
959/*
960 * Write out the upper address, like the upper register of a 2-register
961 * reference, or the next memory location.
962 */
963void
964upput(NODE *p, int size)
965{
966
967 size /= SZLONG;
968 switch (p->n_op) {
969 case REG:
970 putstr(rnames[p->n_rval + size]);
971 break;
972
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);
984 }
985}
986
987void
988adrput(FILE *fp, NODE *p)
989{
990 int r;
991 /* output an address, with offsets, from p */
992
993 if (p->n_op == FLD)
994 p = p->n_left;
995
996 switch (p->n_op) {
997
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;
1004
1005 case OREG:
1006 r = p->n_rval;
1007#if 0
1008 if (R2TEST(r)) { /* double indexing */
1009 register int flags;
1010
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;
1024 }
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;
1033 }
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);
1053 }
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;
1061
1062 case REG:
1063 fputs(rnames[p->n_rval], fp);
1064 return;
1065
1066 default:
1067 cerror("illegal address, op %d", p->n_op);
1068 return;
1069
1070 }
1071}
1072
1073/*
1074 * print out a constant
1075*/
1076void
1077acon(FILE *fp, NODE *p)
1078{
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);
1083}
1084
1085/* printf conditional and unconditional branches */
1086void
1087cbgen(int o,int lab)
1088{
1089}
1090
1091/*
1092 * Do some local optimizations that must be done after optim is called.
1093 */
1094static void
1095optim2(NODE *p, void *arg)
1096{
1097 int op = p->n_op;
1098 int m, ml;
1099 NODE *l;
1100
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;
1130 }
1131
1132 }
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);
1145 }
1146 }
1147
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;
1159 }
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;
1175 }
1176 }
1177}
1178
1179void
1180myreader(struct interpass *ipole)
1181{
1182 struct interpass *ip;
1183
1184 DLIST_FOREACH(ip, ipole, qelem) {
1185 if (ip->type != IP_NODE)
1186 continue;
1187 walkf(ip->ip_node, optim2, 0);
1188 }
1189
1190 if (x2debug) {
1191 printf("myreader final tree:\n");
1192 printip(ipole);
1193 }
1194}
1195
1196/*
1197 * Remove some PCONVs after OREGs are created.
1198 */
1199static void
1200pconv2(NODE *p, void *arg)
1201{
1202 NODE *q;
1203
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;
1215 /*
1216 * This will be converted to another OREG later.
1217 */
1218 }
1219 }
1220}
1221
1222void
1223mycanon(NODE *p)
1224{
1225 walkf(p, pconv2, 0);
1226}
1227
1228/*
1229 * Remove last goto.
1230 */
1231void
1232myoptim(struct interpass *ip)
1233{
1234}
1235
1236/*
1237 * Return a class suitable for a specific type.
1238 */
1239int
1240gclass(TWORD t)
1241{
1242 return (szty(t) == 2 ? CLASSB : CLASSA);
1243}
1244
1245static int
1246argsiz(NODE *p)
1247{
1248 TWORD t = p->n_type;
1249
1250 if (t == STRTY || t == UNIONTY)
1251 return p->n_stsize/(SZINT/SZCHAR);
1252 return szty(t);
1253}
1254
1255/*
1256 * Calculate argument sizes.
1257 */
1258void
1259lastcall(NODE *p)
1260{
1261 NODE *op = p;
1262 int size = 0;
1263
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 */
1273}
1274
1275void
1276rmove(int s, int d, TWORD t)
1277{
1278 printf(" %smove %s,%s\n",
1279 (s > 017 ? "d" : ""), rnames[d], rnames[s]);
1280}
1281
1282/*
1283 * For class c, find worst-case displacement of the number of
1284 * registers in the array r[] indexed by class.
1285 */
1286int
1287COLORMAP(int c, int *r)
1288{
1289 int num;
1290
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;
1301 }
1302 comperr("COLORMAP");
1303 return 0; /* XXX gcc */
1304}
1305
1306/*
1307 * Target-dependent command-line options.
1308 */
1309void
1310mflags(char *str)
1311{
1312}
1313/*
1314 * Do something target-dependent for xasm arguments.
1315 * Supposed to find target-specific constraints and rewrite them.
1316 */
1317int
1318myxasm(struct interpass *ip, NODE *p)
1319{
1320 return 0;
1321}
Note: See TracBrowser for help on using the repository browser.