1 /*	$Id: local2.c,v 1.105 2012/09/26 20:33:03 plunky 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 void acon(FILE *, NODE *p);
34 int argsize(NODE *p);
35 void genargs(NODE *p);
36 
37 static int offlab;
38 int offarg;
39 static int addto;
40 static int regoff[16];
41 
42 void
deflab(int label)43 deflab(int label)
44 {
45 	printf(LABFMT ":\n", label);
46 }
47 
48 void
prologue(struct interpass_prolog * ipp)49 prologue(struct interpass_prolog *ipp)
50 {
51 	int i, j;
52 
53 	if (ipp->ipp_vis)
54 		printf("	.globl %s\n", ipp->ipp_name);
55 	printf("%s:\n", ipp->ipp_name);
56 	addto = p2maxautooff;
57 	if (addto >= AUTOINIT/SZCHAR)
58 		addto -= AUTOINIT/SZCHAR;
59 	addto /= SZINT/SZCHAR;	/* use words here */
60 	printf("	push %s,%s\n",rnames[STKREG], rnames[FPREG]);
61 	printf("	move %s,%s\n", rnames[FPREG],rnames[STKREG]);
62 
63 	for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
64 		if (i & 1)
65 			regoff[j] = addto++;
66 	}
67 	if (addto)
68 		printf("	addi %s,0%o\n", rnames[STKREG], addto);
69 
70 	for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
71 		if (i & 1)
72 			printf("	movem %s,%d(%s)\n",
73 			    rnames[j], regoff[j], rnames[STKREG]);
74 	}
75 }
76 
77 void
eoftn(struct interpass_prolog * ipp)78 eoftn(struct interpass_prolog *ipp)
79 {
80 	int i, j;
81 
82 	if (ipp->ipp_ip.ip_lbl == 0)
83 		return; /* no code needs to be generated */
84 	for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) {
85 		if (i & 1)
86 			printf("	move %s,%d(%s)\n",
87 			    rnames[j], regoff[j], rnames[STKREG]);
88 	}
89 	printf("	move %s,%s\n", rnames[STKREG], rnames[FPREG]);
90 	printf("	pop %s,%s\n", rnames[STKREG], rnames[FPREG]);
91 	printf("	popj %s,\n", rnames[STKREG]);
92 }
93 
94 #if 0
95 void
96 prologue(int regs, int autos)
97 {
98 	int i, addto;
99 
100 	offlab = getlab2();
101 	if (regs < 0 || autos < 0) {
102 		/*
103 		 * non-optimized code, jump to epilogue for code generation.
104 		 */
105 		ftlab1 = getlab2();
106 		ftlab2 = getlab2();
107 		printf("	jrst L%d\n", ftlab1);
108 		printf("L%d:\n", ftlab2);
109 	} else {
110 		/*
111 		 * We here know what register to save and how much to
112 		 * add to the stack.
113 		 */
114 		autos = autos + (SZINT-1);
115 		addto = (autos - AUTOINIT)/SZINT + (MAXRVAR-regs);
116 		if (addto || gflag) {
117 			printf("	push %s,%s\n",rnames[017], rnames[016]);
118 			printf("	move %s,%s\n", rnames[016],rnames[017]);
119 			for (i = regs; i < MAXRVAR; i++) {
120 				int db = ((i+1) < MAXRVAR);
121 				printf("	%smovem %s,0%o(%s)\n",
122 				    db ? "d" : "",
123 				    rnames[i+1], i+1-regs, rnames[016]);
124 				if (db)
125 					i++;
126 			}
127 			if (addto)
128 				printf("	addi %s,0%o\n", rnames[017], addto);
129 		} else
130 			offarg = 1;
131 	}
132 }
133 
134 /*
135  * End of block.
136  */
137 void
138 eoftn(int regs, int autos, int retlab)
139 {
140 	register OFFSZ spoff;	/* offset from stack pointer */
141 	int i;
142 
143 	spoff = autos + (SZINT-1);
144 	if (spoff >= AUTOINIT)
145 		spoff -= AUTOINIT;
146 	spoff /= SZINT;
147 	/* return from function code */
148 	printf("L%d:\n", retlab);
149 	if (gflag || isoptim == 0 || autos != AUTOINIT || regs != MAXRVAR) {
150 		for (i = regs; i < MAXRVAR; i++) {
151 			int db = ((i+1) < MAXRVAR);
152 			printf("	%smove %s,0%o(%s)\n", db ? "d" : "",
153 			    rnames[i+1], i+1-regs, rnames[016]);
154 			if (db)
155 				i++;
156 		}
157 		printf("	move %s,%s\n", rnames[017], rnames[016]);
158 		printf("	pop %s,%s\n", rnames[017], rnames[016]);
159 	}
160 	printf("	popj %s,\n", rnames[017]);
161 
162 	/* Prolog code */
163 	if (isoptim == 0) {
164 		printf("L%d:\n", ftlab1);
165 		printf("	push %s,%s\n", rnames[017], rnames[016]);
166 		printf("	move %s,%s\n", rnames[016], rnames[017]);
167 		for (i = regs; i < MAXRVAR; i++) {
168 			int db = ((i+1) < MAXRVAR);
169 			printf("	%smovem %s,0%o(%s)\n", db ? "d" : "",
170 			    rnames[i+1], i+1-regs, rnames[016]);
171 			spoff++;
172 			if (db)
173 				i++, spoff++;
174 		}
175 		if (spoff)
176 			printf("	addi %s,0%llo\n", rnames[017], spoff);
177 		printf("	jrst L%d\n", ftlab2);
178 	}
179 	printf("	.set " LABFMT ",0%o\n", offlab, MAXRVAR-regs);
180 	offarg = isoptim = 0;
181 }
182 #endif
183 
184 /*
185  * add/sub/...
186  *
187  * Param given:
188  *	R - Register
189  *	M - Memory
190  *	C - Constant
191  */
192 void
hopcode(int f,int o)193 hopcode(int f, int o)
194 {
195 	cerror("hopcode: f %d %d", f, o);
196 }
197 
198 char *
199 rnames[] = {  /* keyed to register number tokens */
200 	"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
201 	"%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
202 	"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
203 	"%10", "%11", "%12", "%13", "%14", "%15",
204 };
205 
206 int
tlen(p)207 tlen(p) NODE *p;
208 {
209 	switch(p->n_type) {
210 		case CHAR:
211 		case UCHAR:
212 			return(1);
213 
214 		case SHORT:
215 		case USHORT:
216 			return(SZSHORT/SZCHAR);
217 
218 		case DOUBLE:
219 			return(SZDOUBLE/SZCHAR);
220 
221 		case INT:
222 		case UNSIGNED:
223 		case LONG:
224 		case ULONG:
225 			return(SZINT/SZCHAR);
226 
227 		case LONGLONG:
228 		case ULONGLONG:
229 			return SZLONGLONG/SZCHAR;
230 
231 		default:
232 			if (!ISPTR(p->n_type))
233 				cerror("tlen type %d not pointer");
234 			return SZPOINT(0)/SZCHAR;
235 		}
236 }
237 
238 static char *
239 binskip[] = {
240 	"e",	/* jumpe */
241 	"n",	/* jumpn */
242 	"le",	/* jumple */
243 	"l",	/* jumpl */
244 	"ge",	/* jumpge */
245 	"g",	/* jumpg */
246 };
247 
248 /*
249  * Extract the higher 36 bits from a longlong.
250  */
251 static CONSZ
gethval(CONSZ lval)252 gethval(CONSZ lval)
253 {
254 	CONSZ hval = (lval >> 35) & 03777777777LL;
255 
256 	if ((hval & 03000000000LL) == 03000000000LL) {
257 		hval |= 0777000000000LL;
258 	} else if ((hval & 03000000000LL) == 02000000000LL) {
259 		hval &= 01777777777LL;
260 		hval |= 0400000000000LL;
261 	}
262 	return hval;
263 }
264 
265 /*
266  * Do a binary comparision, and jump accordingly.
267  */
268 static void
twocomp(NODE * p)269 twocomp(NODE *p)
270 {
271 	int o = p->n_op;
272 	extern int negrel[];
273 	int isscon = 0, iscon = p->n_right->n_op == ICON;
274 
275 	if (o < EQ || o > GT)
276 		cerror("bad binary conditional branch: %s", opst[o]);
277 
278 	if (iscon && p->n_right->n_name[0] != 0) {
279 		printf("	cam%s ", binskip[negrel[o-EQ]-EQ]);
280 		adrput(stdout, getlr(p, 'L'));
281 		putchar(',');
282 		printf("[ .long ");
283 		adrput(stdout, getlr(p, 'R'));
284 		putchar(']');
285 		printf("\n	jrst L%d\n", p->n_label);
286 		return;
287 	}
288 	if (iscon)
289 		isscon = p->n_right->n_lval >= 0 &&
290 		    p->n_right->n_lval < 01000000;
291 
292 	printf("	ca%c%s ", iscon && isscon ? 'i' : 'm',
293 	    binskip[negrel[o-EQ]-EQ]);
294 	adrput(stdout, getlr(p, 'L'));
295 	putchar(',');
296 	if (iscon && (isscon == 0)) {
297 		printf("[ .long ");
298 		adrput(stdout, getlr(p, 'R'));
299 		putchar(']');
300 	} else
301 		adrput(stdout, getlr(p, 'R'));
302 	printf("\n	jrst L%d\n", p->n_label);
303 }
304 
305 /*
306  * Compare byte/word pointers.
307  * XXX - do not work for highest bit set in address
308  */
309 static void
ptrcomp(NODE * p)310 ptrcomp(NODE *p)
311 {
312 	printf("	rot "); adrput(stdout, getlr(p, 'L')); printf(",6\n");
313 	printf("	rot "); adrput(stdout, getlr(p, 'R')); printf(",6\n");
314 	twocomp(p);
315 }
316 
317 /*
318  * Do a binary comparision of two long long, and jump accordingly.
319  * XXX - can optimize for constants.
320  */
321 static void
twollcomp(NODE * p)322 twollcomp(NODE *p)
323 {
324 	int o = p->n_op;
325 	int iscon = p->n_right->n_op == ICON;
326 	int m = 0; /* XXX gcc */
327 
328 	if (o < EQ || o > GT)
329 		cerror("bad long long conditional branch: %s", opst[o]);
330 
331 	/* Special strategy for equal/not equal */
332 	if (o == EQ || o == NE) {
333 		if (o == EQ)
334 			m = getlab2();
335 		printf("	came ");
336 		upput(getlr(p, 'L'), SZLONG);
337 		putchar(',');
338 		if (iscon)
339 			printf("[ .long ");
340 		upput(getlr(p, 'R'), SZLONG);
341 		if (iscon)
342 			putchar(']');
343 		printf("\n	jrst L%d\n", o == EQ ? m : p->n_label);
344 		printf("	cam%c ", o == EQ ? 'n' : 'e');
345 		adrput(stdout, getlr(p, 'L'));
346 		putchar(',');
347 		if (iscon)
348 			printf("[ .long ");
349 		adrput(stdout, getlr(p, 'R'));
350 		if (iscon)
351 			putchar(']');
352 		printf("\n	jrst L%d\n", p->n_label);
353 		if (o == EQ)
354 			printf("L%d:\n", m);
355 		return;
356 	}
357 	/* First test highword */
358 	printf("	cam%ce ", o == GT || o == GE ? 'l' : 'g');
359 	adrput(stdout, getlr(p, 'L'));
360 	putchar(',');
361 	if (iscon)
362 		printf("[ .long ");
363 	adrput(stdout, getlr(p, 'R'));
364 	if (iscon)
365 		putchar(']');
366 	printf("\n	jrst L%d\n", p->n_label);
367 
368 	/* Test equality */
369 	printf("	came ");
370 	adrput(stdout, getlr(p, 'L'));
371 	putchar(',');
372 	if (iscon)
373 		printf("[ .long ");
374 	adrput(stdout, getlr(p, 'R'));
375 	if (iscon)
376 		putchar(']');
377 	printf("\n	jrst L%d\n", m = getlab2());
378 
379 	/* Test lowword. Only works with pdp10 format for longlongs */
380 	printf("	cam%c%c ", o == GT || o == GE ? 'l' : 'g',
381 	    o == LT || o == GT ? 'e' : ' ');
382 	upput(getlr(p, 'L'), SZLONG);
383 	putchar(',');
384 	if (iscon)
385 		printf("[ .long ");
386 	upput(getlr(p, 'R'), SZLONG);
387 	if (iscon)
388 		putchar(']');
389 	printf("\n	jrst L%d\n", p->n_label);
390 	printf("L%d:\n", m);
391 }
392 
393 /*
394  * Print the correct instruction for constants.
395  */
396 static void
constput(NODE * p)397 constput(NODE *p)
398 {
399 	CONSZ val = p->n_right->n_lval;
400 	int reg = p->n_left->n_rval;
401 
402 	/* Only numeric constant */
403 	if (p->n_right->n_name[0] == '\0') {
404 		if (val == 0) {
405 			printf("movei %s,0", rnames[reg]);
406 		} else if ((val & 0777777000000LL) == 0) {
407 			printf("movei %s,0%llo", rnames[reg], val);
408 		} else if ((val & 0777777) == 0) {
409 			printf("hrlzi %s,0%llo", rnames[reg], val >> 18);
410 		} else {
411 			printf("move %s,[ .long 0%llo]", rnames[reg],
412 			    szty(p->n_right->n_type) > 1 ? val :
413 			    val & 0777777777777LL);
414 		}
415 		/* Can have more tests here, hrloi etc */
416 		return;
417 	} else {
418 		printf("xmovei %s,%s", rnames[reg], p->n_right->n_name);
419 		if (val)
420 			printf("+" CONFMT, val);
421 	}
422 }
423 
424 /*
425  * Return true if the constant can be bundled in an instruction (immediate).
426  */
427 static int
oneinstr(NODE * p)428 oneinstr(NODE *p)
429 {
430 	if (p->n_name[0] != '\0')
431 		return 0;
432 	if ((p->n_lval & 0777777000000ULL) != 0)
433 		return 0;
434 	return 1;
435 }
436 
437 /*
438  * Emit a halfword or byte instruction, from OREG to REG.
439  * Sign extension must also be done here.
440  */
441 static void
emitshort(NODE * p)442 emitshort(NODE *p)
443 {
444 	CONSZ off = p->n_lval;
445 	TWORD type = p->n_type;
446 	int reg = p->n_rval;
447 	int issigned = !ISUNSIGNED(type);
448 	int ischar = type == CHAR || type == UCHAR;
449 	int reg1 = getlr(p, '1')->n_rval;
450 
451 	if (off < 0) { /* argument, use move instead */
452 		printf("	move ");
453 	} else if (off == 0 && p->n_name[0] == 0) {
454 		printf("	ldb %s,%s\n", rnames[reg1], rnames[reg]);
455 		/* XXX must sign extend here even if not necessary */
456 		switch (type) {
457 		case CHAR:
458 			printf("	lsh %s,033\n", rnames[reg1]);
459 			printf("	ash %s,-033\n", rnames[reg1]);
460 			break;
461 		case SHORT:
462 			printf("	hrre %s,%s\n",
463 			    rnames[reg1], rnames[reg1]);
464 			break;
465 		}
466 		return;
467 	} else if (ischar) {
468 		if (off >= 0700000000000LL && p->n_name[0] != '\0') {
469 			cerror("emitsh");
470 			/* reg contains index integer */
471 //			if (!istreg(reg))
472 //				cerror("emitshort !istreg");
473 			printf("	adjbp %s,[ .long 0%llo+%s ]\n",
474 			    rnames[reg], off, p->n_name);
475 			printf("	ldb ");
476 			adrput(stdout, getlr(p, '1'));
477 			printf(",%s\n", rnames[reg]);
478 			goto signe;
479 		}
480 		printf("	ldb ");
481 		adrput(stdout, getlr(p, '1'));
482 		if (off)
483 			printf(",[ .long 0%02o11%02o%06o ]\n",
484 			    (int)(27-(9*(off&3))), reg, (int)off/4);
485 		else
486 			printf(",%s\n", rnames[reg]);
487 signe:		if (issigned) {
488 			printf("	lsh ");
489 			adrput(stdout, getlr(p, '1'));
490 			printf(",033\n	ash ");
491 			adrput(stdout, getlr(p, '1'));
492 			printf(",-033\n");
493 		}
494 		return;
495 	} else {
496 		printf("	h%cr%c ", off & 1 ? 'r' : 'l',
497 		    issigned ? 'e' : 'z');
498 	}
499 	p->n_lval /= (ischar ? 4 : 2);
500 	adrput(stdout, getlr(p, '1'));
501 	putchar(',');
502 	adrput(stdout, getlr(p, 'L'));
503 	putchar('\n');
504 }
505 
506 /*
507  * Store a short from a register. Destination is a OREG.
508  */
509 static void
storeshort(NODE * p)510 storeshort(NODE *p)
511 {
512 	NODE *l = p->n_left;
513 	CONSZ off = l->n_lval;
514 	int reg = l->n_rval;
515 	int ischar = BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR;
516 
517 	if (l->n_op == NAME) {
518 		if (ischar) {
519 			printf("	dpb ");
520 			adrput(stdout, getlr(p, 'R'));
521 			printf(",[ .long 0%02o%010o+%s ]\n",
522 			    070+((int)off&3), (int)(off/4), l->n_name);
523 			return;
524 		}
525 		printf("	hr%cm ", off & 1 ? 'r' : 'l');
526 		l->n_lval /= 2;
527 		adrput(stdout, getlr(p, 'R'));
528 		putchar(',');
529 		adrput(stdout, getlr(p, 'L'));
530 		putchar('\n');
531 		return;
532 	}
533 
534 	if (off || reg == FPREG) { /* Can emit halfword instructions */
535 		if (off < 0) { /* argument, use move instead */
536 			printf("	movem ");
537 		} else if (ischar) {
538 			printf("	dpb ");
539 			adrput(stdout, getlr(p, '1'));
540 			printf(",[ .long 0%02o11%02o%06o ]\n",
541 			    (int)(27-(9*(off&3))), reg, (int)off/4);
542 			return;
543 		} else {
544 			printf("	hr%cm ", off & 1 ? 'r' : 'l');
545 		}
546 		l->n_lval /= 2;
547 		adrput(stdout, getlr(p, 'R'));
548 		putchar(',');
549 		adrput(stdout, getlr(p, 'L'));
550 	} else {
551 		printf("	dpb ");
552 		adrput(stdout, getlr(p, 'R'));
553 		putchar(',');
554 		l = getlr(p, 'L');
555 		l->n_op = REG;
556 		adrput(stdout, l);
557 		l->n_op = OREG;
558 	}
559 	putchar('\n');
560 }
561 
562 /*
563  * Multiply a register with a constant.
564  */
565 static void
imuli(NODE * p)566 imuli(NODE *p)
567 {
568 	NODE *r = p->n_right;
569 
570 	if (r->n_lval >= 0 && r->n_lval <= 0777777) {
571 		printf("	imuli ");
572 		adrput(stdout, getlr(p, 'L'));
573 		printf(",0%llo\n", r->n_lval);
574 	} else {
575 		printf("	imul ");
576 		adrput(stdout, getlr(p, 'L'));
577 		printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
578 	}
579 }
580 
581 /*
582  * Divide a register with a constant.
583  */
584 static void
idivi(NODE * p)585 idivi(NODE *p)
586 {
587 	NODE *r = p->n_right;
588 
589 	if (r->n_lval >= 0 && r->n_lval <= 0777777) {
590 		printf("	idivi ");
591 		adrput(stdout, getlr(p, '1'));
592 		printf(",0%llo\n", r->n_lval);
593 	} else {
594 		printf("	idiv ");
595 		adrput(stdout, getlr(p, '1'));
596 		printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
597 	}
598 }
599 
600 /*
601  * move a constant into a register.
602  */
603 static void
xmovei(NODE * p)604 xmovei(NODE *p)
605 {
606 	/*
607 	 * Trick: If this is an unnamed constant, just move it directly,
608 	 * otherwise use xmovei to get section number.
609 	 */
610 	if (p->n_name[0] == '\0' || p->n_lval > 0777777) {
611 		printf("	");
612 		zzzcode(p, 'D');
613 		putchar(' ');
614 		adrput(stdout, getlr(p, '1'));
615 		putchar(',');
616 		zzzcode(p, 'E');
617 	} else {
618 		printf("	xmovei ");
619 		adrput(stdout, getlr(p, '1'));
620 		printf(",%s", p->n_name);
621 		if (p->n_lval != 0)
622 			printf("+0%llo", p->n_lval);
623 	}
624 	putchar('\n');
625 }
626 
627 static void
printcon(NODE * p)628 printcon(NODE *p)
629 {
630 	CONSZ cz;
631 
632 	p = p->n_left;
633 	if (p->n_lval >= 0700000000000LL) {
634 		/* converted to pointer in clocal() */
635 		conput(stdout, p);
636 		return;
637 	}
638 	if (p->n_lval == 0 && p->n_name[0] == '\0') {
639 		putchar('0');
640 		return;
641 	}
642 	if (BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR)
643 		cz = (p->n_lval/4) | ((p->n_lval & 3) << 30);
644 	else
645 		cz = (p->n_lval/2) | (((p->n_lval & 1) + 5) << 30);
646 	cz |= 0700000000000LL;
647 	printf("0%llo", cz);
648 	if (p->n_name[0] != '\0')
649 		printf("+%s", p->n_name);
650 }
651 
652 static void
putcond(NODE * p)653 putcond(NODE *p)
654 {
655 	char *c = 0; /* XXX gcc */
656 
657 	switch (p->n_op) {
658 	case EQ: c = "e"; break;
659 	case NE: c = "n"; break;
660 	case LE: c = "le"; break;
661 	case LT: c = "l"; break;
662 	case GT: c = "g"; break;
663 	case GE: c = "ge"; break;
664 	default:
665 		cerror("putcond");
666 	}
667 	printf("%s", c);
668 }
669 
670 void
zzzcode(NODE * p,int c)671 zzzcode(NODE *p, int c)
672 {
673 	NODE *l;
674 	CONSZ hval;
675 
676 	switch (c) {
677 	case 'A': /* ildb right arg */
678 		adrput(stdout, p->n_left->n_left);
679 		break;
680 
681 	case 'B': /* remove from stack after subroutine call */
682 		if (p->n_qual)
683 			printf("	subi %%17,0%o\n", p->n_qual);
684 		break;
685 
686 	case 'C':
687 		constput(p);
688 		break;
689 
690 	case 'D': /* Find out which type of const load insn to use */
691 		if (p->n_op != ICON)
692 			cerror("zzzcode not ICON");
693 		if (p->n_name[0] == '\0') {
694 			if ((p->n_lval <= 0777777) && (p->n_lval > 0))
695 				printf("movei");
696 			else if ((p->n_lval & 0777777) == 0)
697 				printf("hrlzi");
698 			else
699 				printf("move");
700 		} else
701 			printf("move");
702 		break;
703 
704 	case 'E': /* Print correct constant expression */
705 		if (p->n_name[0] == '\0') {
706 			if ((p->n_lval <= 0777777) && (p->n_lval > 0)){
707 				printf("0%llo", p->n_lval);
708 			} else if ((p->n_lval & 0777777) == 0) {
709 				printf("0%llo", p->n_lval >> 18);
710 			} else {
711 				if (p->n_lval < 0)
712 					printf("[ .long -0%llo]", -p->n_lval);
713 				else
714 					printf("[ .long 0%llo]", p->n_lval);
715 			}
716 		} else {
717 			if (p->n_lval == 0)
718 				printf("[ .long %s]", p->n_name);
719 			else
720 				printf("[ .long %s+0%llo]",
721 				    p->n_name, p->n_lval);
722 		}
723 		break;
724 
725 	case 'G': /* structure argument */
726 		printf("	addl %%17,0%o\n", p->n_stsize/(SZINT/SZCHAR));
727 		printf("	foo...\n");
728 		break;
729 
730 	case 'P':
731 		p = getlr(p, 'R');
732 		/* FALLTHROUGH */
733 	case 'O':
734 		/*
735 		 * Print long long expression.
736 		 */
737 		hval = gethval(p->n_lval);
738 		printf("[ .long 0%llo,0%llo", hval,
739 		    (p->n_lval & 0377777777777LL) | (hval & 0400000000000LL));
740 		if (p->n_name[0] != '\0')
741 			printf("+%s", p->n_name);
742 		printf(" ]");
743 		break;
744 
745 	case 'F': /* Print an "opsimp" instruction based on its const type */
746 		hopcode(oneinstr(p->n_right) ? 'C' : 'R', p->n_op);
747 		break;
748 
749 	case 'H': /* Print a small constant */
750 		p = p->n_right;
751 		printf("0%llo", p->n_lval & 0777777);
752 		break;
753 
754 	case 'Q': /* two-param long long comparisions */
755 		twollcomp(p);
756 		break;
757 
758 	case 'R': /* two-param conditionals */
759 		twocomp(p);
760 		break;
761 
762 	case 'U':
763 		emitshort(p);
764 		break;
765 
766 	case 'V':
767 		storeshort(p);
768 		break;
769 
770 	case 'Z':
771 		ptrcomp(p);
772 		break;
773 
774 	case 'a':
775 		imuli(p);
776 		break;
777 
778 	case 'b':
779 		idivi(p);
780 		break;
781 
782 	case 'c':
783 		xmovei(p);
784 		break;
785 
786 	case 'd':
787 		printcon(p);
788 		break;
789 
790 	case 'e':
791 		putcond(p);
792 		break;
793 
794 	case 'g':
795 		if (p->n_right->n_op != OREG || p->n_right->n_lval != 0)
796 			comperr("bad Zg oreg");
797 		printf("%s", rnames[p->n_right->n_rval]);
798 		break;
799 
800 #if 0
801 	case '1': /* double upput */
802 		p = getlr(p, '1');
803 		p->n_rval += 2;
804 		adrput(stdout, p);
805 		p->n_rval -= 2;
806 		break;
807 #endif
808 
809 	case 'i': /* Write instruction for short load from name */
810 		l = getlr(p, 'L');
811 		printf("	h%cr%c %s,%s+" CONFMT "\n",
812 		    l->n_lval & 1 ? 'r' : 'l',
813 		    ISUNSIGNED(p->n_type) ? 'z' : 'e',
814 		    rnames[getlr(p, '1')->n_rval],
815 		    l->n_name, l->n_lval >> 1);
816 		break;
817 
818 	default:
819 		cerror("zzzcode %c", c);
820 	}
821 }
822 
823 /* set up temporary registers */
824 void
setregs(void)825 setregs(void)
826 {
827 	fregs = 7;	/* 7 free regs on PDP10 (1-7) */
828 }
829 
830 /*ARGSUSED*/
831 int
rewfld(NODE * p)832 rewfld(NODE *p)
833 {
834 	return(1);
835 }
836 
837 int
fldexpand(NODE * p,int cookie,char ** cp)838 fldexpand(NODE *p, int cookie, char **cp)
839 {
840 	return 0;
841 }
842 
843 int
flshape(NODE * p)844 flshape(NODE *p)
845 {
846 	register int o = p->n_op;
847 
848 	return (o == REG || o == NAME || o == ICON ||
849 		(o == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)));
850 }
851 
852 /* INTEMP shapes must not contain any temporary registers */
853 int
shtemp(NODE * p)854 shtemp(NODE *p)
855 {
856 	return(0);
857 }
858 
859 int
shumul(NODE * p,int order)860 shumul(NODE *p, int order)
861 {
862 	register int o;
863 
864 	if (x2debug) {
865 		int val;
866 		printf("shumul(%p)\n", p);
867 		eprint(p, 0, &val, &val);
868 	}
869 
870 	o = p->n_op;
871 #if 0
872 	if (o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON)
873 		return(STARNM);
874 #endif
875 
876 #if 0
877 	if ((o == INCR) &&
878 	    (p->n_left->n_op == REG && p->n_right->n_op == ICON) &&
879 	    p->n_right->n_name[0] == '\0') {
880 		switch (p->n_type) {
881 			case CHAR|PTR:
882 			case UCHAR|PTR:
883 				o = 1;
884 				break;
885 
886 			case SHORT|PTR:
887 			case USHORT|PTR:
888 				o = 2;
889 				break;
890 
891 			case INT|PTR:
892 			case UNSIGNED|PTR:
893 			case LONG|PTR:
894 			case ULONG|PTR:
895 			case FLOAT|PTR:
896 				o = 4;
897 				break;
898 
899 			case DOUBLE|PTR:
900 			case LONGLONG|PTR:
901 			case ULONGLONG|PTR:
902 				o = 8;
903 				break;
904 
905 			default:
906 				if (ISPTR(p->n_type) &&
907 				     ISPTR(DECREF(p->n_type))) {
908 					o = 4;
909 					break;
910 				} else
911 					return(0);
912 		}
913 		return( 0);
914 	}
915 #endif
916 	return( SRNOPE );
917 }
918 
919 void
adrcon(CONSZ val)920 adrcon(CONSZ val)
921 {
922 	cerror("adrcon: val %llo\n", val);
923 }
924 
925 void
conput(FILE * fp,NODE * p)926 conput(FILE *fp, NODE *p)
927 {
928 	switch (p->n_op) {
929 	case ICON:
930 		if (p->n_lval != 0) {
931 			acon(fp, p);
932 			if (p->n_name[0] != '\0')
933 				fputc('+', fp);
934 		}
935 		if (p->n_name[0] != '\0')
936 			fprintf(fp, "%s", p->n_name);
937 		if (p->n_name[0] == '\0' && p->n_lval == 0)
938 			fputc('0', fp);
939 		return;
940 
941 	case REG:
942 		fprintf(fp, "%s", rnames[p->n_rval]);
943 		return;
944 
945 	default:
946 		cerror("illegal conput");
947 	}
948 }
949 
950 /*ARGSUSED*/
951 void
insput(NODE * p)952 insput(NODE *p)
953 {
954 	cerror("insput");
955 }
956 
957 /*
958  * Write out the upper address, like the upper register of a 2-register
959  * reference, or the next memory location.
960  */
961 void
upput(NODE * p,int size)962 upput(NODE *p, int size)
963 {
964 
965 	size /= SZLONG;
966 	switch (p->n_op) {
967 	case REG:
968 		printf("%s", rnames[p->n_rval + size]);
969 		break;
970 
971 	case NAME:
972 	case OREG:
973 		p->n_lval += size;
974 		adrput(stdout, p);
975 		p->n_lval -= size;
976 		break;
977 	case ICON:
978 		printf(CONFMT, p->n_lval >> (36 * size));
979 		break;
980 	default:
981 		cerror("upput bad op %d size %d", p->n_op, size);
982 	}
983 }
984 
985 void
adrput(FILE * fp,NODE * p)986 adrput(FILE *fp, NODE *p)
987 {
988 	int r;
989 	/* output an address, with offsets, from p */
990 
991 	if (p->n_op == FLD)
992 		p = p->n_left;
993 
994 	switch (p->n_op) {
995 
996 	case NAME:
997 		if (p->n_name[0] != '\0')
998 			fputs(p->n_name, fp);
999 		if (p->n_lval != 0)
1000 			fprintf(fp, "+" CONFMT, p->n_lval & 0777777777777LL);
1001 		return;
1002 
1003 	case OREG:
1004 		r = p->n_rval;
1005 #if 0
1006 		if (R2TEST(r)) { /* double indexing */
1007 			register int flags;
1008 
1009 			flags = R2UPK3(r);
1010 			if (flags & 1)
1011 				putc('*', fp);
1012 			if (flags & 4)
1013 				putc('-', fp);
1014 			if (p->n_lval != 0 || p->n_name[0] != '\0')
1015 				acon(p);
1016 			if (R2UPK1(r) != 100)
1017 				printf("(%s)", rnames[R2UPK1(r)]);
1018 			if (flags & 2)
1019 				putchar('+');
1020 			printf("[%s]", rnames[R2UPK2(r)]);
1021 			return;
1022 		}
1023 #endif
1024 		if (R2TEST(r))
1025 			cerror("adrput: unwanted double indexing: r %o", r);
1026 		if (p->n_rval != FPREG && p->n_lval < 0 && p->n_name[0]) {
1027 			fprintf(fp, "%s", p->n_name);
1028 			acon(fp, p);
1029 			fprintf(fp, "(%s)", rnames[p->n_rval]);
1030 			return;
1031 		}
1032 		if (p->n_lval < 0 && p->n_rval == FPREG && offarg) {
1033 			p->n_lval -= offarg-2; acon(fp, p); p->n_lval += offarg-2;
1034 		} else if (p->n_lval != 0)
1035 			acon(fp, p);
1036 		if (p->n_name[0] != '\0')
1037 			fprintf(fp, "%s%s", p->n_lval ? "+" : "", p->n_name);
1038 		if (p->n_lval > 0 && p->n_rval == FPREG && offlab)
1039 			fprintf(fp, "+" LABFMT, offlab);
1040 		if (p->n_lval < 0 && p->n_rval == FPREG && offarg)
1041 			fprintf(fp, "(017)");
1042 		else
1043 			fprintf(fp, "(%s)", rnames[p->n_rval]);
1044 		return;
1045 	case ICON:
1046 		/* addressable value of the constant */
1047 		if (p->n_lval > 0) {
1048 			acon(fp, p);
1049 			if (p->n_name[0] != '\0')
1050 				putc('+', fp);
1051 		}
1052 		if (p->n_name[0] != '\0')
1053 			fprintf(fp, "%s", p->n_name);
1054 		if (p->n_lval < 0)
1055 			acon(fp, p);
1056 		if (p->n_name[0] == '\0' && p->n_lval == 0)
1057 			putc('0', fp);
1058 		return;
1059 
1060 	case REG:
1061 		fputs(rnames[p->n_rval], fp);
1062 		return;
1063 
1064 	default:
1065 		cerror("illegal address, op %d", p->n_op);
1066 		return;
1067 
1068 	}
1069 }
1070 
1071 /*
1072  * print out a constant
1073  */
1074 void
acon(FILE * fp,NODE * p)1075 acon(FILE *fp, NODE *p)
1076 {
1077 	if (p->n_lval < 0 && p->n_lval > -0777777777777ULL)
1078 		fprintf(fp, "-" CONFMT, -p->n_lval);
1079 	else
1080 		fprintf(fp, CONFMT, p->n_lval);
1081 }
1082 
1083 /*   printf conditional and unconditional branches */
1084 void
cbgen(int o,int lab)1085 cbgen(int o,int lab)
1086 {
1087 }
1088 
1089 /*
1090  * Do some local optimizations that must be done after optim is called.
1091  */
1092 static void
optim2(NODE * p,void * arg)1093 optim2(NODE *p, void *arg)
1094 {
1095 	int op = p->n_op;
1096 	int m, ml;
1097 	NODE *l;
1098 
1099 	/* Remove redundant PCONV's */
1100 	if (op == PCONV) {
1101 		l = p->n_left;
1102 		m = BTYPE(p->n_type);
1103 		ml = BTYPE(l->n_type);
1104 		if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT ||
1105 		    m == DOUBLE || m == STRTY || m == UNIONTY ||
1106 		    m == UNSIGNED || m == ULONG || m == ULONGLONG) &&
1107 		    (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT ||
1108 		    ml == DOUBLE || ml == STRTY || ml == UNIONTY ||
1109 		    ml == UNSIGNED || ml == ULONG ||
1110 		    ml == ULONGLONG) && ISPTR(l->n_type)) {
1111 			*p = *l;
1112 			nfree(l);
1113 			op = p->n_op;
1114 		} else
1115 		if (ISPTR(DECREF(p->n_type)) &&
1116 		    (l->n_type == INCREF(STRTY))) {
1117 			*p = *l;
1118 			nfree(l);
1119 			op = p->n_op;
1120 		} else
1121 		if (ISPTR(DECREF(l->n_type)) &&
1122 		    (p->n_type == INCREF(INT) ||
1123 		    p->n_type == INCREF(STRTY) ||
1124 		    p->n_type == INCREF(UNSIGNED))) {
1125 			*p = *l;
1126 			nfree(l);
1127 			op = p->n_op;
1128 		}
1129 
1130 	}
1131 	/* Add constands, similar to the one in optim() */
1132 	if (op == PLUS && p->n_right->n_op == ICON) {
1133 		l = p->n_left;
1134 		if (l->n_op == PLUS && l->n_right->n_op == ICON &&
1135 		    (p->n_right->n_name[0] == '\0' ||
1136 		     l->n_right->n_name[0] == '\0')) {
1137 			l->n_right->n_lval += p->n_right->n_lval;
1138 			if (l->n_right->n_name[0] == '\0')
1139 				l->n_right->n_name = p->n_right->n_name;
1140 			nfree(p->n_right);
1141 			*p = *l;
1142 			nfree(l);
1143 		}
1144 	}
1145 
1146 	/* Convert "PTR undef" (void *) to "PTR uchar" */
1147 	/* XXX - should be done in MI code */
1148 	if (BTYPE(p->n_type) == VOID)
1149 		p->n_type = (p->n_type & ~BTMASK) | UCHAR;
1150 	if (op == ICON) {
1151 		if ((p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR))
1152 		    && p->n_lval == 0 && p->n_name[0] != '\0')
1153 			p->n_lval = 0700000000000LL;
1154 		if ((p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT))
1155 		    && p->n_lval == 0 && p->n_name[0] != '\0')
1156 			p->n_lval = 0750000000000LL;
1157 	}
1158 	if (op == MINUS) {
1159 		if ((p->n_left->n_type == (PTR|CHAR) ||
1160 		    p->n_left->n_type == (PTR|UCHAR)) &&
1161 		    (p->n_right->n_type == (PTR|CHAR) ||
1162 		    p->n_right->n_type == (PTR|UCHAR))) {
1163 			l = talloc();
1164 			l->n_op = SCONV;
1165 			l->n_type = INT;
1166 			l->n_left = p->n_right;
1167 			p->n_right = l;
1168 			l = talloc();
1169 			l->n_op = SCONV;
1170 			l->n_type = INT;
1171 			l->n_left = p->n_left;
1172 			p->n_left = l;
1173 		}
1174 	}
1175 }
1176 
1177 void
myreader(struct interpass * ipole)1178 myreader(struct interpass *ipole)
1179 {
1180 	struct interpass *ip;
1181 
1182 	DLIST_FOREACH(ip, ipole, qelem) {
1183 		if (ip->type != IP_NODE)
1184 			continue;
1185 		walkf(ip->ip_node, optim2, 0);
1186 	}
1187 
1188 	if (x2debug) {
1189 		printf("myreader final tree:\n");
1190 		printip(ipole);
1191 	}
1192 }
1193 
1194 /*
1195  * Remove some PCONVs after OREGs are created.
1196  */
1197 static void
pconv2(NODE * p,void * arg)1198 pconv2(NODE *p, void *arg)
1199 {
1200 	NODE *q;
1201 
1202 	if (p->n_op == PLUS) {
1203 		if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
1204 			if (p->n_right->n_op != ICON)
1205 				return;
1206 			if (p->n_left->n_op != PCONV)
1207 				return;
1208 			if (p->n_left->n_left->n_op != OREG)
1209 				return;
1210 			q = p->n_left->n_left;
1211 			nfree(p->n_left);
1212 			p->n_left = q;
1213 			/*
1214 			 * This will be converted to another OREG later.
1215 			 */
1216 		}
1217 	}
1218 }
1219 
1220 void
mycanon(NODE * p)1221 mycanon(NODE *p)
1222 {
1223 	walkf(p, pconv2, 0);
1224 }
1225 
1226 /*
1227  * Remove last goto.
1228  */
1229 void
myoptim(struct interpass * ip)1230 myoptim(struct interpass *ip)
1231 {
1232 }
1233 
1234 /*
1235  * Return a class suitable for a specific type.
1236  */
1237 int
gclass(TWORD t)1238 gclass(TWORD t)
1239 {
1240 	return (szty(t) == 2 ? CLASSB : CLASSA);
1241 }
1242 
1243 static int
argsiz(NODE * p)1244 argsiz(NODE *p)
1245 {
1246 	TWORD t = p->n_type;
1247 
1248 	if (t == STRTY || t == UNIONTY)
1249 		return p->n_stsize/(SZINT/SZCHAR);
1250 	return szty(t);
1251 }
1252 
1253 /*
1254  * Calculate argument sizes.
1255  */
1256 void
lastcall(NODE * p)1257 lastcall(NODE *p)
1258 {
1259         NODE *op = p;
1260         int size = 0;
1261 
1262         p->n_qual = 0;
1263         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1264                 return;
1265         for (p = p->n_right; p->n_op == CM; p = p->n_left)
1266 		if (p->n_right->n_op != ASSIGN)
1267                 	size += argsiz(p->n_right);
1268 	if (p->n_op != ASSIGN)
1269         	size += argsiz(p);
1270         op->n_qual = size; /* XXX */
1271 }
1272 
1273 void
rmove(int s,int d,TWORD t)1274 rmove(int s, int d, TWORD t)
1275 {
1276 	printf("	%smove %s,%s\n",
1277 	    (s > 017 ? "d" : ""), rnames[d], rnames[s]);
1278 }
1279 
1280 /*
1281  * For class c, find worst-case displacement of the number of
1282  * registers in the array r[] indexed by class.
1283  */
1284 int
COLORMAP(int c,int * r)1285 COLORMAP(int c, int *r)
1286 {
1287 	int num;
1288 
1289 	switch (c) {
1290 	case CLASSA:
1291 		/* there are 13 classa, so min 6 classb are needed to block */
1292 		num = r[CLASSB] * 2;
1293 		num += r[CLASSA];
1294 		return num < 13;
1295 	case CLASSB:
1296 		/* 7 classa may block all classb */
1297 		num = r[CLASSB] + r[CLASSA];
1298 		return num < 7;
1299 	}
1300 	comperr("COLORMAP");
1301 	return 0; /* XXX gcc */
1302 }
1303 
1304 /*
1305  * Target-dependent command-line options.
1306  */
1307 void
mflags(char * str)1308 mflags(char *str)
1309 {
1310 }
1311 
1312 /*
1313  * Do something target-dependent for xasm arguments.
1314  * Supposed to find target-specific constraints and rewrite them.
1315  */
1316 int
myxasm(struct interpass * ip,NODE * p)1317 myxasm(struct interpass *ip, NODE *p)
1318 {
1319 	return 0;
1320 }
1321