Mips port from Jan and Simon.
[pcc.git] / arch / i386 / local2.c
blobd7e83deef15f0d372c157e7702ba6fb142438413
1 /* $Id: local2.c,v 1.72 2006/03/18 08:18:33 ragge Exp $ */
2 /*
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
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
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.
30 # include "pass2.h"
31 # include <ctype.h>
32 # include <string.h>
34 void acon(NODE *p);
35 int argsize(NODE *p);
37 static int stkpos;
39 void
40 lineid(int l, char *fn)
42 /* identify line l and file fn */
43 printf("# line %d, file %s\n", l, fn);
46 void
47 deflab(int label)
49 printf(LABFMT ":\n", label);
52 static int regoff[7];
53 static TWORD ftype;
56 * Print out the prolog assembler.
57 * addto and regoff are already calculated.
59 static void
60 prtprolog(struct interpass_prolog *ipp, int addto)
62 int i, j;
64 printf(" pushl %%ebp\n");
65 printf(" movl %%esp,%%ebp\n");
66 if (addto)
67 printf(" subl $%d,%%esp\n", addto);
68 for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
69 if (i & 1)
70 fprintf(stdout, " movl %s,-%d(%s)\n",
71 rnames[j], regoff[j], rnames[FPREG]);
75 * calculate stack size and offsets
77 static int
78 offcalc(struct interpass_prolog *ipp)
80 int i, j, addto;
82 addto = p2maxautooff;
83 if (addto >= AUTOINIT/SZCHAR)
84 addto -= AUTOINIT/SZCHAR;
85 for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
86 if (i & 1) {
87 addto += SZINT/SZCHAR;
88 regoff[j] = addto;
91 return addto;
94 void
95 prologue(struct interpass_prolog *ipp)
97 int addto;
99 ftype = ipp->ipp_type;
100 if (ipp->ipp_vis)
101 printf(" .globl %s\n", ipp->ipp_name);
102 printf(" .align 4\n");
103 printf("%s:\n", ipp->ipp_name);
105 * We here know what register to save and how much to
106 * add to the stack.
108 addto = offcalc(ipp);
109 prtprolog(ipp, addto);
112 void
113 eoftn(struct interpass_prolog *ipp)
115 int i, j;
117 if (ipp->ipp_ip.ip_lbl == 0)
118 return; /* no code needs to be generated */
120 /* return from function code */
121 for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
122 if (i & 1)
123 fprintf(stdout, " movl -%d(%s),%s\n",
124 regoff[j], rnames[FPREG], rnames[j]);
128 /* struct return needs special treatment */
129 if (ftype == STRTY || ftype == UNIONTY) {
130 printf(" movl 8(%%ebp),%%eax\n");
131 printf(" leave\n");
132 printf(" ret $4\n");
133 } else {
134 printf(" leave\n");
135 printf(" ret\n");
140 * add/sub/...
142 * Param given:
144 void
145 hopcode(int f, int o)
147 char *str;
149 switch (o) {
150 case PLUS:
151 str = "add";
152 break;
153 case MINUS:
154 str = "sub";
155 break;
156 case AND:
157 str = "and";
158 break;
159 case OR:
160 str = "or";
161 break;
162 case ER:
163 str = "xor";
164 break;
165 default:
166 comperr("hopcode2: %d", o);
167 str = 0; /* XXX gcc */
169 printf("%s%c", str, f);
173 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
176 tlen(p) NODE *p;
178 switch(p->n_type) {
179 case CHAR:
180 case UCHAR:
181 return(1);
183 case SHORT:
184 case USHORT:
185 return(SZSHORT/SZCHAR);
187 case DOUBLE:
188 return(SZDOUBLE/SZCHAR);
190 case INT:
191 case UNSIGNED:
192 case LONG:
193 case ULONG:
194 return(SZINT/SZCHAR);
196 case LONGLONG:
197 case ULONGLONG:
198 return SZLONGLONG/SZCHAR;
200 default:
201 if (!ISPTR(p->n_type))
202 comperr("tlen type %d not pointer");
203 return SZPOINT(p->n_type)/SZCHAR;
208 * Emit code to compare two longlong numbers.
210 static void
211 twollcomp(NODE *p)
213 int o = p->n_op;
214 int s = getlab();
215 int e = p->n_label;
216 int cb1, cb2;
218 if (o >= ULE)
219 o -= (ULE-LE);
220 switch (o) {
221 case NE:
222 cb1 = 0;
223 cb2 = NE;
224 break;
225 case EQ:
226 cb1 = NE;
227 cb2 = 0;
228 break;
229 case LE:
230 case LT:
231 cb1 = GT;
232 cb2 = LT;
233 break;
234 case GE:
235 case GT:
236 cb1 = LT;
237 cb2 = GT;
238 break;
240 default:
241 cb1 = cb2 = 0; /* XXX gcc */
243 if (p->n_op >= ULE)
244 cb1 += 4, cb2 += 4;
245 expand(p, 0, " cmpl UR,UL\n");
246 if (cb1) cbgen(cb1, s);
247 if (cb2) cbgen(cb2, e);
248 expand(p, 0, " cmpl AR,AL\n");
249 cbgen(p->n_op, e);
250 deflab(s);
254 * Assign to a bitfield.
255 * Clumsy at least, but what to do?
257 static void
258 bfasg(NODE *p)
260 NODE *fn = p->n_left;
261 int shift = UPKFOFF(fn->n_rval);
262 int fsz = UPKFSZ(fn->n_rval);
263 int andval, tch = 0;
265 /* get instruction size */
266 switch (p->n_type) {
267 case CHAR: case UCHAR: tch = 'b'; break;
268 case SHORT: case USHORT: tch = 'w'; break;
269 case INT: case UNSIGNED: tch = 'l'; break;
270 default: comperr("bfasg");
273 /* put src into a temporary reg */
274 fprintf(stdout, " mov%c ", tch);
275 adrput(stdout, getlr(p, 'R'));
276 fprintf(stdout, ",");
277 adrput(stdout, getlr(p, '1'));
278 fprintf(stdout, "\n");
280 /* AND away the bits from dest */
281 andval = ~(((1 << fsz) - 1) << shift);
282 fprintf(stdout, " and%c $%d,", tch, andval);
283 adrput(stdout, fn->n_left);
284 fprintf(stdout, "\n");
286 /* AND away unwanted bits from src */
287 andval = ((1 << fsz) - 1);
288 fprintf(stdout, " and%c $%d,", tch, andval);
289 adrput(stdout, getlr(p, '1'));
290 fprintf(stdout, "\n");
292 /* SHIFT left src number of bits */
293 if (shift) {
294 fprintf(stdout, " sal%c $%d,", tch, shift);
295 adrput(stdout, getlr(p, '1'));
296 fprintf(stdout, "\n");
299 /* OR in src to dest */
300 fprintf(stdout, " or%c ", tch);
301 adrput(stdout, getlr(p, '1'));
302 fprintf(stdout, ",");
303 adrput(stdout, fn->n_left);
304 fprintf(stdout, "\n");
308 * Push a structure on stack as argument.
309 * the scratch registers are already free here
311 static void
312 starg(NODE *p)
314 FILE *fp = stdout;
316 fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
317 fprintf(fp, " pushl $%d\n", p->n_stsize);
318 expand(p, 0, " pushl AL\n");
319 expand(p, 0, " leal 8(%esp),A1\n");
320 expand(p, 0, " pushl A1\n");
321 fprintf(fp, " call memcpy\n");
322 fprintf(fp, " addl $12,%%esp\n");
326 * Compare two floating point numbers.
328 static void
329 fcomp(NODE *p)
332 if (p->n_left->n_op == REG)
333 expand(p, 0, " fucompp\n"); /* emit compare insn */
334 else if (p->n_left->n_type == DOUBLE)
335 expand(p, 0, " fcompl AL\n"); /* emit compare insn */
336 else if (p->n_left->n_type == FLOAT)
337 expand(p, 0, " fcomp AL\n"); /* emit compare insn */
338 else
339 comperr("bad compare %p\n", p);
340 expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */
342 switch (p->n_op) {
343 case EQ:
344 expand(p, 0, " andb $64,%ah\n jne LC\n");
345 break;
346 case NE:
347 expand(p, 0, " andb $64,%ah\n je LC\n");
348 break;
349 case LE:
350 expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
351 break;
352 case LT:
353 expand(p, 0, " andb $65,%ah\n je LC\n");
354 break;
355 case GT:
356 expand(p, 0, " andb $1,%ah\n jne LC\n");
357 break;
358 case GE:
359 expand(p, 0, " andb $65,%ah\n jne LC\n");
360 break;
361 default:
362 comperr("fcomp op %d\n", p->n_op);
367 * Convert an unsigned long long to floating point number.
369 static void
370 ulltofp(NODE *p)
372 static int loadlab;
373 int jmplab;
375 if (loadlab == 0) {
376 loadlab = getlab();
377 expand(p, 0, " .data\n");
378 printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
379 expand(p, 0, " .text\n");
381 jmplab = getlab();
382 expand(p, 0, " pushl UL\n pushl AL\n");
383 expand(p, 0, " fildq (%esp)\n");
384 expand(p, 0, " addl $8,%esp\n");
385 expand(p, 0, " cmpl $0,UL\n");
386 printf(" jge " LABFMT "\n", jmplab);
387 printf(" fldt " LABFMT "\n", loadlab);
388 printf(" faddp %%st,%%st(1)\n");
389 printf(LABFMT ":\n", jmplab);
392 static int
393 argsiz(NODE *p)
395 TWORD t = p->n_type;
397 if (t < LONGLONG || t == FLOAT || t > MAXTYPES)
398 return 4;
399 if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
400 return 8;
401 if (t == LDOUBLE)
402 return 12;
403 if (t == STRTY)
404 return p->n_stsize;
405 comperr("argsiz");
406 return 0;
409 void
410 zzzcode(NODE *p, int c)
412 struct optab *q;
413 NODE *r, *l;
414 int pr, lr;
415 char *ch;
417 switch (c) {
418 case 'A':
420 * Shift operations. Either the right node is a constant
421 * or a register, in the latter case it must be %cl.
423 p = p->n_right;
424 if (p->n_op == ICON)
425 printf("$" CONFMT, p->n_lval);
426 else if (p->n_op != REG || p->n_rval != 2) /* CX */
427 comperr("bad shift reg");
428 else
429 printf("%%cl");
430 break;
432 case 'B':
434 * Print conversion chars for loading into register.
436 p = getlr(p, 'R');
437 switch (p->n_type) {
438 case SHORT: printf("swl"); break;
439 case USHORT: printf("zwl"); break;
440 case CHAR: printf("sbl"); break;
441 case UCHAR: printf("zbl"); break;
442 default: comperr("ZB: %d", p->n_type);
444 break;
446 case 'C': /* remove from stack after subroutine call */
447 pr = p->n_qual;
448 if (p->n_op == STCALL || p->n_op == USTCALL) {
449 pr += 4;
450 q = &table[TBLIDX(p->n_su)];
451 if (q->visit == FOREFF)
452 pr += p->n_stsize;
454 if (p->n_op == UCALL)
455 return; /* XXX remove ZC from UCALL */
456 if (pr)
457 printf(" addl $%d, %s\n", pr, rnames[ESP]);
458 break;
460 case 'D': /* Long long comparision */
461 twollcomp(p);
462 break;
464 case 'E': /* Assign to bitfield */
465 bfasg(p);
466 break;
468 case 'F': /* Structure argument */
469 if (p->n_stalign != 0) /* already on stack */
470 starg(p);
471 break;
473 case 'G': /* Floating point compare */
474 fcomp(p);
475 break;
477 case 'H': /* Fix correct order of sub from stack */
478 /* Check which leg was evaluated first */
479 if ((p->n_su & DORIGHT) == 0)
480 putchar('r');
481 break;
483 case 'I': /* high part of init constant */
484 if (p->n_name[0] != '\0')
485 comperr("named highword");
486 fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff);
487 break;
489 case 'J': /* convert unsigned long long to floating point */
490 ulltofp(p);
491 break;
493 case 'L':
494 case 'R':
495 case '1':
497 * Prints out a register of small type, like %al.
498 * Type is determined by op.
500 r = getlr(p, c);
501 if (r->n_op != REG && r->n_op != MOVE)
502 adrput(stdout, r);
503 comperr("zzz LR1 %p", p);
504 break;
506 case 'M': /* Output sconv move, if needed */
507 l = getlr(p, 'L');
508 /* XXX fixneed: regnum */
509 pr = DECRA(p->n_reg, 0);
510 lr = DECRA(l->n_reg, 0);
511 if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
512 (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
514 else
515 printf(" movb %%%cl,%s\n",
516 rnames[lr][2], rnames[pr]);
517 l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
518 break;
520 case 'N': /* output extended reg name */
521 printf("%s", rnames[getlr(p, '1')->n_rval]);
522 break;
524 case 'O': /* print out emulated ops */
525 if (p->n_op == RS || p->n_op == LS)
526 expand(p, INAREG, "\tpushl AR\n");
527 else
528 expand(p, INCREG, "\tpushl UR\n\tpushl AR\n");
529 expand(p, INCREG, "\tpushl UL\n\tpushl AL\n");
530 if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
531 else if (p->n_op == DIV) ch = "div";
532 else if (p->n_op == MUL) ch = "mul";
533 else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
534 else if (p->n_op == MOD) ch = "mod";
535 else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshr";
536 else if (p->n_op == RS) ch = "ashr";
537 else if (p->n_op == LS) ch = "ashl";
538 else ch = 0, comperr("ZO");
539 printf("\tcall __%sdi3\n\taddl $16,%s\n", ch, rnames[ESP]);
540 break;
542 case 'P': /* push hidden argument on stack */
543 r = (NODE *)p->n_sue;
544 printf("\tleal -%d(%%esp),", stkpos);
545 adrput(stdout, getlr(p, '1'));
546 printf("\n\tpushl ");
547 adrput(stdout, getlr(p, '1'));
548 putchar('\n');
549 break;
551 case 'Q': /* emit struct assign */
552 /* XXX - optimize for small structs */
553 printf("\tpushl $%d\n", p->n_stsize);
554 expand(p, INAREG, "\tpushl AR\n");
555 expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n");
556 printf("\tcall memcpy\n");
557 break;
559 default:
560 comperr("zzzcode %c", c);
564 /*ARGSUSED*/
566 rewfld(NODE *p)
568 return(1);
571 int canaddr(NODE *);
573 canaddr(NODE *p)
575 int o = p->n_op;
577 if (o==NAME || o==REG || o==ICON || o==OREG ||
578 (o==UMUL && shumul(p->n_left)))
579 return(1);
580 return(0);
584 * Does the bitfield shape match?
587 flshape(NODE *p)
589 int o = p->n_op;
591 if (o == OREG || o == REG || o == NAME)
592 return SRDIR; /* Direct match */
593 if (o == UMUL && shumul(p->n_left))
594 return SROREG; /* Convert into oreg */
595 return SRREG; /* put it into a register */
598 /* INTEMP shapes must not contain any temporary registers */
599 /* XXX should this go away now? */
601 shtemp(NODE *p)
603 return 0;
604 #if 0
605 int r;
607 if (p->n_op == STARG )
608 p = p->n_left;
610 switch (p->n_op) {
611 case REG:
612 return (!istreg(p->n_rval));
614 case OREG:
615 r = p->n_rval;
616 if (R2TEST(r)) {
617 if (istreg(R2UPK1(r)))
618 return(0);
619 r = R2UPK2(r);
621 return (!istreg(r));
623 case UMUL:
624 p = p->n_left;
625 return (p->n_op != UMUL && shtemp(p));
628 if (optype(p->n_op) != LTYPE)
629 return(0);
630 return(1);
631 #endif
634 void
635 adrcon(CONSZ val)
637 printf("$" CONFMT, val);
640 void
641 conput(FILE *fp, NODE *p)
643 int val = p->n_lval;
645 switch (p->n_op) {
646 case ICON:
647 if (p->n_name[0] != '\0') {
648 fprintf(fp, "%s", p->n_name);
649 if (val)
650 fprintf(fp, "+%d", val);
651 } else
652 fprintf(fp, "%d", val);
653 return;
655 default:
656 comperr("illegal conput");
660 /*ARGSUSED*/
661 void
662 insput(NODE *p)
664 comperr("insput");
668 * Write out the upper address, like the upper register of a 2-register
669 * reference, or the next memory location.
671 void
672 upput(NODE *p, int size)
675 size /= SZCHAR;
676 switch (p->n_op) {
677 case REG:
678 fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
679 break;
681 case NAME:
682 case OREG:
683 p->n_lval += size;
684 adrput(stdout, p);
685 p->n_lval -= size;
686 break;
687 case ICON:
688 fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
689 break;
690 default:
691 comperr("upput bad op %d size %d", p->n_op, size);
695 void
696 adrput(FILE *io, NODE *p)
698 int r;
699 /* output an address, with offsets, from p */
701 if (p->n_op == FLD)
702 p = p->n_left;
704 switch (p->n_op) {
706 case NAME:
707 if (p->n_name[0] != '\0')
708 fputs(p->n_name, io);
709 if (p->n_lval != 0)
710 fprintf(io, "+" CONFMT, p->n_lval);
711 return;
713 case OREG:
714 r = p->n_rval;
715 if (p->n_lval)
716 fprintf(io, "%d", (int)p->n_lval);
717 fprintf(io, "(%s)", rnames[p->n_rval]);
718 return;
719 case ICON:
720 /* addressable value of the constant */
721 fputc('$', io);
722 conput(io, p);
723 return;
725 case MOVE:
726 case REG:
727 switch (p->n_type) {
728 case LONGLONG:
729 case ULONGLONG:
730 fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
731 rnames[p->n_rval][1], rnames[p->n_rval][2]);
732 break;
733 case SHORT:
734 case USHORT:
735 fprintf(io, "%%%s", &rnames[p->n_rval][2]);
736 break;
737 default:
738 fprintf(io, "%s", rnames[p->n_rval]);
740 return;
742 default:
743 comperr("illegal address, op %d, node %p", p->n_op, p);
744 return;
749 static char *
750 ccbranches[] = {
751 "je", /* jumpe */
752 "jne", /* jumpn */
753 "jle", /* jumple */
754 "jl", /* jumpl */
755 "jge", /* jumpge */
756 "jg", /* jumpg */
757 "jbe", /* jumple (jlequ) */
758 "jb", /* jumpl (jlssu) */
759 "jae", /* jumpge (jgequ) */
760 "ja", /* jumpg (jgtru) */
764 /* printf conditional and unconditional branches */
765 void
766 cbgen(int o, int lab)
768 if (o < EQ || o > UGT)
769 comperr("bad conditional branch: %s", opst[o]);
770 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
774 * Prepare for struct return by allocate bounce space on stack.
776 static void
777 fixcalls(NODE *p)
780 switch (p->n_op) {
781 case STCALL:
782 case USTCALL:
783 if (p->n_stsize+p2autooff > p2maxautooff)
784 stkpos = p2maxautooff = p->n_stsize+p2autooff;
785 break;
790 void
791 myreader(struct interpass *ipole)
793 struct interpass *ip;
795 stkpos = p2autooff;
796 DLIST_FOREACH(ip, ipole, qelem) {
797 if (ip->type != IP_NODE)
798 continue;
799 walkf(ip->ip_node, fixcalls);
801 if (x2debug)
802 printip(ipole);
806 * Remove some PCONVs after OREGs are created.
808 static void
809 pconv2(NODE *p)
811 NODE *q;
813 if (p->n_op == PLUS) {
814 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
815 if (p->n_right->n_op != ICON)
816 return;
817 if (p->n_left->n_op != PCONV)
818 return;
819 if (p->n_left->n_left->n_op != OREG)
820 return;
821 q = p->n_left->n_left;
822 nfree(p->n_left);
823 p->n_left = q;
825 * This will be converted to another OREG later.
831 void
832 mycanon(NODE *p)
834 walkf(p, pconv2);
837 void
838 myoptim(struct interpass *ip)
842 void
843 rmove(int s, int d, TWORD t)
845 switch (t) {
846 case LONGLONG:
847 case ULONGLONG:
848 if (memcmp(rnames[s], rnames[d], 3) != 0)
849 printf(" movl %%%c%c%c,%%%c%c%c\n",
850 rnames[s][0],rnames[s][1],rnames[s][2],
851 rnames[d][0],rnames[d][1],rnames[d][2]);
852 if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
853 printf(" movl %%%c%c%c,%%%c%c%c\n",
854 rnames[s][3],rnames[s][4],rnames[s][5],
855 rnames[d][3],rnames[d][4],rnames[d][5]);
856 break;
857 case CHAR:
858 case UCHAR:
859 printf(" movb %s,%s\n", rnames[s], rnames[d]);
860 break;
861 case FLOAT:
862 case DOUBLE:
863 case LDOUBLE:
864 #ifdef notdef
865 /* a=b()*c(); will generate this */
866 comperr("bad float rmove: %d %d", s, d);
867 #endif
868 break;
869 default:
870 printf(" movl %s,%s\n", rnames[s], rnames[d]);
875 * For class c, find worst-case displacement of the number of
876 * registers in the array r[] indexed by class.
879 COLORMAP(int c, int *r)
881 int num;
883 switch (c) {
884 case CLASSA:
885 num = r[CLASSB] > 4 ? 4 : r[CLASSB];
886 num += 2*r[CLASSC];
887 num += r[CLASSA];
888 return num < 6;
889 case CLASSB:
890 num = r[CLASSA];
891 num += 2*r[CLASSC];
892 num += r[CLASSB];
893 return num < 4;
894 case CLASSC:
895 num = r[CLASSA];
896 num += r[CLASSB] > 4 ? 4 : r[CLASSB];
897 num += 2*r[CLASSC];
898 return num < 5;
899 case CLASSD:
900 return r[CLASSD] < DREGCNT;
902 return 0; /* XXX gcc */
905 char *rnames[] = {
906 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
907 "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
908 "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
909 "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
910 "ebxesi", "ebxedi", "esiedi",
911 "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
915 * Return a class suitable for a specific type.
918 gclass(TWORD t)
920 if (t == CHAR || t == UCHAR)
921 return CLASSB;
922 if (t == LONGLONG || t == ULONGLONG)
923 return CLASSC;
924 if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
925 return CLASSD;
926 return CLASSA;
930 * Calculate argument sizes.
932 void
933 lastcall(NODE *p)
935 NODE *op = p;
936 int size = 0;
938 p->n_qual = 0;
939 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
940 return;
941 for (p = p->n_right; p->n_op == CM; p = p->n_left)
942 size += argsiz(p->n_right);
943 size += argsiz(p);
944 op->n_qual = size; /* XXX */
948 * Special shapes.
951 special(NODE *p, int shape)
953 int o = p->n_op;
955 switch (shape) {
956 case SFUNCALL:
957 if (o == STCALL || o == USTCALL)
958 return SRREG;
959 break;
960 case SPCON:
961 if (o != ICON || p->n_name[0] || p->n_lval < 0)
962 break;
963 return SRDIR;
965 return SRNOPE;