xref: /netbsd-src/external/bsd/pcc/dist/pcc/arch/pdp11/local2.c (revision 411dcbec990c8aa9c57d3bd2f4bcacadec0b1ab5)
1 /*	Id: local2.c,v 1.10 2015/06/29 18:49:36 ragge Exp 	*/
2 /*	$NetBSD: local2.c,v 1.1.1.3 2016/02/09 20:28:27 plunky Exp $	*/
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 # include "pass2.h"
29 # include <ctype.h>
30 # include <string.h>
31 
32 static int spcoff;
33 static int argsiz(NODE *p);
34 
35 void
deflab(int label)36 deflab(int label)
37 {
38 	printf(LABFMT ":\n", label);
39 }
40 
41 void
prologue(struct interpass_prolog * ipp)42 prologue(struct interpass_prolog *ipp)
43 {
44 	int addto;
45 
46 #ifdef LANG_F77
47 	if (ipp->ipp_vis)
48 		printf("	.globl %s\n", ipp->ipp_name);
49 	printf("%s:\n", ipp->ipp_name);
50 #endif
51 	printf("jsr	r5,csv\n");
52 	addto = p2maxautooff;
53 	if (addto >= AUTOINIT/SZCHAR)
54 		addto -= AUTOINIT/SZCHAR;
55 	if (addto & 1)
56 		addto++;
57 	if (addto == 2)
58 		printf("tst	-(sp)\n");
59 	else if (addto == 4)
60 		printf("cmp	-(sp),-(sp)\n");
61 	else if (addto > 4)
62 		printf("sub	$%o,sp\n", addto);
63 	spcoff = 0;
64 }
65 
66 void
eoftn(struct interpass_prolog * ipp)67 eoftn(struct interpass_prolog *ipp)
68 {
69 	if (spcoff)
70 		comperr("spcoff == %d", spcoff);
71 	if (ipp->ipp_ip.ip_lbl == 0)
72 		return; /* no code needs to be generated */
73 	printf("jmp	cret\n");
74 }
75 
76 /*
77  * add/sub/...
78  *
79  * Param given:
80  */
81 void
hopcode(int f,int o)82 hopcode(int f, int o)
83 {
84 	char *str;
85 
86 	switch (o) {
87 	case PLUS:
88 		str = "add";
89 		break;
90 	case MINUS:
91 		str = "sub";
92 		break;
93 	case AND:
94 		str = "and";
95 		break;
96 	case OR:
97 		str = "or";
98 		break;
99 	case ER:
100 		str = "xor";
101 		break;
102 	default:
103 		comperr("hopcode2: %d", o);
104 		str = 0; /* XXX gcc */
105 	}
106 	printf("%s%c", str, f);
107 }
108 
109 /*
110  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
111  */
112 int
tlen(p)113 tlen(p) NODE *p;
114 {
115 	switch(p->n_type) {
116 		case CHAR:
117 		case UCHAR:
118 			return(1);
119 
120 		case SHORT:
121 		case USHORT:
122 			return(SZSHORT/SZCHAR);
123 
124 		case DOUBLE:
125 			return(SZDOUBLE/SZCHAR);
126 
127 		case INT:
128 		case UNSIGNED:
129 		case LONG:
130 		case ULONG:
131 			return(SZINT/SZCHAR);
132 
133 		case LONGLONG:
134 		case ULONGLONG:
135 			return SZLONGLONG/SZCHAR;
136 
137 		default:
138 			if (!ISPTR(p->n_type))
139 				comperr("tlen type %d not pointer");
140 			return SZPOINT(p->n_type)/SZCHAR;
141 		}
142 }
143 
144 /*
145  * Emit code to compare two long numbers.
146  */
147 static void
twolcomp(NODE * p)148 twolcomp(NODE *p)
149 {
150 	int o = p->n_op;
151 	int s = getlab2();
152 	int e = p->n_label;
153 	int cb1, cb2;
154 
155 	if (o >= ULE)
156 		o -= (ULE-LE);
157 	switch (o) {
158 	case NE:
159 		cb1 = 0;
160 		cb2 = NE;
161 		break;
162 	case EQ:
163 		cb1 = NE;
164 		cb2 = 0;
165 		break;
166 	case LE:
167 	case LT:
168 		cb1 = GT;
169 		cb2 = LT;
170 		break;
171 	case GE:
172 	case GT:
173 		cb1 = LT;
174 		cb2 = GT;
175 		break;
176 
177 	default:
178 		cb1 = cb2 = 0; /* XXX gcc */
179 	}
180 	if (p->n_op >= ULE)
181 		cb1 += 2, cb2 += 2;
182 	expand(p, 0, "cmp	AR,AL\n");
183 	if (cb1) cbgen(cb1, s);
184 	if (cb2) cbgen(cb2, e);
185         expand(p, 0, "cmp	UR,UL\n");
186         cbgen(p->n_op, e);
187         deflab(s);
188 }
189 
190 
191 /*
192  * Generate compare code for long instructions when right node is 0.
193  */
194 static void
lcomp(NODE * p)195 lcomp(NODE *p)
196 {
197 	switch (p->n_op) {
198 	case EQ:
199 		expand(p, FORCC, "tst	AL\n");
200 		printf("jne	1f\n");
201 		expand(p, FORCC, "tst	UL\n");
202 		cbgen(EQ, p->n_label);
203 		printf("1:\n");
204 		break;
205 	case NE:
206 		expand(p, FORCC, "tst	AL\n");
207 		cbgen(NE, p->n_label);
208 		expand(p, FORCC, "tst	UL\n");
209 		cbgen(NE, p->n_label);
210 		break;
211 	case GE:
212 		expand(p, FORCC, "tst	AL\n");
213 		cbgen(GE, p->n_label);
214 		break;
215 	default:
216 		comperr("lcomp %p", p);
217 	}
218 }
219 
220 void
zzzcode(NODE * p,int c)221 zzzcode(NODE *p, int c)
222 {
223 	switch (c) {
224 	case 'A': /* print out - if not first arg */
225 		if (spcoff || (p->n_type == FLOAT || p->n_type == DOUBLE))
226 			printf("-");
227 		spcoff += argsiz(p);
228 		break;
229 
230 	case 'B': /* arg is pointer to block */
231 		expand(p->n_left, FOREFF, "mov	AL,ZA(sp)\n");
232 		expand(p->n_left, FOREFF, "sub	CR,(sp)\n");
233 		break;
234 
235 	case 'C': /* subtract stack after call */
236 		spcoff -= p->n_qual;
237 		if (spcoff == 0 /* && !(p->n_flags & NLOCAL1) XXX FIXME */)
238 			p->n_qual -= 2;
239 		if (p->n_qual == 2)
240 			printf("tst	(sp)+\n");
241 		else if (p->n_qual == 4)
242 			printf("cmp	(sp)+,(sp)+\n");
243 		else if (p->n_qual > 2)
244 			printf("add	$%o,sp\n", (int)p->n_qual);
245 		break;
246 
247 	case 'D': /* long comparisions */
248 		lcomp(p);
249 		break;
250 
251 	case 'E': /* long move */
252 		rmove(p->n_right->n_reg, p->n_left->n_reg, p->n_type);
253 		break;
254 
255 	case 'F': /* long comparision */
256 		twolcomp(p);
257 		break;
258 
259 	case 'G': /* printout a subnode for post-inc */
260 		adrput(stdout, p->n_left->n_left);
261 		break;
262 
263 	case 'H': /* arg with post-inc */
264 		expand(p->n_left->n_left, FOREFF, "mov	AL,ZA(sp)\n");
265 		expand(p->n_left->n_left, FOREFF, "inc	AL\n");
266 		break;
267 
268 	case 'Q': /* struct assignment, no rv */
269 		printf("mov	$%o,", attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0)/2);
270 		expand(p, INAREG, "A1\n");
271 		printf("1:\n");
272 		expand(p, INAREG, "mov	(AR)+,(AL)+\n");
273 		expand(p, INAREG, "dec	A1\n");
274 		printf("jne	1b\n");
275 		break;
276 
277 	case 'R': /* struct assignment with rv */
278 		printf("mov	$%o,", attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0)/2);
279 		expand(p, INAREG, "A1\n");
280 		expand(p, INAREG, "mov	AR,A2\n");
281 		printf("1:\n");
282 		expand(p, INAREG, "mov	(A2)+,(AL)+\n");
283 		expand(p, INAREG, "dec	A1\n");
284 		printf("jne	1b\n");
285 		break;
286 
287 	case '1': /* lower part of double regs */
288 		p = getlr(p, '1');
289 		printf("r%c", rnames[p->n_rval][1]);
290 		break;
291 
292 	default:
293 		comperr("zzzcode %c", c);
294 	}
295 }
296 
297 /*ARGSUSED*/
298 int
rewfld(NODE * p)299 rewfld(NODE *p)
300 {
301 	return(1);
302 }
303 
304 int canaddr(NODE *);
305 int
canaddr(NODE * p)306 canaddr(NODE *p)
307 {
308 	int o = p->n_op;
309 
310 	if (o==NAME || o==REG || o==ICON || o==OREG ||
311 	    (o==UMUL && shumul(p->n_left, STARNM|SOREG)))
312 		return(1);
313 	return(0);
314 }
315 
316 /*
317  * Does the bitfield shape match?
318  */
319 int
flshape(NODE * p)320 flshape(NODE *p)
321 {
322 	int o = p->n_op;
323 
324 	if (o == OREG || o == REG || o == NAME)
325 		return SRDIR; /* Direct match */
326 	if (o == UMUL && shumul(p->n_left, SOREG))
327 		return SROREG; /* Convert into oreg */
328 	return SRREG; /* put it into a register */
329 }
330 
331 /* INTEMP shapes must not contain any temporary registers */
332 /* XXX should this go away now? */
333 int
shtemp(NODE * p)334 shtemp(NODE *p)
335 {
336 	return 0;
337 #if 0
338 	int r;
339 
340 	if (p->n_op == STARG )
341 		p = p->n_left;
342 
343 	switch (p->n_op) {
344 	case REG:
345 		return (!istreg(p->n_rval));
346 
347 	case OREG:
348 		r = p->n_rval;
349 		if (R2TEST(r)) {
350 			if (istreg(R2UPK1(r)))
351 				return(0);
352 			r = R2UPK2(r);
353 		}
354 		return (!istreg(r));
355 
356 	case UMUL:
357 		p = p->n_left;
358 		return (p->n_op != UMUL && shtemp(p));
359 	}
360 
361 	if (optype(p->n_op) != LTYPE)
362 		return(0);
363 	return(1);
364 #endif
365 }
366 
367 static void
negcon(FILE * fp,int con)368 negcon(FILE *fp, int con)
369 {
370 	if (con < 0)
371 		fprintf(fp, "-"), con = -con;
372 	fprintf(fp, "%o", con & 0177777);
373 }
374 
375 void
adrcon(CONSZ val)376 adrcon(CONSZ val)
377 {
378 	printf("$" CONFMT, val);
379 }
380 
381 void
conput(FILE * fp,NODE * p)382 conput(FILE *fp, NODE *p)
383 {
384 	int val = p->n_lval;
385 
386 	switch (p->n_op) {
387 	case ICON:
388 		printf("$");
389 		if (p->n_name[0] != '\0') {
390 			fprintf(fp, "%s", p->n_name);
391 			if (val)
392 				fprintf(fp, "+%o", val & 0177777);
393 		} else if (p->n_type == LONG || p->n_type == ULONG)
394 			negcon(fp, val >> 16);
395 		else
396 			negcon(fp, val);
397 		return;
398 
399 	default:
400 		comperr("illegal conput, p %p", p);
401 	}
402 }
403 
404 /*ARGSUSED*/
405 void
insput(NODE * p)406 insput(NODE *p)
407 {
408 	comperr("insput");
409 }
410 
411 /*
412  * Write out the upper address, like the upper register of a 2-register
413  * reference, or the next memory location.
414  */
415 void
upput(NODE * p,int size)416 upput(NODE *p, int size)
417 {
418 	size /= SZINT;
419 	switch (p->n_op) {
420 	case NAME:
421 	case OREG:
422 		p->n_lval += size;
423 		adrput(stdout, p);
424 		p->n_lval -= size;
425 		break;
426 	case REG:
427 		printf("r%c", rnames[p->n_rval][2]);
428 		break;
429 	case ICON:
430 		/* On PDP11 upper value is low 16 bits */
431 		printf("$");
432 		negcon(stdout, p->n_lval & 0177777);
433 		break;
434 	default:
435 		comperr("upput bad op %d size %d", p->n_op, size);
436 	}
437 }
438 
439 /*
440  * output an address, with offsets, from p
441  */
442 void
adrput(FILE * io,NODE * p)443 adrput(FILE *io, NODE *p)
444 {
445 	int r;
446 
447 	if (p->n_op == FLD)
448 		p = p->n_left;
449 
450 	switch (p->n_op) {
451 	case NAME:
452 		if (p->n_name[0] != '\0') {
453 			fputs(p->n_name, io);
454 			if (p->n_lval != 0)
455 				fprintf(io, "+%o", (int)(p->n_lval&0177777));
456 		} else
457 			negcon(io, p->n_lval);
458 		return;
459 
460 	case OREG:
461 		r = p->n_rval;
462 		if (p->n_name[0])
463 			printf("%s%s", p->n_name, p->n_lval ? "+" : "");
464 		if (R2TEST(r) && R2UPK3(r) == 0)
465 			printf("*");
466 		if (p->n_lval)
467 			negcon(io, p->n_lval);
468 		if (R2TEST(r)) {
469 			fprintf(io, "(%s)", rnames[R2UPK1(r)]);
470 			if (R2UPK3(r) == 1)
471 				fprintf(io, "+");
472 		} else
473 			fprintf(io, "(%s)", rnames[p->n_rval]);
474 		return;
475 	case ICON:
476 		/* addressable value of the constant */
477 		conput(io, p);
478 		return;
479 
480 	case REG:
481 		switch (p->n_type) {
482 		case LONG:
483 		case ULONG:
484 			fprintf(io, "r%c", rnames[p->n_rval][1]);
485 			break;
486 		default:
487 			fprintf(io, "%s", rnames[p->n_rval]);
488 		}
489 		return;
490 
491 	case UMUL:
492 		if (tshape(p, STARNM)) {
493 			printf("*");
494 			adrput(io, p->n_left);
495 			break;
496 		}
497 		/* FALLTHROUGH */
498 	default:
499 		comperr("illegal address, op %d, node %p", p->n_op, p);
500 		return;
501 
502 	}
503 }
504 
505 static char *
506 ccbranches[] = {
507 	"jeq",		/* jumpe */
508 	"jne",		/* jumpn */
509 	"jle",		/* jumple */
510 	"jlt",		/* jumpl */
511 	"jge",		/* jumpge */
512 	"jgt",		/* jumpg */
513 	"jlos",		/* jumple (jlequ) */
514 	"jlo",		/* jumpl (jlssu) */
515 	"jhis",		/* jumpge (jgequ) */
516 	"jhi",		/* jumpg (jgtru) */
517 };
518 
519 
520 /*   printf conditional and unconditional branches */
521 void
cbgen(int o,int lab)522 cbgen(int o, int lab)
523 {
524 	if (o < EQ || o > UGT)
525 		comperr("bad conditional branch: %s", opst[o]);
526 	printf("%s	" LABFMT "\n", ccbranches[o-EQ], lab);
527 }
528 
529 #define	IS1CON(p) ((p)->n_op == ICON && (p)->n_lval == 1)
530 
531 /*
532  * Move postfix operators to the next statement, unless they are
533  * within a function call or a branch.
534  */
535 static void
cvtree(NODE * p,struct interpass * ip2)536 cvtree(NODE *p, struct interpass *ip2)
537 {
538 	struct interpass *ip;
539 	NODE *q;
540 
541 	if (callop(p->n_op) || p->n_op == CBRANCH)
542 		return;
543 
544 	if ((p->n_op == PLUS || p->n_op == MINUS) &&
545 	    IS1CON(p->n_right) && (q = p->n_left)->n_op == ASSIGN &&
546 	    treecmp(q->n_left, q->n_right->n_left) &&
547 	    IS1CON(q->n_right->n_right)) {
548 		if ((p->n_op == PLUS && q->n_right->n_op == MINUS) ||
549 		    (p->n_op == MINUS && q->n_right->n_op == PLUS)) {
550 			nfree(p->n_right);
551 			*p = *q->n_left;
552 			if (optype(p->n_op) != LTYPE)
553 				p->n_left = tcopy(p->n_left);
554 			ip = ipnode(q);
555 			DLIST_INSERT_AFTER(ip2, ip, qelem);
556 			return;
557 		}
558 	}
559 	if (optype(p->n_op) == BITYPE)
560 		cvtree(p->n_right, ip2);
561 	if (optype(p->n_op) != LTYPE)
562 		cvtree(p->n_left, ip2);
563 }
564 
565 /*
566  * Convert AND to BIC.
567  */
568 static void
fixops(NODE * p,void * arg)569 fixops(NODE *p, void *arg)
570 {
571 	static int fltwritten;
572 
573 	if (!fltwritten && (p->n_type == FLOAT || p->n_type == DOUBLE)) {
574 		printf(".globl	fltused\n");
575 		fltwritten = 1;
576 	}
577 	switch (p->n_op) {
578 	case AND:
579 		if (p->n_right->n_op == ICON) {
580 			p->n_right->n_lval = ((~p->n_right->n_lval) & 0177777);
581 		} else if (p->n_right->n_op == COMPL) {
582 			NODE *q = p->n_right->n_left;
583 			nfree(p->n_right);
584 			p->n_right = q;
585 		} else
586 			p->n_right = mkunode(COMPL, p->n_right, 0, p->n_type);
587 		break;
588 	case RS:
589 		p->n_right = mkunode(UMINUS, p->n_right, 0, p->n_right->n_type);
590 		p->n_op = LS;
591 		break;
592 	case EQ:
593 	case NE: /* Hack not to clear bits if FORCC */
594 		if (p->n_left->n_op == AND)
595 			fixops(p->n_left, 0); /* Convert an extra time */
596 		break;
597 	}
598 }
599 
600 void
myreader(struct interpass * ipole)601 myreader(struct interpass *ipole)
602 {
603 	struct interpass *ip;
604 
605 #ifdef PCC_DEBUG
606 	if (x2debug) {
607 		printf("myreader before\n");
608 		printip(ipole);
609 	}
610 #endif
611 	DLIST_FOREACH(ip, ipole, qelem) {
612 		if (ip->type != IP_NODE)
613 			continue;
614 		walkf(ip->ip_node, fixops, 0);
615 		canon(ip->ip_node); /* call it early */
616 	}
617 #ifdef PCC_DEBUG
618 	if (x2debug) {
619 		printf("myreader middle\n");
620 		printip(ipole);
621 	}
622 #endif
623 	DLIST_FOREACH(ip, ipole, qelem) {
624 		if (ip->type == IP_NODE)
625 			cvtree(ip->ip_node, ip);
626 	}
627 #ifdef PCC_DEBUG
628 	if (x2debug) {
629 		printf("myreader after\n");
630 		printip(ipole);
631 	}
632 #endif
633 }
634 
635 /*
636  * Remove SCONVs where the left node is an OREG with a smaller type.
637  */
638 static void
delsconv(NODE * p,void * arg)639 delsconv(NODE *p, void *arg)
640 {
641 #if 0
642 	NODE *l;
643 
644 	if (p->n_op != SCONV || (l = p->n_left)->n_op != OREG)
645 		return;
646 	if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == LONG) {
647 		p->n_op = OREG;
648 		p->n_lval = l->n_lval; /* high word */
649 		p->n_rval = l->n_rval;
650 		nfree(l);
651 	}
652 #endif
653 	/* Could do this for char etc. also */
654 }
655 
656 void
mycanon(NODE * p)657 mycanon(NODE *p)
658 {
659 	walkf(p, delsconv, 0);
660 }
661 
662 void
myoptim(struct interpass * ip)663 myoptim(struct interpass *ip)
664 {
665 }
666 
667 void
rmove(int s,int d,TWORD t)668 rmove(int s, int d, TWORD t)
669 {
670 	if (t < LONG || t > BTMASK) {
671 		printf("mov%s	%s,%s\n", t < SHORT ? "b" : "",
672 		    rnames[s],rnames[d]); /* XXX char should be full reg? */
673 	} else if (t == LONG || t == ULONG) {
674 		/* avoid trashing double regs */
675 		if (d > s)
676 			printf("mov     r%c,r%c\nmov    r%c,r%c\n",
677 			    rnames[s][2],rnames[d][2],
678 			    rnames[s][1],rnames[d][1]);
679 		else
680 			printf("mov	r%c,r%c\nmov	r%c,r%c\n",
681 			    rnames[s][1],rnames[d][1],
682 			    rnames[s][2],rnames[d][2]);
683 	} else if (t == FLOAT || t == DOUBLE) {
684 		printf("movf	%s,%s\n", rnames[s],rnames[d]);
685 	} else
686 		comperr("bad float rmove: %d %d %x", s, d, t);
687 
688 }
689 
690 /*
691  * For class c, find worst-case displacement of the number of
692  * registers in the array r[] indexed by class.
693  */
694 int
COLORMAP(int c,int * r)695 COLORMAP(int c, int *r)
696 {
697 	switch (c) {
698 	case CLASSA:
699 		return (r[CLASSB] * 2 + r[CLASSA]) < 5;
700 	case CLASSB:
701 		if (r[CLASSB] > 1) return 0;
702 		if (r[CLASSB] == 1 && r[CLASSA] > 0) return 0;
703 		if (r[CLASSA] > 2) return 0;
704 		return 1;
705 	case CLASSC:
706 		return r[CLASSC] < 8;
707 	}
708 	return 0;
709 }
710 
711 char *rnames[] = {
712 	"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc",
713 	"r01", "r12", "r23", "r34", "XXX", "XXX", "XXX", "XXX",
714 	"fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "XXX", "XXX",
715 };
716 
717 /*
718  * Return a class suitable for a specific type.
719  */
720 int
gclass(TWORD t)721 gclass(TWORD t)
722 {
723 	if (t < LONG || t > BTMASK)
724 		return CLASSA;
725 	if (t == LONG || t == ULONG)
726 		return CLASSB;
727 	if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
728 		return CLASSC;
729 	comperr("gclass");
730 	return CLASSD;
731 }
732 
733 static int
argsiz(NODE * p)734 argsiz(NODE *p)
735 {
736 	TWORD t = p->n_type;
737 
738 	if (t == LONG || t == ULONG || t == FLOAT)
739 		return 4;
740 	if (t == DOUBLE)
741 		return 8;
742 	if (t == STRTY || t == UNIONTY)
743 		return attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
744 	return 2;
745 }
746 
747 /*
748  * Argument specialties.
749  */
750 void
lastcall(NODE * p)751 lastcall(NODE *p)
752 {
753 	NODE *op = p;
754 	int size = 0;
755 
756 	/*
757 	 * Calculate arg sizes.
758 	 * Mark first arg not to have - before it.
759 	 */
760 	p->n_qual = 0;
761 	if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
762 		return;
763 	for (p = p->n_right; p->n_op == CM; p = p->n_left) {
764 		p->n_right->n_qual = 0;
765 		size += argsiz(p->n_right);
766 	}
767 	p->n_qual = 0;
768 	size += argsiz(p);
769 	p = op->n_right;
770 
771 	if (p->n_op == CM)
772 		p = p->n_right;
773 #if 0 /* XXX fixme */
774 	if (p->n_type == FLOAT || p->n_type == DOUBLE ||
775 	    p->n_type == STRTY || p->n_type == UNIONTY)
776 		op->n_flags |= NLOCAL1;	/* Does not use stack slot */
777 	else
778 		op->n_flags &= ~NLOCAL1;
779 #endif
780 	op->n_qual = size; /* XXX */
781 }
782 
783 static int
is1con(NODE * p)784 is1con(NODE *p)
785 {
786 	if (p->n_op == ICON && p->n_lval == 1)
787 		return 1;
788 	return 0;
789 }
790 
791 /*
792  * Special shapes.
793  */
794 int
special(NODE * p,int shape)795 special(NODE *p, int shape)
796 {
797 	CONSZ s;
798 
799 	switch (shape) {
800 	case SANDSCON:
801 		s = ~p->n_lval;
802 		if (s < 65536 || s > -65537)
803 			return SRDIR;
804 		break;
805 	case SINCB: /* Check if subject for post-inc */
806 		if (p->n_op == ASSIGN && p->n_right->n_op == PLUS &&
807 		    treecmp(p->n_left, p->n_right->n_left) &&
808 		    is1con(p->n_right->n_right))
809 			return SRDIR;
810 		break;
811 	case SARGSUB:
812 		if (p->n_op == MINUS && p->n_right->n_op == ICON &&
813 		    p->n_left->n_op == REG)
814 			return SRDIR;
815 		break;
816 	case SARGINC:
817 		if (p->n_op == MINUS && is1con(p->n_right))
818 			return special(p->n_left, SINCB);
819 		break;
820 	}
821 	return SRNOPE;
822 }
823 
824 /*
825  * Target-dependent command-line options.
826  */
827 void
mflags(char * str)828 mflags(char *str)
829 {
830 }
831 
832 /*
833  * Do something target-dependent for xasm arguments.
834  */
835 int
myxasm(struct interpass * ip,NODE * p)836 myxasm(struct interpass *ip, NODE *p)
837 {
838 	return 0;
839 }
840 
841 int
fldexpand(NODE * p,int cookie,char ** cp)842 fldexpand(NODE *p, int cookie, char **cp)
843 {
844 	return 0;
845 }
846 
847