Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20090521093459

Diff

Diff from 1.3 to:

Annotations

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

Annotated File View

gmcgarry
1.3
1 /*      $Id: local2.c,v 1.3 2009/05/21 09:34:59 gmcgarry 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
gmcgarry
1.3
228 #if 0
mickey
1.1
229 /*
230  * Emit code to compare two longlong numbers.
231  */
232 static void
233 twollcomp(NODE *p)
234 {
235         int o = p->n_op;
mickey
1.2
236         int s = getlab2();
mickey
1.1
237         int e = p->n_label;
238         int cb1cb2;
239
240         if (o >= ULE)
241                 o -= (ULE-LE);
242         switch (o) {
243         case NE:
244                 cb1 = 0;
245                 cb2 = NE;
246                 break;
247         case EQ:
248                 cb1 = NE;
249                 cb2 = 0;
250                 break;
251         case LE:
252         case LT:
253                 cb1 = GT;
254                 cb2 = LT;
255                 break;
256         case GE:
257         case GT:
258                 cb1 = LT;
259                 cb2 = GT;
260                 break;
261         
262         default:
263                 cb1 = cb2 = 0/* XXX gcc */
264         }
265         if (p->n_op >= ULE)
266                 cb1 += 4cb2 += 4;
267         expand(p0"  cmpl UR,UL\n");
268         if (cb1cbgen(cb1s);
269         if (cb2cbgen(cb2e);
270         expand(p0"  cmpl AR,AL\n");
271         cbgen(p->n_ope);
272         deflab(s);
273 }
gmcgarry
1.3
274 #endif
mickey
1.1
275
276 int
277 fldexpand(NODE *pint cookiechar **cp)
278 {
279         CONSZ val;
280
281         if (p->n_op == ASSIGN)
282                 p = p->n_left;
283         switch (**cp) {
284         case 'S':
285                 printf("%d"UPKFSZ(p->n_rval));
286                 break;
287         case 'H':
288                 printf("%d"UPKFOFF(p->n_rval));
289                 break;
290         case 'M':
291         case 'N':
292                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
293                 --val;
294                 val <<= UPKFOFF(p->n_rval);
295                 printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
296                 break;
297         default:
298                 comperr("fldexpand");
299         }
300         return 1;
301 }
302
303 static void
304 bfext(NODE *p)
305 {
306         int ch = 0sz = 0;
307
308         if (ISUNSIGNED(p->n_right->n_type))
309                 return;
310         switch (p->n_right->n_type) {
311         case CHAR:
312                 ch = 'b';
313                 sz = 8;
314                 break;
315         case SHORT:
316                 ch = 'w';
317                 sz = 16;
318                 break;
319         case INT:
320                 ch = 'l';
321                 sz = 32;
322                 break;
323         case LONG:
324                 ch = 'q';
325                 sz = 64;
326                 break;
327         default:
328                 comperr("bfext");
329         }
330
331         sz -= UPKFSZ(p->n_left->n_rval);
332         printf("\tshl%c $%d,"chsz);
333         adrput(stdoutgetlr(p'D'));
334         printf("\n\tsar%c $%d,"chsz);
335         adrput(stdoutgetlr(p'D'));
336         printf("\n");
337 }
338
339 /*
340  * Push a structure on stack as argument.
341  * the scratch registers are already free here
342  */
343 static void
344 starg(NODE *p)
345 {
346         FILE *fp = stdout;
347
348         fprintf(fp"   subl $%d,%%esp\n"p->n_stsize);
349         fprintf(fp"   pushl $%d\n"p->n_stsize);
350         expand(p0"  pushl AL\n");
351         expand(p0"  leal 8(%esp),A1\n");
352         expand(p0"  pushl A1\n");
353         fprintf(fp"   call memcpy\n");
354         fprintf(fp"   addl $12,%%esp\n");
355 }
356
357 /*
358  * Compare two floating point numbers.
359  */
360 static void
361 fcomp(NODE *p)  
362 {
363         
364         if (p->n_left->n_op == REG) {
365                 if (p->n_su & DORIGHT)
366                         expand(p0"  fxch\n");
367                 expand(p0"  fucompp\n");    /* emit compare insn  */
368         } else if (p->n_left->n_type == DOUBLE)
369                 expand(p0"  fcompl AL\n");  /* emit compare insn  */
370         else if (p->n_left->n_type == FLOAT)
371                 expand(p0"  fcomp AL\n");   /* emit compare insn  */
372         else
373                 comperr("bad compare %p\n"p);
374         expand(p0"  fnstsw %ax\n"); /* move status reg to ax */
375         
376         switch (p->n_op) {
377         case EQ:
378                 expand(p0"  andb $64,%ah\n  jne LC\n");
379                 break;
380         case NE:
381                 expand(p0"  andb $64,%ah\n  je LC\n");
382                 break;
383         case LE:
384                 expand(p0"  andb $65,%ah\n  cmpb $1,%ah\n   jne LC\n");
385                 break;
386         case LT:
387                 expand(p0"  andb $65,%ah\n  je LC\n");
388                 break;
389         case GT:
390                 expand(p0"  andb $1,%ah\n   jne LC\n");
391                 break;
392         case GE:
393                 expand(p0"  andb $65,%ah\n  jne LC\n");
394                 break;
395         default:
396                 comperr("fcomp op %d\n"p->n_op);
397         }
398 }
399
400 /*
401  * Convert an unsigned long long to floating point number.
402  */
403 static void
404 ulltofp(NODE *p)
405 {
406         static int loadlab;
407         int jmplab;
408
409         if (loadlab == 0) {
mickey
1.2
410                 loadlab = getlab2();
mickey
1.1
411                 expand(p0"  .data\n");
412                 printf(LABFMT ":        .long 0,0x80000000,0x403f\n"loadlab);
413                 expand(p0"  .text\n");
414         }
mickey
1.2
415         jmplab = getlab2();
mickey
1.1
416         expand(p0"  pushl UL\n      pushl AL\n");
417         expand(p0"  fildq (%esp)\n");
418         expand(p0"  addl $8,%esp\n");
419         expand(p0"  cmpl $0,UL\n");
420         printf("        jge " LABFMT "\n"jmplab);
421         printf("        fldt " LABFMT "\n"loadlab);
422         printf("        faddp %%st,%%st(1)\n");
423         printf(LABFMT ":\n"jmplab);
424 }
425
426 static int
427 argsiz(NODE *p)
428 {
429         TWORD t = p->n_type;
430
431         if (t < LONG || t == FLOAT || t > BTMASK)
432                 return 4;
433         if (t == LONG || t == ULONG || t == LONGLONG || t == ULONGLONG ||
434             t == DOUBLE)
435                 return 8;
436         if (t == LDOUBLE)
437                 return 16;
438         if (t == STRTY || t == UNIONTY)
439                 return p->n_stsize;
440         comperr("argsiz");
441         return 0;
442 }
443
444 void
445 zzzcode(NODE *pint c)
446 {
gmcgarry
1.3
447         NODE *l;
mickey
1.1
448         int prlrs;
449
450         switch (c) {
451         case 'A'/* swap st0 and st1 if right is evaluated second */
452                 if ((p->n_su & DORIGHT) == 0) {
453                         if (logop(p->n_op))
454                                 printf("        fxch\n");
455                         else
456                                 printf("r");
457                 }
458                 break;
459
460         case 'C':  /* remove from stack after subroutine call */
461                 if (p->n_left->n_flags & FSTDCALL)
462                         break;
463                 pr = p->n_qual;
464                 if (p->n_op == STCALL || p->n_op == USTCALL)
465                         pr += 4;
466                 if (p->n_op == UCALL)
467                         return/* XXX remove ZC from UCALL */
468                 if (pr)
469                         printf("        addl $%d, %s\n"prrnames[ESP]);
470                 break;
471
472         case 'E'/* Perform bitfield sign-extension */
473                 bfext(p);
474                 break;
475
476         case 'F'/* Structure argument */
477                 if (p->n_stalign != 0/* already on stack */
478                         starg(p);
479                 break;
480
481         case 'G'/* Floating point compare */
482                 fcomp(p);
483                 break;
484
485         case 'J'/* convert unsigned long long to floating point */
486                 ulltofp(p);
487                 break;
488
489         case 'M'/* Output sconv move, if needed */
490                 l = getlr(p'L');
491                 /* XXX fixneed: regnum */
492                 pr = DECRA(p->n_reg0);
493                 lr = DECRA(l->n_reg0);
494                 if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
495                     (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
496                         ;
497                 else
498                         printf("        movb %%%cl,%s\n",
499                             rnames[lr][2], rnames[pr]);
500                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
501                 break;
502
503         case 'N'/* output extended reg name */
504                 printf("%s"rnames[getlr(p'1')->n_rval]);
505                 break;
506
507         case 'S'/* emit eventual move after cast from longlong */
508                 pr = DECRA(p->n_reg0);
509                 lr = p->n_left->n_rval;
510                 switch (p->n_type) {
511                 case CHAR:
512                 case UCHAR:
513                         if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
514                             rnames[pr][1] == rnames[lr][1])
515                                 break;
516                         if (rnames[lr][2] == 'x') {
517                                 printf("\tmovb %%%cl,%s\n",
518                                     rnames[lr][1], rnames[pr]);
519                                 break;
520                         }
521                         /* Must go via stack */
522                         s = BITOOR(freetemp(1));
523                         printf("\tmovl %%e%ci,%d(%%rbp)\n"rnames[lr][1], s);
524                         printf("\tmovb %d(%%rbp),%s\n"srnames[pr]);
525                         comperr("SCONV1 %s->%s"rnames[lr], rnames[pr]);
526                         break;
527
528                 case SHORT:
529                 case USHORT:
530                         if (rnames[lr][1] == rnames[pr][2] &&
531                             rnames[lr][2] == rnames[pr][3])
532                                 break;
533                         printf("\tmovw %%%c%c,%%%s\n",
534                             rnames[lr][1], rnames[lr][2], rnames[pr]+2);
535                         comperr("SCONV2 %s->%s"rnames[lr], rnames[pr]);
536                         break;
537                 case INT:
538                 case UNSIGNED:
539                         if (rnames[lr][1] == rnames[pr][2] &&
540                             rnames[lr][2] == rnames[pr][3])
541                                 break;
542                         printf("\tmovl %%e%c%c,%s\n",
543                                     rnames[lr][1], rnames[lr][2], rnames[pr]);
544                         comperr("SCONV3 %s->%s"rnames[lr], rnames[pr]);
545                         break;
546
547                 default:
548                         if (rnames[lr][1] == rnames[pr][2] &&
549                             rnames[lr][2] == rnames[pr][3])
550                                 break;
551                         comperr("SCONV4 %s->%s"rnames[lr], rnames[pr]);
552                         break;
553                 }
554                 break;
555
556         default:
557                 comperr("zzzcode %c"c);
558         }
559 }
560
561 /*ARGSUSED*/
562 int
563 rewfld(NODE *p)
564 {
565         return(1);
566 }
567
568 int canaddr(NODE *);
569 int
570 canaddr(NODE *p)
571 {
572         int o = p->n_op;
573
574         if (o==NAME || o==REG || o==ICON || o==OREG ||
575             (o==UMUL && shumul(p->n_leftSOREG)))
576                 return(1);
577         return(0);
578 }
579
580 /*
581  * Does the bitfield shape match?
582  */
583 int
584 flshape(NODE *p)
585 {
586         int o = p->n_op;
587
588         if (o == OREG || o == REG || o == NAME)
589                 return SRDIR/* Direct match */
590         if (o == UMUL && shumul(p->n_leftSOREG))
591                 return SROREG/* Convert into oreg */
592         return SRREG/* put it into a register */
593 }
594
595 /* INTEMP shapes must not contain any temporary registers */
596 /* XXX should this go away now? */
597 int
598 shtemp(NODE *p)
599 {
600         return 0;
601 #if 0
602         int r;
603
604         if (p->n_op == STARG )
605                 p = p->n_left;
606
607         switch (p->n_op) {
608         case REG:
609                 return (!istreg(p->n_rval));
610
611         case OREG:
612                 r = p->n_rval;
613                 if (R2TEST(r)) {
614                         if (istreg(R2UPK1(r)))
615                                 return(0);
616                         r = R2UPK2(r);
617                 }
618                 return (!istreg(r));
619
620         case UMUL:
621                 p = p->n_left;
622                 return (p->n_op != UMUL && shtemp(p));
623         }
624
625         if (optype(p->n_op) != LTYPE)
626                 return(0);
627         return(1);
628 #endif
629 }
630
631 void
632 adrcon(CONSZ val)
633 {
634         printf("$" CONFMTval);
635 }
636
637 void
638 conput(FILE *fpNODE *p)
639 {
640         int val = p->n_lval;
641
642         switch (p->n_op) {
643         case ICON:
644                 if (p->n_name[0] != '\0') {
645                         fprintf(fp"%s"p->n_name);
646                         if (val)
647                                 fprintf(fp"+%d"val);
648                 } else
649                         fprintf(fp"%d"val);
650                 return;
651
652         default:
653                 comperr("illegal conput, p %p"p);
654         }
655 }
656
657 /*ARGSUSED*/
658 void
659 insput(NODE *p)
660 {
661         comperr("insput");
662 }
663
664 /*
665  * Write out the upper address, like the upper register of a 2-register
666  * reference, or the next memory location.
667  */
668 void
669 upput(NODE *pint size)
670 {
671
672         size /= SZCHAR;
673         switch (p->n_op) {
674         case REG:
675                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
676                 break;
677
678         case NAME:
679         case OREG:
680                 p->n_lval += size;
681                 adrput(stdoutp);
682                 p->n_lval -= size;
683                 break;
684         case ICON:
685                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
686                 break;
687         default:
688                 comperr("upput bad op %d size %d"p->n_opsize);
689         }
690 }
691
692 void
693 adrput(FILE *ioNODE *p)
694 {
695         int r;
696         /* output an address, with offsets, from p */
697
698         if (p->n_op == FLD)
699                 p = p->n_left;
700
701         switch (p->n_op) {
702
703         case NAME:
704                 if (p->n_name[0] != '\0') {
705                         fputs(p->n_nameio);
706                         if (p->n_lval != 0)
707                                 fprintf(io"+" CONFMTp->n_lval);
708                 } else
709                         fprintf(ioCONFMTp->n_lval);
710                 return;
711
712         case OREG:
713                 r = p->n_rval;
714                 if (p->n_name[0])
715                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
716                 if (p->n_lval)
717                         fprintf(io"%d", (int)p->n_lval);
718                 if (R2TEST(r)) {
719                         fprintf(io"(%s,%s,8)"rnames[R2UPK1(r)],
720                             rnames[R2UPK2(r)]);
721                 } else
722                         fprintf(io"(%s)"rnames[p->n_rval]);
723                 return;
724         case ICON:
725 #ifdef PCC_DEBUG
726                 /* Sanitycheck for PIC, to catch adressable constants */
727                 if (kflag && p->n_name[0]) {
728                         static int foo;
729
730                         if (foo++ == 0) {
731                                 printf("\nfailing...\n");
732                                 fwalk(pe2print0);
733                                 comperr("pass2 conput");
734                         }
735                 }
736 #endif
737                 /* addressable value of the constant */
738                 fputc('$'io);
739                 conput(iop);
740                 return;
741
742         case REG:
743                 switch (p->n_type) {
744                 case LONGLONG:
745                 case ULONGLONG:
746                         fprintf(io"%%%c%c%c"rnames[p->n_rval][0],
747                             rnames[p->n_rval][1], rnames[p->n_rval][2]);
748                         break;
749                 case SHORT:
750                 case USHORT:
751                         fprintf(io"%%%s", &rnames[p->n_rval][2]);
752                         break;
753                 default:
754                         fprintf(io"%s"rnames[p->n_rval]);
755                 }
756                 return;
757
758         default:
759                 comperr("illegal address, op %d, node %p"p->n_opp);
760                 return;
761
762         }
763 }
764
765 static char *
766 ccbranches[] = {
767         "je",           /* jumpe */
768         "jne",          /* jumpn */
769         "jle",          /* jumple */
770         "jl",           /* jumpl */
771         "jge",          /* jumpge */
772         "jg",           /* jumpg */
773         "jbe",          /* jumple (jlequ) */
774         "jb",           /* jumpl (jlssu) */
775         "jae",          /* jumpge (jgequ) */
776         "ja",           /* jumpg (jgtru) */
777 };
778
779
780 /*   printf conditional and unconditional branches */
781 void
782 cbgen(int oint lab)
783 {
784         if (o < EQ || o > UGT)
785                 comperr("bad conditional branch: %s"opst[o]);
786         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
787 }
788
789 static void
790 fixcalls(NODE *pvoid *arg)
791 {
792         /* Prepare for struct return by allocating bounce space on stack */
793         switch (p->n_op) {
794         case STCALL:
795         case USTCALL:
796                 if (p->n_stsize+p2autooff > stkpos)
797                         stkpos = p->n_stsize+p2autooff;
798                 break;
799         }
800 }
801
802 /*
803  * Must store floats in memory if there are two function calls involved.
804  */
805 static int
806 storefloat(struct interpass *ipNODE *p)
807 {
808         int lr;
809
810         switch (optype(p->n_op)) {
811         case BITYPE:
812                 l = storefloat(ipp->n_left);
813                 r = storefloat(ipp->n_right);
814                 if (p->n_op == CM)
815                         return 0/* arguments, don't care */
816                 if (callop(p->n_op))
817                         return 1/* found one */
818 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
819         (p)->n_type == LDOUBLE)
820                 if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
821                         /* must store one. store left */
822                         struct interpass *nip;
823                         TWORD t = p->n_left->n_type;
824                         NODE *ll;
825                         int off;
826
827                         off = BITOOR(freetemp(szty(t)));
828                         ll = mklnode(OREGoffFPREGt);
829                         nip = ipnode(mkbinode(ASSIGNllp->n_leftt));
830                         p->n_left = mklnode(OREGoffFPREGt);
831                         DLIST_INSERT_BEFORE(ipnipqelem);
832                 }
833                 return l|r;
834
835         case UTYPE:
836                 l = storefloat(ipp->n_left);
837                 if (callop(p->n_op))
838                         l = 1;
839                 return l;
840         default:
841                 return 0;
842         }
843 }
844
845 void
846 myreader(struct interpass *ipole)
847 {
848         struct interpass *ip;
849
850         stkpos = p2autooff;
851         DLIST_FOREACH(ipipoleqelem) {
852                 if (ip->type != IP_NODE)
853                         continue;
854                 walkf(ip->ip_nodefixcalls0);
855                 storefloat(ipip->ip_node);
856         }
857         if (stkpos > p2autooff)
858                 p2autooff = stkpos;
859         if (stkpos > p2maxautooff)
860                 p2maxautooff = stkpos;
861         if (x2debug)
862                 printip(ipole);
863 }
864
865 /*
866  * Remove some PCONVs after OREGs are created.
867  */
868 static void
869 pconv2(NODE *pvoid *arg)
870 {
871         NODE *q;
872
873         if (p->n_op == PLUS) {
874                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
875                         if (p->n_right->n_op != ICON)
876                                 return;
877                         if (p->n_left->n_op != PCONV)
878                                 return;
879                         if (p->n_left->n_left->n_op != OREG)
880                                 return;
881                         q = p->n_left->n_left;
882                         nfree(p->n_left);
883                         p->n_left = q;
884                         /*
885                          * This will be converted to another OREG later.
886                          */
887                 }
888         }
889 }
890
891 void
892 mycanon(NODE *p)
893 {
894         walkf(ppconv20);
895 }
896
897 void
898 myoptim(struct interpass *ip)
899 {
900 }
901
902 void
903 rmove(int sint dTWORD t)
904 {
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.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-08-30 10:12 +0200