Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:mickey:20090120121658

Diff

Diff from 1.2 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/amd64/local2.c

Annotated File View

mickey
1.2
1 /*      $Id: local2.c,v 1.2 2009/01/20 12:16:58 mickey Exp $    */
mickey
1.1
2 /*
3  * Copyright (c) 2008 Michael Shalayeff
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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 # include "pass2.h"
31 # include <ctype.h>
32 # include <string.h>
33
34 static int stkpos;
35
36 void
37 deflab(int label)
38 {
39         printf(LABFMT ":\n"label);
40 }
41
42 static int regoff[7];
43 static TWORD ftype;
44
45 /*
46  * Print out the prolog assembler.
47  * addto and regoff are already calculated.
48  */
49 static void
50 prtprolog(struct interpass_prolog *ippint addto)
51 {
52         static int lwnr;
53         int i;
54
mickey
1.2
55         printf("\tpushq %%rbp\n");
56         printf("\tmovq %%rsp,%%rbp\n");
mickey
1.1
57         if (addto)
mickey
1.2
58                 printf("\tsubq $%d,%%rsp\n"addto);
mickey
1.1
59         for (i = 0i < MAXREGSi++)
60                 if (TESTBIT(ipp->ipp_regsi))
mickey
1.2
61                         fprintf(stdout"\tmov %s,-%d(%s)\n",
mickey
1.1
62                             rnames[i], regoff[i], rnames[FPREG]);
63         if (kflag == 0)
64                 return;
65
66         /* if ebx are not saved to stack, it must be moved into another reg */
67         /* check and emit the move before GOT stuff */
68         if (!TESTBIT(ipp->ipp_regsEBX)) {
69                 struct interpass *ip = (struct interpass *)ipp;
70
71                 ip = DLIST_PREV(ipqelem);
72                 ip = DLIST_PREV(ipqelem);
73                 ip = DLIST_PREV(ipqelem);
74                 if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
75                     ip->ip_node->n_left->n_op != REG)
76                         comperr("prtprolog pic error");
77                 ip = (struct interpass *)ipp;
78                 ip = DLIST_NEXT(ipqelem);
79                 if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
80                     ip->ip_node->n_left->n_op != REG)
81                         comperr("prtprolog pic error2");
82                 printf("        movl %s,%s\n",
83                     rnames[ip->ip_node->n_right->n_rval],
84                     rnames[ip->ip_node->n_left->n_rval]);
85                 tfree(ip->ip_node);
86                 DLIST_REMOVE(ipqelem);
87         }
88         printf("        call .LW%d\n", ++lwnr);
89         printf(".LW%d:\n"lwnr);
90         printf("        popl %%ebx\n");
91         printf("        addl $_GLOBAL_OFFSET_TABLE_+[.-.LW%d], %%ebx\n"lwnr);
92 }
93
94 /*
95  * calculate stack size and offsets
96  */
97 static int
98 offcalc(struct interpass_prolog *ipp)
99 {
100         int iaddto;
101
102         addto = p2maxautooff;
103         if (addto >= AUTOINIT/SZCHAR)
104                 addto -= AUTOINIT/SZCHAR;
105         for (i = 0i < MAXREGSi++)
106                 if (TESTBIT(ipp->ipp_regsi)) {
107                         addto += SZINT/SZCHAR;
108                         regoff[i] = addto;
109                 }
110         return addto;
111 }
112
113 void
114 prologue(struct interpass_prolog *ipp)
115 {
116         int addto;
117
118         ftype = ipp->ipp_type;
119
120 #ifdef LANG_F77
121         if (ipp->ipp_vis)
122                 printf("        .globl %s\n"ipp->ipp_name);
123         printf("        .align 4\n");
124         printf("%s:\n"ipp->ipp_name);
125 #endif
126         /*
127          * We here know what register to save and how much to 
128          * add to the stack.
129          */
130         addto = offcalc(ipp);
131         prtprolog(ippaddto);
132 }
133
134 void
135 eoftn(struct interpass_prolog *ipp)
136 {
137         int i;
138
139         if (ipp->ipp_ip.ip_lbl == 0)
140                 return/* no code needs to be generated */
141
142         /* return from function code */
143         for (i = 0i < MAXREGSi++)
144                 if (TESTBIT(ipp->ipp_regsi))
145                         fprintf(stdout"       movl -%d(%s),%s\n",
146                             regoff[i], rnames[FPREG], rnames[i]);
147
148         /* struct return needs special treatment */
149         if (ftype == STRTY || ftype == UNIONTY) {
150                 printf("        movl 8(%%ebp),%%eax\n");
151                 printf("        leave\n");
152                 printf("        ret $%d\n"4);
153         } else {
154                 printf("        leave\n");
155         }
156         printf("\t.size %s,.-%s\n"ipp->ipp_name,
157             ipp->ipp_name);
158 }
159
160 /*
161  * add/sub/...
162  *
163  * Param given:
164  */
165 void
166 hopcode(int fint o)
167 {
168         char *str;
169
170         switch (o) {
171         case PLUS:
172                 str = "add";
173                 break;
174         case MINUS:
175                 str = "sub";
176                 break;
177         case AND:
178                 str = "and";
179                 break;
180         case OR:
181                 str = "or";
182                 break;
183         case ER:
184                 str = "xor";
185                 break;
186         default:
187                 comperr("hopcode2: %d"o);
188                 str = 0/* XXX gcc */
189         }
190         printf("%s%c"strf);
191 }
192
193 /*
194  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
195  */
196 int
mickey
1.2
197 tlen(NODE *p)
mickey
1.1
198 {
199         switch(p->n_type) {
200                 case CHAR:
201                 case UCHAR:
202                         return(1);
203
204                 case SHORT:
205                 case USHORT:
206                         return(SZSHORT/SZCHAR);
207
208                 case DOUBLE:
209                         return(SZDOUBLE/SZCHAR);
210
211                 case INT:
212                 case UNSIGNED:
213                         return(SZINT/SZCHAR);
214
215                 case LONG:
216                 case ULONG:
217                 case LONGLONG:
218                 case ULONGLONG:
219                         return SZLONGLONG/SZCHAR;
220
221                 default:
222                         if (!ISPTR(p->n_type))
223                                 comperr("tlen type %d not pointer");
224                         return SZPOINT(p->n_type)/SZCHAR;
225                 }
226 }
227
228 /*
229  * Emit code to compare two longlong numbers.
230  */
231 static void
232 twollcomp(NODE *p)
233 {
234         int o = p->n_op;
mickey
1.2
235         int s = getlab2();
mickey
1.1
236         int e = p->n_label;
237         int cb1cb2;
238
239         if (o >= ULE)
240                 o -= (ULE-LE);
241         switch (o) {
242         case NE:
243                 cb1 = 0;
244                 cb2 = NE;
245                 break;
246         case EQ:
247                 cb1 = NE;
248                 cb2 = 0;
249                 break;
250         case LE:
251         case LT:
252                 cb1 = GT;
253                 cb2 = LT;
254                 break;
255         case GE:
256         case GT:
257                 cb1 = LT;
258                 cb2 = GT;
259                 break;
260         
261         default:
262                 cb1 = cb2 = 0/* XXX gcc */
263         }
264         if (p->n_op >= ULE)
265                 cb1 += 4cb2 += 4;
266         expand(p0"  cmpl UR,UL\n");
267         if (cb1cbgen(cb1s);
268         if (cb2cbgen(cb2e);
269         expand(p0"  cmpl AR,AL\n");
270         cbgen(p->n_ope);
271         deflab(s);
272 }
273
274 int
275 fldexpand(NODE *pint cookiechar **cp)
276 {
277         CONSZ val;
278
279         if (p->n_op == ASSIGN)
280                 p = p->n_left;
281         switch (**cp) {
282         case 'S':
283                 printf("%d"UPKFSZ(p->n_rval));
284                 break;
285         case 'H':
286                 printf("%d"UPKFOFF(p->n_rval));
287                 break;
288         case 'M':
289         case 'N':
290                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
291                 --val;
292                 val <<= UPKFOFF(p->n_rval);
293                 printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
294                 break;
295         default:
296                 comperr("fldexpand");
297         }
298         return 1;
299 }
300
301 static void
302 bfext(NODE *p)
303 {
304         int ch = 0sz = 0;
305
306         if (ISUNSIGNED(p->n_right->n_type))
307                 return;
308         switch (p->n_right->n_type) {
309         case CHAR:
310                 ch = 'b';
311                 sz = 8;
312                 break;
313         case SHORT:
314                 ch = 'w';
315                 sz = 16;
316                 break;
317         case INT:
318                 ch = 'l';
319                 sz = 32;
320                 break;
321         case LONG:
322                 ch = 'q';
323                 sz = 64;
324                 break;
325         default:
326                 comperr("bfext");
327         }
328
329         sz -= UPKFSZ(p->n_left->n_rval);
330         printf("\tshl%c $%d,"chsz);
331         adrput(stdoutgetlr(p'D'));
332         printf("\n\tsar%c $%d,"chsz);
333         adrput(stdoutgetlr(p'D'));
334         printf("\n");
335 }
336
337 /*
338  * Push a structure on stack as argument.
339  * the scratch registers are already free here
340  */
341 static void
342 starg(NODE *p)
343 {
344         FILE *fp = stdout;
345
346         fprintf(fp"   subl $%d,%%esp\n"p->n_stsize);
347         fprintf(fp"   pushl $%d\n"p->n_stsize);
348         expand(p0"  pushl AL\n");
349         expand(p0"  leal 8(%esp),A1\n");
350         expand(p0"  pushl A1\n");
351         fprintf(fp"   call memcpy\n");
352         fprintf(fp"   addl $12,%%esp\n");
353 }
354
355 /*
356  * Compare two floating point numbers.
357  */
358 static void
359 fcomp(NODE *p)  
360 {
361         
362         if (p->n_left->n_op == REG) {
363                 if (p->n_su & DORIGHT)
364                         expand(p0"  fxch\n");
365                 expand(p0"  fucompp\n");    /* emit compare insn  */
366         } else if (p->n_left->n_type == DOUBLE)
367                 expand(p0"  fcompl AL\n");  /* emit compare insn  */
368         else if (p->n_left->n_type == FLOAT)
369                 expand(p0"  fcomp AL\n");   /* emit compare insn  */
370         else
371                 comperr("bad compare %p\n"p);
372         expand(p0"  fnstsw %ax\n"); /* move status reg to ax */
373         
374         switch (p->n_op) {
375         case EQ:
376                 expand(p0"  andb $64,%ah\n  jne LC\n");
377                 break;
378         case NE:
379                 expand(p0"  andb $64,%ah\n  je LC\n");
380                 break;
381         case LE:
382                 expand(p0"  andb $65,%ah\n  cmpb $1,%ah\n   jne LC\n");
383                 break;
384         case LT:
385                 expand(p0"  andb $65,%ah\n  je LC\n");
386                 break;
387         case GT:
388                 expand(p0"  andb $1,%ah\n   jne LC\n");
389                 break;
390         case GE:
391                 expand(p0"  andb $65,%ah\n  jne LC\n");
392                 break;
393         default:
394                 comperr("fcomp op %d\n"p->n_op);
395         }
396 }
397
398 /*
399  * Convert an unsigned long long to floating point number.
400  */
401 static void
402 ulltofp(NODE *p)
403 {
404         static int loadlab;
405         int jmplab;
406
407         if (loadlab == 0) {
mickey
1.2
408                 loadlab = getlab2();
mickey
1.1
409                 expand(p0"  .data\n");
410                 printf(LABFMT ":        .long 0,0x80000000,0x403f\n"loadlab);
411                 expand(p0"  .text\n");
412         }
mickey
1.2
413         jmplab = getlab2();
mickey
1.1
414         expand(p0"  pushl UL\n      pushl AL\n");
415         expand(p0"  fildq (%esp)\n");
416         expand(p0"  addl $8,%esp\n");
417         expand(p0"  cmpl $0,UL\n");
418         printf("        jge " LABFMT "\n"jmplab);
419         printf("        fldt " LABFMT "\n"loadlab);
420         printf("        faddp %%st,%%st(1)\n");
421         printf(LABFMT ":\n"jmplab);
422 }
423
424 static int
425 argsiz(NODE *p)
426 {
427         TWORD t = p->n_type;
428
429         if (t < LONG || t == FLOAT || t > BTMASK)
430                 return 4;
431         if (t == LONG || t == ULONG || t == LONGLONG || t == ULONGLONG ||
432             t == DOUBLE)
433                 return 8;
434         if (t == LDOUBLE)
435                 return 16;
436         if (t == STRTY || t == UNIONTY)
437                 return p->n_stsize;
438         comperr("argsiz");
439         return 0;
440 }
441
442 void
443 zzzcode(NODE *pint c)
444 {
445         NODE *r, *l;
446         int prlrs;
447         char *ch;
448
449         switch (c) {
450         case 'A'/* swap st0 and st1 if right is evaluated second */
451                 if ((p->n_su & DORIGHT) == 0) {
452                         if (logop(p->n_op))
453                                 printf("        fxch\n");
454                         else
455                                 printf("r");
456                 }
457                 break;
458
459         case 'C':  /* remove from stack after subroutine call */
460                 if (p->n_left->n_flags & FSTDCALL)
461                         break;
462                 pr = p->n_qual;
463                 if (p->n_op == STCALL || p->n_op == USTCALL)
464                         pr += 4;
465                 if (p->n_op == UCALL)
466                         return/* XXX remove ZC from UCALL */
467                 if (pr)
468                         printf("        addl $%d, %s\n"prrnames[ESP]);
469                 break;
470
471         case 'E'/* Perform bitfield sign-extension */
472                 bfext(p);
473                 break;
474
475         case 'F'/* Structure argument */
476                 if (p->n_stalign != 0/* already on stack */
477                         starg(p);
478                 break;
479
480         case 'G'/* Floating point compare */
481                 fcomp(p);
482                 break;
483
484         case 'J'/* convert unsigned long long to floating point */
485                 ulltofp(p);
486                 break;
487
488         case 'M'/* Output sconv move, if needed */
489                 l = getlr(p'L');
490                 /* XXX fixneed: regnum */
491                 pr = DECRA(p->n_reg0);
492                 lr = DECRA(l->n_reg0);
493                 if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
494                     (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
495                         ;
496                 else
497                         printf("        movb %%%cl,%s\n",
498                             rnames[lr][2], rnames[pr]);
499                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
500                 break;
501
502         case 'N'/* output extended reg name */
503                 printf("%s"rnames[getlr(p'1')->n_rval]);
504                 break;
505
506         case 'S'/* emit eventual move after cast from longlong */
507                 pr = DECRA(p->n_reg0);
508                 lr = p->n_left->n_rval;
509                 switch (p->n_type) {
510                 case CHAR:
511                 case UCHAR:
512                         if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
513                             rnames[pr][1] == rnames[lr][1])
514                                 break;
515                         if (rnames[lr][2] == 'x') {
516                                 printf("\tmovb %%%cl,%s\n",
517                                     rnames[lr][1], rnames[pr]);
518                                 break;
519                         }
520                         /* Must go via stack */
521                         s = BITOOR(freetemp(1));
522                         printf("\tmovl %%e%ci,%d(%%rbp)\n"rnames[lr][1], s);
523                         printf("\tmovb %d(%%rbp),%s\n"srnames[pr]);
524                         comperr("SCONV1 %s->%s"rnames[lr], rnames[pr]);
525                         break;
526
527                 case SHORT:
528                 case USHORT:
529                         if (rnames[lr][1] == rnames[pr][2] &&
530                             rnames[lr][2] == rnames[pr][3])
531                                 break;
532                         printf("\tmovw %%%c%c,%%%s\n",
533                             rnames[lr][1], rnames[lr][2], rnames[pr]+2);
534                         comperr("SCONV2 %s->%s"rnames[lr], rnames[pr]);
535                         break;
536                 case INT:
537                 case UNSIGNED:
538                         if (rnames[lr][1] == rnames[pr][2] &&
539                             rnames[lr][2] == rnames[pr][3])
540                                 break;
541                         printf("\tmovl %%e%c%c,%s\n",
542                                     rnames[lr][1], rnames[lr][2], rnames[pr]);
543                         comperr("SCONV3 %s->%s"rnames[lr], rnames[pr]);
544                         break;
545
546                 default:
547                         if (rnames[lr][1] == rnames[pr][2] &&
548                             rnames[lr][2] == rnames[pr][3])
549                                 break;
550                         comperr("SCONV4 %s->%s"rnames[lr], rnames[pr]);
551                         break;
552                 }
553                 break;
554
555         default:
556                 comperr("zzzcode %c"c);
557         }
558 }
559
560 /*ARGSUSED*/
561 int
562 rewfld(NODE *p)
563 {
564         return(1);
565 }
566
567 int canaddr(NODE *);
568 int
569 canaddr(NODE *p)
570 {
571         int o = p->n_op;
572
573         if (o==NAME || o==REG || o==ICON || o==OREG ||
574             (o==UMUL && shumul(p->n_leftSOREG)))
575                 return(1);
576         return(0);
577 }
578
579 /*
580  * Does the bitfield shape match?
581  */
582 int
583 flshape(NODE *p)
584 {
585         int o = p->n_op;
586
587         if (o == OREG || o == REG || o == NAME)
588                 return SRDIR/* Direct match */
589         if (o == UMUL && shumul(p->n_leftSOREG))
590                 return SROREG/* Convert into oreg */
591         return SRREG/* put it into a register */
592 }
593
594 /* INTEMP shapes must not contain any temporary registers */
595 /* XXX should this go away now? */
596 int
597 shtemp(NODE *p)
598 {
599         return 0;
600 #if 0
601         int r;
602
603         if (p->n_op == STARG )
604                 p = p->n_left;
605
606         switch (p->n_op) {
607         case REG:
608                 return (!istreg(p->n_rval));
609
610         case OREG:
611                 r = p->n_rval;
612                 if (R2TEST(r)) {
613                         if (istreg(R2UPK1(r)))
614                                 return(0);
615                         r = R2UPK2(r);
616                 }
617                 return (!istreg(r));
618
619         case UMUL:
620                 p = p->n_left;
621                 return (p->n_op != UMUL && shtemp(p));
622         }
623
624         if (optype(p->n_op) != LTYPE)
625                 return(0);
626         return(1);
627 #endif
628 }
629
630 void
631 adrcon(CONSZ val)
632 {
633         printf("$" CONFMTval);
634 }
635
636 void
637 conput(FILE *fpNODE *p)
638 {
639         int val = p->n_lval;
640
641         switch (p->n_op) {
642         case ICON:
643                 if (p->n_name[0] != '\0') {
644                         fprintf(fp"%s"p->n_name);
645                         if (val)
646                                 fprintf(fp"+%d"val);
647                 } else
648                         fprintf(fp"%d"val);
649                 return;
650
651         default:
652                 comperr("illegal conput, p %p"p);
653         }
654 }
655
656 /*ARGSUSED*/
657 void
658 insput(NODE *p)
659 {
660         comperr("insput");
661 }
662
663 /*
664  * Write out the upper address, like the upper register of a 2-register
665  * reference, or the next memory location.
666  */
667 void
668 upput(NODE *pint size)
669 {
670
671         size /= SZCHAR;
672         switch (p->n_op) {
673         case REG:
674                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
675                 break;
676
677         case NAME:
678         case OREG:
679                 p->n_lval += size;
680                 adrput(stdoutp);
681                 p->n_lval -= size;
682                 break;
683         case ICON:
684                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
685                 break;
686         default:
687                 comperr("upput bad op %d size %d"p->n_opsize);
688         }
689 }
690
691 void
692 adrput(FILE *ioNODE *p)
693 {
694         int r;
695         /* output an address, with offsets, from p */
696
697         if (p->n_op == FLD)
698                 p = p->n_left;
699
700         switch (p->n_op) {
701
702         case NAME:
703                 if (p->n_name[0] != '\0') {
704                         fputs(p->n_nameio);
705                         if (p->n_lval != 0)
706                                 fprintf(io"+" CONFMTp->n_lval);
707                 } else
708                         fprintf(ioCONFMTp->n_lval);
709                 return;
710
711         case OREG:
712                 r = p->n_rval;
713                 if (p->n_name[0])
714                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
715                 if (p->n_lval)
716                         fprintf(io"%d", (int)p->n_lval);
717                 if (R2TEST(r)) {
718                         fprintf(io"(%s,%s,8)"rnames[R2UPK1(r)],
719                             rnames[R2UPK2(r)]);
720                 } else
721                         fprintf(io"(%s)"rnames[p->n_rval]);
722                 return;
723         case ICON:
724 #ifdef PCC_DEBUG
725                 /* Sanitycheck for PIC, to catch adressable constants */
726                 if (kflag && p->n_name[0]) {
727                         static int foo;
728
729                         if (foo++ == 0) {
730                                 printf("\nfailing...\n");
731                                 fwalk(pe2print0);
732                                 comperr("pass2 conput");
733                         }
734                 }
735 #endif
736                 /* addressable value of the constant */
737                 fputc('$'io);
738                 conput(iop);
739                 return;
740
741         case REG:
742                 switch (p->n_type) {
743                 case LONGLONG:
744                 case ULONGLONG:
745                         fprintf(io"%%%c%c%c"rnames[p->n_rval][0],
746                             rnames[p->n_rval][1], rnames[p->n_rval][2]);
747                         break;
748                 case SHORT:
749                 case USHORT:
750                         fprintf(io"%%%s", &rnames[p->n_rval][2]);
751                         break;
752                 default:
753                         fprintf(io"%s"rnames[p->n_rval]);
754                 }
755                 return;
756
757         default:
758                 comperr("illegal address, op %d, node %p"p->n_opp);
759                 return;
760
761         }
762 }
763
764 static char *
765 ccbranches[] = {
766         "je",           /* jumpe */
767         "jne",          /* jumpn */
768         "jle",          /* jumple */
769         "jl",           /* jumpl */
770         "jge",          /* jumpge */
771         "jg",           /* jumpg */
772         "jbe",          /* jumple (jlequ) */
773         "jb",           /* jumpl (jlssu) */
774         "jae",          /* jumpge (jgequ) */
775         "ja",           /* jumpg (jgtru) */
776 };
777
778
779 /*   printf conditional and unconditional branches */
780 void
781 cbgen(int oint lab)
782 {
783         if (o < EQ || o > UGT)
784                 comperr("bad conditional branch: %s"opst[o]);
785         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
786 }
787
788 static void
789 fixcalls(NODE *pvoid *arg)
790 {
791         /* Prepare for struct return by allocating bounce space on stack */
792         switch (p->n_op) {
793         case STCALL:
794         case USTCALL:
795                 if (p->n_stsize+p2autooff > stkpos)
796                         stkpos = p->n_stsize+p2autooff;
797                 break;
798         }
799 }
800
801 /*
802  * Must store floats in memory if there are two function calls involved.
803  */
804 static int
805 storefloat(struct interpass *ipNODE *p)
806 {
807         int lr;
808
809         switch (optype(p->n_op)) {
810         case BITYPE:
811                 l = storefloat(ipp->n_left);
812                 r = storefloat(ipp->n_right);
813                 if (p->n_op == CM)
814                         return 0/* arguments, don't care */
815                 if (callop(p->n_op))
816                         return 1/* found one */
817 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
818         (p)->n_type == LDOUBLE)
819                 if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
820                         /* must store one. store left */
821                         struct interpass *nip;
822                         TWORD t = p->n_left->n_type;
823                         NODE *ll;
824                         int off;
825
826                         off = BITOOR(freetemp(szty(t)));
827                         ll = mklnode(OREGoffFPREGt);
828                         nip = ipnode(mkbinode(ASSIGNllp->n_leftt));
829                         p->n_left = mklnode(OREGoffFPREGt);
830                         DLIST_INSERT_BEFORE(ipnipqelem);
831                 }
832                 return l|r;
833
834         case UTYPE:
835                 l = storefloat(ipp->n_left);
836                 if (callop(p->n_op))
837                         l = 1;
838                 return l;
839         default:
840                 return 0;
841         }
842 }
843
844 void
845 myreader(struct interpass *ipole)
846 {
847         struct interpass *ip;
848
849         stkpos = p2autooff;
850         DLIST_FOREACH(ipipoleqelem) {
851                 if (ip->type != IP_NODE)
852                         continue;
853                 walkf(ip->ip_nodefixcalls0);
854                 storefloat(ipip->ip_node);
855         }
856         if (stkpos > p2autooff)
857                 p2autooff = stkpos;
858         if (stkpos > p2maxautooff)
859                 p2maxautooff = stkpos;
860         if (x2debug)
861                 printip(ipole);
862 }
863
864 /*
865  * Remove some PCONVs after OREGs are created.
866  */
867 static void
868 pconv2(NODE *pvoid *arg)
869 {
870         NODE *q;
871
872         if (p->n_op == PLUS) {
873                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
874                         if (p->n_right->n_op != ICON)
875                                 return;
876                         if (p->n_left->n_op != PCONV)
877                                 return;
878                         if (p->n_left->n_left->n_op != OREG)
879                                 return;
880                         q = p->n_left->n_left;
881                         nfree(p->n_left);
882                         p->n_left = q;
883                         /*
884                          * This will be converted to another OREG later.
885                          */
886                 }
887         }
888 }
889
890 void
891 mycanon(NODE *p)
892 {
893         walkf(ppconv20);
894 }
895
896 void
897 myoptim(struct interpass *ip)
898 {
899 }
900
901 void
902 rmove(int sint dTWORD t)
903 {
904         int slshdldh;
905
906         switch (t) {
907         case LONG:
908         case ULONG:
909         case LONGLONG:
910         case ULONGLONG:
911                 printf("        movq %s,%s\n"rnames[s], rnames[d]);
912                 break;
913         case CHAR:
914         case UCHAR:
915                 printf("        movb %s,%s\n"rnames[s], rnames[d]);
916                 break;
917         case FLOAT:
918         case DOUBLE:
919         case LDOUBLE:
920 #ifdef notdef
921                 /* a=b()*c(); will generate this */
922                 comperr("bad float rmove: %d %d"sd);
923 #endif
924                 break;
925         default:
926                 printf("        movl %s,%s\n"rnames[s], rnames[d]);
927         }
928 }
929
930 /*
931  * For class c, find worst-case displacement of the number of
932  * registers in the array r[] indexed by class.
933  */
934 int
935 COLORMAP(int cint *r)
936 {
937         int num;
938
939         switch (c) {
940         case CLASSA:
941                 num = r[CLASSB] > 4 ? 4 : r[CLASSB];
942                 num += 2*r[CLASSC];
943                 num += r[CLASSA];
944                 return num < 6;
945         case CLASSB:
946                 num = r[CLASSA];
947                 num += 2*r[CLASSC];
948                 num += r[CLASSB];
949                 return num < 4;
950         case CLASSC:
951                 num = r[CLASSA];
952                 num += r[CLASSB] > 4 ? 4 : r[CLASSB];
953                 num += 2*r[CLASSC];
954                 return num < 5;
955         case CLASSD:
956                 return r[CLASSD] < DREGCNT;
957         }
958         return 0/* XXX gcc */
959 }
960
961 char *rnames[] = {
962         "%eax""%edx""%ecx""%ebx""%esi""%edi""%ebp""%esp",
963         "%al""%ah""%dl""%dh""%cl""%ch""%bl""%bh",
964         "%rax""%rdx""%rcx""%rbx""%rsi""%rdi""%rbp""%rsp",
965         "%r08""%r09""%r10""%r11""%r12""%r13""%r14""%r15",
mickey
1.2
966         "%eaxedx",
mickey
1.1
967         "%st0""%st1""%st2""%st3""%st4""%st5""%st6""%st7",
968 };
969
970 /*
971  * Return a class suitable for a specific type.
972  */
973 int
974 gclass(TWORD t)
975 {
976         if (t == CHAR || t == UCHAR)
977                 return CLASSB;
978         if (t == LONG || t == ULONG || t == LONGLONG || t == ULONGLONG)
979                 return CLASSC;
980         if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
981                 return CLASSD;
982         return CLASSA;
983 }
984
985 /*
986  * Calculate argument sizes.
987  */
988 void
989 lastcall(NODE *p)
990 {
991         NODE *op = p;
992         int size = 0;
993
994         p->n_qual = 0;
995         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
996                 return;
997         for (p = p->n_rightp->n_op == CMp = p->n_left)
998                 size += argsiz(p->n_right);
999         size += argsiz(p);
1000         if (kflag)
1001                 size -= 4;
1002         op->n_qual = size/* XXX */
1003 }
1004
1005 /*
1006  * Special shapes.
1007  */
1008 int
1009 special(NODE *pint shape)
1010 {
1011         int o = p->n_op;
1012
1013         switch (shape) {
1014         case SFUNCALL:
1015                 if (o == STCALL || o == USTCALL)
1016                         return SRREG;
1017                 break;
1018         case SPCON:
1019                 if (o != ICON || p->n_name[0] ||
1020                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
1021                         break;
1022                 return SRDIR;
1023         case SMIXOR:
1024                 return tshape(pSZERO);
1025         case SMILWXOR:
1026                 if (o != ICON || p->n_name[0] ||
1027                     p->n_lval == 0 || p->n_lval & 0xffffffff)
1028                         break;
1029                 return SRDIR;
1030         case SMIHWXOR:
1031                 if (o != ICON || p->n_name[0] ||
1032                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
1033                         break;
1034                 return SRDIR;
1035         }
1036         return SRNOPE;
1037 }
1038
1039 /*
1040  * Target-dependent command-line options.
1041  */
1042 void
1043 mflags(char *str)
1044 {
1045 }
1046
1047 /*
1048  * Do something target-dependent for xasm arguments.
1049  */
1050 int
1051 myxasm(struct interpass *ipNODE *p)
1052 {
1053         struct interpass *ip2;
1054         NODE *in = 0, *ut = 0;
1055         TWORD t;
1056         char *w;
1057         int reg;
1058         int cw;
1059
1060         cw = xasmcode(p->n_name);
1061         if (cw & (XASMASG|XASMINOUT))
1062                 ut = p->n_left;
1063         if ((cw & XASMASG) == 0)
1064                 in = p->n_left;
1065
1066         switch (XASMVAL(cw)) {
1067         case 'D'reg = EDIbreak;
1068         case 'S'reg = ESIbreak;
1069         case 'a'reg = EAXbreak;
1070         case 'b'reg = EBXbreak;
1071         case 'c'reg = ECXbreak;
1072         case 'd'reg = EDXbreak;
1073         case 't'reg = 0break;
1074         case 'u'reg = 1break;
1075         case 'A'reg = EAXEDXbreak;
1076         case 'q'/* XXX let it be CLASSA as for now */
1077                 p->n_name = tmpstrdup(p->n_name);
1078                 w = strchr(p->n_name'q');
1079                 *w = 'r';
1080                 return 0;
1081         default:
1082                 return 0;
1083         }
1084         p->n_name = tmpstrdup(p->n_name);
1085         for (w = p->n_name; *ww++)
1086                 ;
1087         w[-1] = 'r'/* now reg */
1088         t = p->n_left->n_type;
1089         if (reg == EAXEDX) {
1090                 p->n_label = CLASSC;
1091         } else {
1092                 p->n_label = CLASSA;
1093                 if (t == CHAR || t == UCHAR) {
1094                         p->n_label = CLASSB;
1095                         reg = reg * 2 + 8;
1096                 }
1097         }
1098         if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
1099                 p->n_label = CLASSD;
1100                 reg += 037;
1101         }
1102
1103         if (in && ut)
1104                 in = tcopy(in);
1105         p->n_left = mklnode(REG0regt);
1106         if (ut) {
1107                 ip2 = ipnode(mkbinode(ASSIGNuttcopy(p->n_left), t));
1108                 DLIST_INSERT_AFTER(ipip2qelem);
1109         }
1110         if (in) {
1111                 ip2 = ipnode(mkbinode(ASSIGNtcopy(p->n_left), int));
1112                 DLIST_INSERT_BEFORE(ipip2qelem);
1113         }
1114         return 1;
1115 }
1116
1117 void
1118 targarg(char *wvoid *arg)
1119 {
1120         NODE **ary = arg;
1121         NODE *p, *q;
1122
1123         p = ary[(int)w[1]-'0']->n_left;
1124         if (optype(p->n_op) != LTYPE)
1125                 comperr("bad xarg op %d"p->n_op);
1126         q = tcopy(p);
1127         if (q->n_op == REG) {
1128                 if (*w == 'k') {
1129                         q->n_type = INT;
1130                 } else if (*w != 'w') {
1131                         if (q->n_type > UCHAR) {
1132                                 regno(q) = regno(q)*2+8;
1133                                 if (*w == 'h')
1134                                         regno(q)++;
1135                         }
1136                         q->n_type = INT;
1137                 } else
1138                         q->n_type = SHORT;
1139         }
1140         adrput(stdoutq);
1141         tfree(q);
1142 }
1143
1144 /*
1145  * target-specific conversion of numeric arguments.
1146  */
1147 int
1148 numconv(void *ipvoid *p1void *q1)
1149 {
1150         NODE *p = p1, *q = q1;
1151         int cw = xasmcode(q->n_name);
1152
1153         switch (XASMVAL(cw)) {
1154         case 'a':
1155         case 'b':
1156         case 'c':
1157         case 'd':
1158                 p->n_name = tmpcalloc(2);
1159                 p->n_name[0] = XASMVAL(cw);
1160                 return 1;
1161         default:
1162                 return 0;
1163         }
1164 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-21 12:24 +0100