1/*	Id: local2.c,v 1.30 2011/06/05 08:54:42 plunky Exp 	*/
2/*	$NetBSD$	*/
3
4/*
5 * Copyright (c) 2007 Michael Shalayeff
6 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33# include "pass2.h"
34# include <ctype.h>
35# include <string.h>
36
37void acon(NODE *p);
38void prtprolog(struct interpass_prolog *, int);
39int countargs(NODE *p, int *);
40void fixcalls(NODE *p, void *);
41
42static int stkpos;
43int p2calls;
44
45static const int rl[] =
46  { R0, R1, R1, R1, R1, R1, R31, R31, R31, R31,
47    R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18,
48    T1, T4, T3, T2, ARG3, ARG1, RET1 };
49static const int rh[] =
50  { R0, R31, T4, T3, T2, T1, T4, T3, T2, T1,
51    R18, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17,
52    T4, T3, T2, T1, ARG2, ARG0, RET0 };
53
54void
55deflab(int label)
56{
57	printf("\t.label\t" LABFMT "\n", label);
58}
59
60static int regoff[MAXREGS];
61static TWORD ftype;
62
63/*
64 * Print out the prolog assembler.
65 * addto and regoff are already calculated.
66 */
67void
68prtprolog(struct interpass_prolog *ipp, int addto)
69{
70	int i;
71
72	/* if this functions calls nothing -- no frame is needed */
73	if (p2calls || p2maxautooff > 4) {
74		printf("\tcopy\t%%r3,%%r1\n\tcopy\t%%sp,%%r3\n");
75		if (addto < 0x2000)
76			printf("\tstw,ma\t%%r1,%d(%%sp)\n", addto);
77		else if (addto < 0x802000)
78			printf("\tstw,ma\t%%r1,8192(%%sp)\n"
79			    "\taddil\t%d-8192,%%sp\n"
80			    "\tcopy\t%%r1,%%sp\n", addto);
81		else
82			comperr("too much local allocation");
83		if (p2calls)
84			printf("\tstw\t%%rp,-20(%%r3)\n");
85	}
86
87	for (i = 0; i < MAXREGS; i++)
88		if (TESTBIT(ipp->ipp_regs, i)) {
89			if (i <= R31)
90				printf("\tstw\t%s,%d(%%r3)\n",
91				    rnames[i], regoff[i]);
92			else if (i <= RETD0)
93				printf("\tstw\t%s,%d(%%r3)\n"
94				    "\tstw\t%s,%d(%%r3)\n",
95				    rnames[rl[i - RD0]], regoff[i] + 0,
96				    rnames[rh[i - RD0]], regoff[i] + 4);
97			else if (i <= FR31)
98				printf("\tfstws\t%s,%d(%%r3)\n",
99				    rnames[i], regoff[i]);
100			else
101				printf("\tfstds\t%s,%d(%%r3)\n",
102				    rnames[i], regoff[i]);
103		}
104}
105
106/*
107 * calculate stack size and offsets
108 */
109static int
110offcalc(struct interpass_prolog *ipp)
111{
112	int i, addto, off;
113
114	addto = 32;
115	if (p2calls) {
116		i = p2calls - 1;
117		/* round up to 4 args */
118		if (i < 4)
119			i = 4;
120		addto += i * 4;
121	}
122
123	for (off = 4, i = 0; i < MAXREGS; i++)
124		if (TESTBIT(ipp->ipp_regs, i)) {
125			regoff[i] = off;
126			off += szty(PERMTYPE(i)) * SZINT/SZCHAR;
127		}
128	addto += off + p2maxautooff;
129	return (addto + 63) & ~63;
130}
131
132void
133prologue(struct interpass_prolog *ipp)
134{
135	int addto;
136
137	ftype = ipp->ipp_type;
138
139	/*
140	 * We here know what registers to save and how much to
141	 * add to the stack.
142	 */
143	addto = offcalc(ipp);
144	printf("\t.proc\ncallinfo frame=%d, save_rp, save_sp\n\t.entry\n",
145	    addto);
146	prtprolog(ipp, addto);
147}
148
149void
150eoftn(struct interpass_prolog *ipp)
151{
152	int i;
153
154	if (ipp->ipp_ip.ip_lbl == 0)
155		return; /* no code needs to be generated */
156
157	/* return from function code */
158	for (i = 0; i < MAXREGS; i++)
159		if (TESTBIT(ipp->ipp_regs, i)) {
160			if (i <= R31)
161				printf("\tldw\t%d(%%r3),%s\n",
162				    regoff[i], rnames[i]);
163			else if (i <= RETD0)
164				printf("\tldw\t%d(%%r3),%s\n"
165				    "\tldw\t%d(%%r3),%s\n",
166				    regoff[i] + 0, rnames[rl[i - RD0]],
167				    regoff[i] + 4, rnames[rh[i - RD0]]);
168			else if (i <= FR31)
169				printf("\tfldws\t%d(%%r3),%s\n",
170				    regoff[i], rnames[i]);
171			else
172				printf("\tfldds\t%d(%%r3),%s\n",
173				    regoff[i], rnames[i]);
174		}
175
176	if (p2calls || p2maxautooff > 4) {
177		if (p2calls)
178			printf("\tldw\t-20(%%r3),%%rp\n");
179		printf("\tcopy\t%%r3,%%r1\n"
180		    "\tldw\t0(%%r3),%%r3\n"
181		    "\tbv\t%%r0(%%rp)\n"
182		    "\tcopy\t%%r1,%%sp\n");
183	} else
184		printf("\tbv\t%%r0(%%rp)\n\tnop\n");
185
186	printf("\t.exit\n\t.procend\n\t.size\t%s, .-%s\n",
187	    ipp->ipp_name, ipp->ipp_name);
188}
189
190/*
191 * add/sub/...
192 *
193 * Param given:
194 */
195void
196hopcode(int f, int o)
197{
198	char *str;
199
200	switch (o) {
201	case PLUS:
202		str = "add";
203		break;
204	case MINUS:
205		str = "sub";
206		break;
207	case AND:
208		str = "and";
209		break;
210	case OR:
211		str = "or";
212		break;
213	case ER:
214		str = "xor";
215		break;
216	case EQ:
217		str = "=";
218		break;
219	case NE:
220		str = "<>";
221		break;
222	case LE:
223		str = "<";
224		break;
225	case LT:
226		str = "<=";
227		break;
228	case ULE:
229		str = "<<";
230		break;
231	case ULT:
232		str = "<<=";
233		break;
234	case GE:
235		str = ">=";
236		break;
237	case GT:
238		str = ">";
239		break;
240	case UGE:
241		str = ">>";
242		break;
243	case UGT:
244		str = ">>=";
245		break;
246	default:
247		comperr("hopcode2: %d", o);
248		str = 0; /* XXX gcc */
249	}
250	printf("%s%c", str, f);
251}
252
253/*
254 * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
255 */
256int
257tlen(p) NODE *p;
258{
259	switch(p->n_type) {
260		case CHAR:
261		case UCHAR:
262			return(1);
263
264		case SHORT:
265		case USHORT:
266			return(SZSHORT/SZCHAR);
267
268		case FLOAT:
269			return(SZFLOAT/SZCHAR);
270
271		case DOUBLE:
272			return(SZDOUBLE/SZCHAR);
273
274		case INT:
275		case UNSIGNED:
276		case LONG:
277		case ULONG:
278			return(SZINT/SZCHAR);
279
280		case LONGLONG:
281		case ULONGLONG:
282			return SZLONGLONG/SZCHAR;
283
284		default:
285			if (!ISPTR(p->n_type))
286				comperr("tlen type %d not pointer", p->n_type);
287			return SZPOINT(p->n_type)/SZCHAR;
288		}
289}
290
291static int
292argsiz(NODE *p)
293{
294	NODE *q;
295	TWORD t = p->n_type;
296
297	if (t < LONGLONG || t == FLOAT || t > BTMASK)
298		return 4;
299	if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
300		return 8;
301	if (t == LDOUBLE)
302		return 8;	/* LDOUBLE is 16 */
303	if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == STARG)
304		return 4 + p->n_right->n_stsize;
305        /* perhaps it's down there somewhere -- let me take another look! */
306	if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == CALL) {
307		q = p->n_right->n_right->n_left->n_left->n_right;
308		if (q->n_op == STARG)
309			return 4 + q->n_stsize;
310	}
311	comperr("argsiz %p", p);
312	return 0;
313}
314
315/*
316 * Emit code to compare two longlong numbers.
317 */
318static void
319twollcomp(NODE *p)
320{
321	int o = p->n_op;
322	int s = getlab2();
323	int e = p->n_label;
324	int cb1, cb2;
325
326	if (o >= ULE)
327		o -= (ULE-LE);
328	switch (o) {
329	case NE:
330		cb1 = 0;
331		cb2 = NE;
332		break;
333	case EQ:
334		cb1 = NE;
335		cb2 = 0;
336		break;
337	case LE:
338	case LT:
339		cb1 = GT;
340		cb2 = LT;
341		break;
342	case GE:
343	case GT:
344		cb1 = LT;
345		cb2 = GT;
346		break;
347
348	default:
349		cb1 = cb2 = 0; /* XXX gcc */
350	}
351	if (p->n_op >= ULE)
352		cb1 += 4, cb2 += 4;
353	if (cb1) {
354		p->n_op = cb1;
355		p->n_label = s;
356		expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
357		p->n_label = e;
358		p->n_op = o;
359	}
360	if (cb2) {
361		p->n_op = cb2;
362		expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
363		p->n_op = o;
364	}
365	expand(p, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n");
366	deflab(s);
367}
368
369void
370zzzcode(NODE *p, int c)
371{
372	int n;
373
374	switch (c) {
375
376	case 'C':	/* after-call fixup */
377		n = p->n_qual;	/* args */
378		break;
379
380	case 'P':	/* returning struct-call setup */
381		n = p->n_qual;	/* args */
382		break;
383
384	case 'D':	/* Long long comparision */
385		twollcomp(p);
386		break;
387
388	case 'F':	/* struct as an arg */
389
390	default:
391		comperr("zzzcode %c", c);
392	}
393}
394
395int canaddr(NODE *);
396int
397canaddr(NODE *p)
398{
399	int o = p->n_op;
400
401	if (o == NAME || o == REG || o == ICON || o == OREG ||
402	    (o == UMUL && shumul(p->n_left, SOREG)))
403		return(1);
404	return(0);
405}
406
407int
408fldexpand(NODE *p, int cookie, char **cp)
409{
410	return 0;
411}
412
413/*
414 * Does the bitfield shape match?
415 */
416int
417flshape(NODE *p)
418{
419	if (isreg(p))
420		return SRDIR; /* Direct match */
421
422	return SRREG; /* put it into a register */
423}
424
425/* INTEMP shapes must not contain any temporary registers */
426/* XXX should this go away now? */
427int
428shtemp(NODE *p)
429{
430	return 0;
431#if 0
432	int r;
433
434	if (p->n_op == STARG )
435		p = p->n_left;
436
437	switch (p->n_op) {
438	case REG:
439		return (!istreg(p->n_rval));
440
441	case OREG:
442		r = p->n_rval;
443		if (R2TEST(r)) {
444			if (istreg(R2UPK1(r)))
445				return(0);
446			r = R2UPK2(r);
447		}
448		return (!istreg(r));
449
450	case UMUL:
451		p = p->n_left;
452		return (p->n_op != UMUL && shtemp(p));
453	}
454
455	if (optype(p->n_op) != LTYPE)
456		return(0);
457	return(1);
458#endif
459}
460
461void
462adrcon(CONSZ val)
463{
464	/* fix for L% and R% */
465	printf(CONFMT, val);
466}
467
468void
469conput(FILE *fp, NODE *p)
470{
471	CONSZ val = p->n_lval;
472
473	switch (p->n_op) {
474	case ICON:
475		if (p->n_name[0] != '\0') {
476			fprintf(fp, "RR'%s-$global$", p->n_name);
477			if (val)
478				fprintf(fp, "+" CONFMT, val);
479		} else
480			fprintf(fp, CONFMT, val);
481		return;
482
483	default:
484		comperr("illegal conput, p %p", p);
485	}
486}
487
488/*ARGSUSED*/
489void
490insput(NODE *p)
491{
492	comperr("insput");
493}
494
495/*
496 * Write out the upper address, like the upper register of a 2-register
497 * reference, or the next memory location.
498 */
499void
500upput(NODE *p, int size)
501{
502
503	size /= SZCHAR;
504	switch (p->n_op) {
505	case REG:
506		printf("%s", rnames[rh[p->n_rval - RD0]]);
507		break;
508
509	case OREG:
510		p->n_lval += size;
511		adrput(stdout, p);
512		p->n_lval -= size;
513		break;
514
515	case ICON:
516	case NAME:
517		if (p->n_name[0] != '\0') {
518			printf("LR'%s-$global$", p->n_name);
519			if (p->n_lval != 0)
520				printf("+" CONFMT, p->n_lval);
521		} else
522			printf("L%%" CONFMT, p->n_lval >> 32);
523		break;
524	default:
525		comperr("upput bad op %d size %d", p->n_op, size);
526	}
527}
528
529void
530adrput(FILE *io, NODE *p)
531{
532	int r;
533	/* output an address, with offsets, from p */
534
535	if (p->n_op == FLD)
536		p = p->n_left;
537
538	switch (p->n_op) {
539
540	case ICON:
541	case NAME:
542		if (p->n_name[0] != '\0') {
543			fprintf(io, "RR'%s-$global$", p->n_name);
544			if (p->n_lval != 0)
545				fprintf(io, "+" CONFMT, p->n_lval);
546		} else
547			fprintf(io, "R%%" CONFMT, p->n_lval);
548		return;
549
550	case OREG:
551		r = p->n_rval;
552		if (p->n_name[0] != '\0') {
553			fprintf(io, "RR'%s-$global$", p->n_name);
554			if (p->n_lval != 0)
555				fprintf(io, "+" CONFMT, p->n_lval);
556		} else
557			fprintf(io, "%d", (int)p->n_lval);
558		if (R2TEST(r)) {
559			fprintf(io, "%s(%s)", rnames[R2UPK1(r)],
560			    rnames[R2UPK2(r)]);
561		} else
562			fprintf(io, "(%s)", rnames[p->n_rval]);
563		return;
564	case REG:
565		if (RD0 <= p->n_rval && p->n_rval <= RETD0)
566			fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]);
567		else
568			fprintf(io, "%s", rnames[p->n_rval]);
569		return;
570
571	default:
572		comperr("illegal address, op %d, node %p", p->n_op, p);
573		return;
574
575	}
576}
577
578/* not used */
579void
580cbgen(int o, int lab)
581{
582}
583
584int
585countargs(NODE *p, int *n)
586{
587	int sz;
588
589	if (p->n_op == CM) {
590		countargs(p->n_left, n);
591		countargs(p->n_right, n);
592		return *n;
593	}
594
595	sz = argsiz(p) / 4;
596	if (*n % (sz > 4? 4 : sz))
597		(*n)++; /* XXX */
598
599	return *n += sz;
600}
601
602void
603fixcalls(NODE *p, void *arg)
604{
605	int n, o;
606
607	/* Prepare for struct return by allocating bounce space on stack */
608	switch (o = p->n_op) {
609	case STCALL:
610	case USTCALL:
611		if (p->n_stsize + p2autooff > stkpos)
612			stkpos = p->n_stsize + p2autooff;
613		/* FALLTHROGH */
614	case CALL:
615	case UCALL:
616		n = 0;
617		n = 1 + countargs(p->n_right, &n);
618		if (n > p2calls)
619			p2calls = n;
620		break;
621	}
622}
623
624void
625myreader(struct interpass *ipole)
626{
627	struct interpass *ip;
628
629	stkpos = p2autooff;
630	DLIST_FOREACH(ip, ipole, qelem) {
631		switch (ip->type) {
632		case IP_PROLOG:
633			p2calls = 0;
634			break;
635
636		case IP_NODE:
637			walkf(ip->ip_node, fixcalls, 0);
638			break;
639		}
640	}
641	if (stkpos > p2autooff)
642		p2autooff = stkpos;
643	if (stkpos > p2maxautooff)
644		p2maxautooff = stkpos;
645	if (x2debug)
646		printip(ipole);
647}
648
649/*
650 * Remove some PCONVs after OREGs are created.
651 */
652static void
653pconv2(NODE *p, void *arg)
654{
655	NODE *q;
656
657	if (p->n_op == PLUS) {
658		if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
659			if (p->n_right->n_op != ICON)
660				return;
661			if (p->n_left->n_op != PCONV)
662				return;
663			if (p->n_left->n_left->n_op != OREG)
664				return;
665			q = p->n_left->n_left;
666			nfree(p->n_left);
667			p->n_left = q;
668			/*
669			 * This will be converted to another OREG later.
670			 */
671		}
672	}
673}
674
675void
676mycanon(NODE *p)
677{
678	walkf(p, pconv2, 0);
679}
680
681void
682myoptim(struct interpass *ipole)
683{
684}
685
686void
687rmove(int s, int d, TWORD t)
688{
689	int sl, sh, dl, dh;
690
691	switch (t) {
692	case LONGLONG:
693	case ULONGLONG:
694		sl = rl[s-RD0];
695		sh = rh[s-RD0];
696		dl = rl[d-RD0];
697		dh = rh[d-RD0];
698
699#define	SW(x,y) { int i = x; x = y; y = i; }
700		if (sl == dh || sh == dl) {
701			/* Swap if moving to itself */
702			SW(sl, sh);
703			SW(dl, dh);
704		}
705		if (sl != dl)
706			printf("\tcopy\t%s,%s\n", rnames[sl], rnames[dl]);
707		if (sh != dh)
708			printf("\tcopy\t%s,%s\n", rnames[sh], rnames[dh]);
709		break;
710	case FLOAT:
711		printf("\tfcpy,sgl\t%s,%s\n", rnames[s], rnames[d]);
712		break;
713	case DOUBLE:
714	case LDOUBLE:
715		printf("\tfcpy,dbl\t%s,%s\n", rnames[s], rnames[d]);
716		break;
717	default:
718		printf("\tcopy\t%s,%s\n", rnames[s], rnames[d]);
719	}
720}
721
722/*
723 * For class c, find worst-case displacement of the number of
724 * registers in the array r[] indexed by class.
725 */
726int
727COLORMAP(int c, int *r)
728{
729	int num;
730
731	switch (c) {
732	case CLASSA:
733		num = 2 * r[CLASSB];
734		num += r[CLASSA];
735		return num < 28;
736	case CLASSB:
737		num = r[CLASSA];
738		num += r[CLASSB] * 2;
739		return num < 28;
740	case CLASSC:
741		num = (r[CLASSD] > 8? 8 : r[CLASSD]) * 2;
742		num += r[CLASSC];
743		return num < 28;
744	case CLASSD:
745		num = (r[CLASSC] + 1) / 2;
746		num += r[CLASSD];
747		return num < 28;
748	}
749	return 0; /* XXX gcc */
750}
751
752char * rnames[MAXREGS] = {
753	"%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9",
754	"%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18",
755	"%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp",
756	"%ret0", "%ret1", "%sp", "%r31",
757	"%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7",
758	"%rd8", "%rd9", "%rd10", "%rd11", "%rd12", "%rd13", "%rd14", "%rd15",
759	"%rd16", "%rd17", "%rd18", "%rd19", "%rd20", "%rd21", "%rd22", "%rd23",
760	"%rd24", "%td4", "%td3", "%td2", "%td1", "%ad1", "%ad0", "%retd0",
761	"%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10",
762	"%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18",
763	"%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26",
764	"%fr27", "%fr28", "%fr29", "%fr30", "%fr31",
765	"%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r",
766	"%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r",
767	"%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r",
768	"%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r",
769	"%fr16l", "%fr16r", "%fr17l", "%fr17r", "%fr18l", "%fr18r",
770#ifdef __hppa64__
771	"%fr19l", "%fr19r",
772	"%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r",
773	"%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r",
774	"%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r",
775	"%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r",
776#endif
777};
778
779/*
780 * Return a class suitable for a specific type.
781 */
782int
783gclass(TWORD t)
784{
785	switch (t) {
786	case LONGLONG:
787	case ULONGLONG:
788		return CLASSB;
789	case FLOAT:
790		return CLASSC;
791	case DOUBLE:
792	case LDOUBLE:
793		return CLASSD;
794	default:
795		return CLASSA;
796	}
797}
798
799/*
800 * Calculate argument sizes.
801 */
802void
803lastcall(NODE *p)
804{
805	NODE *op = p;
806	int size = 64;
807
808	p->n_qual = size;
809	if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
810		return;
811	for (p = p->n_right; p->n_op == CM; p = p->n_left)
812		size += argsiz(p->n_right);
813	size += argsiz(p);
814	op->n_qual = size; /* XXX */
815}
816
817/*
818 * Special shapes.
819 */
820int
821special(NODE *p, int shape)
822{
823	int o = p->n_op;
824
825	switch (shape) {
826	case SFUNCALL:
827		if (o == STCALL || o == USTCALL)
828			return SRREG;
829		break;
830	case SPIMM:
831		if (o != ICON || p->n_name[0] ||
832		    p->n_lval < -31 || p->n_lval >= 32)
833			break;
834		return SRDIR;
835	case SPICON:
836		if (o != ICON || p->n_name[0] ||
837		    p->n_lval < -1024 || p->n_lval >= 1024)
838			break;
839		return SRDIR;
840	case SPCNHW:
841		if (o != ICON || p->n_name[0] || (p->n_lval & 0xffffffffLL))
842			break;
843		return SRDIR;
844	case SPCNLW:
845		if (o != ICON || p->n_name[0] || (p->n_lval & ~0xffffffffLL))
846			break;
847		return SRDIR;
848	case SPCNHI:
849		if (o != ICON || p->n_name[0] || (p->n_lval & ~0xfffff800LL))
850			break;
851		return SRDIR;
852	case SPCON:
853		if (o != ICON || p->n_name[0] ||
854		    p->n_lval < -8192 || p->n_lval >= 8192)
855			break;
856		return SRDIR;
857	case SPNAME:
858		if (o != ICON || !p->n_name[0])
859			break;
860		return SRDIR;
861	}
862	return SRNOPE;
863}
864
865/*
866 * Target-dependent command-line options.
867 */
868void
869mflags(char *str)
870{
871}
872/*
873 * Do something target-dependent for xasm arguments.
874 * Supposed to find target-specific constraints and rewrite them.
875 */
876int
877myxasm(struct interpass *ip, NODE *p)
878{
879	return 0;
880}
881