source: mainline/uspace/app/pcc/arch/hppa/local2.c@ 94f6df7

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