Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101105155551

Diff

Diff from 1.27 to:

Annotations

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

Annotated File View

ragge
1.27
1 /*      $Id: local2.c,v 1.27 2010/11/05 15:55:51 ragge 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
ragge
1.11
42 static int regoff[MAXREGS];
mickey
1.1
43 static TWORD ftype;
ragge
1.4
44 char *rbyte[], *rshort[], *rlong[];
mickey
1.1
45
46 /*
47  * Print out the prolog assembler.
48  * addto and regoff are already calculated.
49  */
50 static void
51 prtprolog(struct interpass_prolog *ippint addto)
52 {
53         int i;
54
ragge
1.5
55         /* XXX should look if there is any need to emit this */
mickey
1.2
56         printf("\tpushq %%rbp\n");
57         printf("\tmovq %%rsp,%%rbp\n");
ragge
1.10
58         addto = (addto+15) & ~15/* 16-byte aligned */
mickey
1.1
59         if (addto)
mickey
1.2
60                 printf("\tsubq $%d,%%rsp\n"addto);
ragge
1.10
61
62         /* save permanent registers */
mickey
1.1
63         for (i = 0i < MAXREGSi++)
ragge
1.10
64                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.11
65                         fprintf(stdout"\tmovq %s,-%d(%s)\n",
mickey
1.1
66                             rnames[i], regoff[i], rnames[FPREG]);
ragge
1.4
67 }
mickey
1.1
68
69 /*
70  * calculate stack size and offsets
71  */
72 static int
73 offcalc(struct interpass_prolog *ipp)
74 {
75         int iaddto;
76
77         addto = p2maxautooff;
78         if (addto >= AUTOINIT/SZCHAR)
79                 addto -= AUTOINIT/SZCHAR;
80         for (i = 0i < MAXREGSi++)
81                 if (TESTBIT(ipp->ipp_regsi)) {
ragge
1.10
82                         addto += SZLONG/SZCHAR;
mickey
1.1
83                         regoff[i] = addto;
84                 }
85         return addto;
86 }
87
88 void
89 prologue(struct interpass_prolog *ipp)
90 {
91         int addto;
92
93         ftype = ipp->ipp_type;
94
95 #ifdef LANG_F77
96         if (ipp->ipp_vis)
97                 printf("        .globl %s\n"ipp->ipp_name);
ragge
1.10
98         printf("        .align 16\n");
mickey
1.1
99         printf("%s:\n"ipp->ipp_name);
100 #endif
101         /*
102          * We here know what register to save and how much to 
103          * add to the stack.
104          */
105         addto = offcalc(ipp);
106         prtprolog(ippaddto);
107 }
108
109 void
110 eoftn(struct interpass_prolog *ipp)
111 {
112         int i;
113
114         if (ipp->ipp_ip.ip_lbl == 0)
115                 return/* no code needs to be generated */
116
117         /* return from function code */
118         for (i = 0i < MAXREGSi++)
119                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.10
120                         fprintf(stdout"       movq -%d(%s),%s\n",
mickey
1.1
121                             regoff[i], rnames[FPREG], rnames[i]);
122
123         /* struct return needs special treatment */
124         if (ftype == STRTY || ftype == UNIONTY) {
125                 printf("        movl 8(%%ebp),%%eax\n");
126                 printf("        leave\n");
127                 printf("        ret $%d\n"4);
128         } else {
129                 printf("        leave\n");
ragge
1.11
130                 printf("        ret\n");
mickey
1.1
131         }
ragge
1.10
132         printf("\t.size %s,.-%s\n"ipp->ipp_nameipp->ipp_name);
mickey
1.1
133 }
134
135 /*
136  * add/sub/...
137  *
138  * Param given:
139  */
140 void
141 hopcode(int fint o)
142 {
143         char *str;
144
145         switch (o) {
146         case PLUS:
147                 str = "add";
148                 break;
149         case MINUS:
150                 str = "sub";
151                 break;
152         case AND:
153                 str = "and";
154                 break;
155         case OR:
156                 str = "or";
157                 break;
158         case ER:
159                 str = "xor";
160                 break;
161         default:
162                 comperr("hopcode2: %d"o);
163                 str = 0/* XXX gcc */
164         }
165         printf("%s%c"strf);
166 }
167
168 /*
169  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
170  */
171 int
mickey
1.2
172 tlen(NODE *p)
mickey
1.1
173 {
174         switch(p->n_type) {
175                 case CHAR:
176                 case UCHAR:
177                         return(1);
178
179                 case SHORT:
180                 case USHORT:
181                         return(SZSHORT/SZCHAR);
182
183                 case DOUBLE:
184                         return(SZDOUBLE/SZCHAR);
185
186                 case INT:
187                 case UNSIGNED:
188                         return(SZINT/SZCHAR);
189
190                 case LONG:
191                 case ULONG:
192                 case LONGLONG:
193                 case ULONGLONG:
194                         return SZLONGLONG/SZCHAR;
195
196                 default:
197                         if (!ISPTR(p->n_type))
198                                 comperr("tlen type %d not pointer");
199                         return SZPOINT(p->n_type)/SZCHAR;
200                 }
201 }
202
ragge
1.19
203 /*
204  * Compare two floating point numbers.
205  */
206 static void
207 fcomp(NODE *p)  
208 {
209
210         if (p->n_left->n_op == REG) {
211                 if (p->n_su & DORIGHT)
212                         expand(p0"  fxch\n");
213                 expand(p0"  fucompp\n");    /* emit compare insn  */
214         } else
215                 comperr("bad compare %p\n"p);
216         expand(p0"  fnstsw %ax\n"); /* move status reg to ax */
217         
218         switch (p->n_op) {
219         case EQ:
220                 expand(p0"  andb $69,%ah\n  xorb $64,%ah\n  je LC\n");
221                 break;
222         case NE:
223                 expand(p0"  andb $69,%ah\n  xorb $64,%ah\n  jne LC\n");
224                 break;
225         case LE:
226                 expand(p0"  andb $69,%ah\n  xorb $1,%ah\n   jne LC\n");
227                 break;
228         case LT:
229                 expand(p0"  andb $69,%ah\n  je LC\n");
230                 break;
231         case GT:
232                 expand(p0"  andb $1,%ah\n   jne LC\n");
233                 break;
234         case GE:
235                 expand(p0"  andb $69,%ah\n  jne LC\n");
236                 break;
237         default:
238                 comperr("fcomp op %d\n"p->n_op);
239         }
240 }
241
mickey
1.1
242 int
243 fldexpand(NODE *pint cookiechar **cp)
244 {
245         CONSZ val;
246
247         if (p->n_op == ASSIGN)
248                 p = p->n_left;
249         switch (**cp) {
250         case 'S':
251                 printf("%d"UPKFSZ(p->n_rval));
252                 break;
253         case 'H':
254                 printf("%d"UPKFOFF(p->n_rval));
255                 break;
256         case 'M':
257         case 'N':
258                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
259                 --val;
260                 val <<= UPKFOFF(p->n_rval);
ragge
1.13
261                 if (p->n_type > UNSIGNED)
262                         printf("0x%llx", (**cp == 'M' ? val : ~val));
263                 else
264                         printf("0x%llx", (**cp == 'M' ? val : ~val)&0xffffffff);
mickey
1.1
265                 break;
266         default:
267                 comperr("fldexpand");
268         }
269         return 1;
270 }
271
272 static void
273 bfext(NODE *p)
274 {
275         int ch = 0sz = 0;
276
277         if (ISUNSIGNED(p->n_right->n_type))
278                 return;
279         switch (p->n_right->n_type) {
280         case CHAR:
281                 ch = 'b';
282                 sz = 8;
283                 break;
284         case SHORT:
285                 ch = 'w';
286                 sz = 16;
287                 break;
288         case INT:
289                 ch = 'l';
290                 sz = 32;
291                 break;
292         case LONG:
293                 ch = 'q';
294                 sz = 64;
295                 break;
296         default:
297                 comperr("bfext");
298         }
299
300         sz -= UPKFSZ(p->n_left->n_rval);
301         printf("\tshl%c $%d,"chsz);
302         adrput(stdoutgetlr(p'D'));
303         printf("\n\tsar%c $%d,"chsz);
304         adrput(stdoutgetlr(p'D'));
305         printf("\n");
306 }
307
308 static void
ragge
1.21
309 stasg(NODE *p)
mickey
1.1
310 {
ragge
1.21
311         expand(pINAREG"     leaq AL,%rdi\n");
312         if (p->n_stsize >= 8)
313                 printf("\tmovl $%d,%%ecx\n\trep movsq\n"p->n_stsize >> 3);
314         if (p->n_stsize & 3)
315                 printf("\tmovsl\n");
316         if (p->n_stsize & 2)
317                 printf("\tmovsw\n");
318         if (p->n_stsize & 1)
319                 printf("\tmovsb\n");
mickey
1.1
320 }
321
ragge
1.25
322 #define E(x)    expand(p, 0, x)
mickey
1.1
323 /*
ragge
1.7
324  * Generate code to convert an unsigned long to xmm float/double.
mickey
1.1
325  */
326 static void
ragge
1.7
327 ultofd(NODE *p)
mickey
1.1
328 {
329
ragge
1.7
330         E("     movq AL,A1\n");
ragge
1.9
331         E("     testq A1,A1\n");
ragge
1.7
332         E("     js 2f\n");
333         E("     cvtsi2sZfq A1,A3\n");
334         E("     jmp 3f\n");
335         E("2:\n");
336         E("     movq A1,A2\n");
337         E("     shrq A2\n");
ragge
1.9
338         E("     andq $1,A1\n");
ragge
1.7
339         E("     orq A1,A2\n");
340         E("     cvtsi2sZfq A2,A3\n");
341         E("     addsZf A3,A3\n");
342         E("3:\n");
ragge
1.25
343 }
344
345 /*
346  * Generate code to convert an x87 long double to an unsigned long.
347  * This is ugly :-/
348  */
349 static void
350 ldtoul(NODE *p)
351 {
352         int r;
353
354         r = getlr(p'1')->n_rval;
355
356         E("     subq $16,%rsp\n");
357         E("     movl $0x5f000000,(%rsp)\n"); /* More than long can have */
358         E("     flds (%rsp)\n");
359         if (p->n_left->n_op == REG) {
360                 E("     movq AL,(%rsp)\n");
361                 E("     fldt (%rsp)\n");
362         } else
363                 E("     fldt AL\n");
364         E("     fucomi %st(1), %st\n");
365         E("     jae 2f\n");
366
367         E("     fstp %st(1)\n");         /* Pop huge val from stack */
368         E("     fnstcw (%rsp)\n");       /* store cw */
369         E("     movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
370         E("     fldcw 4(%rsp)\n");       /* new cw */
371         E("     fistpll 8(%rsp)\n");     /* save val */
372         E("     fldcw (%rsp)\n");        /* fetch old cw */
373         E("     movq 8(%rsp),A1\n");
374
375         E("     jmp 3f\n");
376
377         E("2:\n");
378
379         E("     fsubp %st, %st(1)\n");
380         E("     fnstcw (%rsp)\n");      
381         E("     movw $0x0f3f,4(%rsp)\n");
382         E("     fldcw 4(%rsp)\n");
383         E("     fistpll 8(%rsp)\n");
384         E("     fldcw (%rsp)\n");
385         E("     movabsq $0x8000000000000000,A1\n");
386         E("     xorq 8(%rsp),A1\n");
387
388         E("3:   addq $16,%rsp\n");
389 }
ragge
1.26
390
391 /*
392  * Generate code to convert an SSE float/double to an unsigned long.
393  */     
394 static void     
395 fdtoul(NODE *p
396 {
397         E("     movabsq $0x43e0000000000000,A1\n");
398         E("     movd A1,A3\n");
399         E("     ucomisd A3,AL\n");
400         E("     jae 2f\n");
401         E("     cvttsd2siq AL,A1\n");
402         E("     jmp 3f\n");
403         E("2:\n");
404         E("     subsd A3,AL\n");
405         E("     cvttsd2siq AL,A1\n");
406         E("     movabsq $0x8000000000000000,A2\n");
407         E("     xorq A2,A1\n");
408         E("3:\n");
409 }
ragge
1.7
410 #undef E
mickey
1.1
411
412 void
413 zzzcode(NODE *pint c)
414 {
ragge
1.6
415         NODE *l;
ragge
1.7
416         int prlrs;
ragge
1.14
417         char **rt;
mickey
1.1
418
419         switch (c) {
420         case 'A'/* swap st0 and st1 if right is evaluated second */
421                 if ((p->n_su & DORIGHT) == 0) {
422                         if (logop(p->n_op))
423                                 printf("        fxch\n");
424                         else
425                                 printf("r");
426                 }
427                 break;
428
ragge
1.25
429         case 'B'/* ldouble to unsigned long cast */
430                 ldtoul(p);
431                 break;
432
ragge
1.26
433         case 'b'/* float/double to unsigned long cast */
434                 fdtoul(p);
435                 break;
436
mickey
1.1
437         case 'C':  /* remove from stack after subroutine call */
438                 pr = p->n_qual;
439                 if (p->n_op == UCALL)
440                         return/* XXX remove ZC from UCALL */
441                 if (pr)
ragge
1.10
442                         printf("        addq $%d, %s\n"prrnames[RSP]);
mickey
1.1
443                 break;
444
445         case 'E'/* Perform bitfield sign-extension */
446                 bfext(p);
447                 break;
448
449         case 'F'/* Structure argument */
ragge
1.21
450                 printf("        subq $%d,%%rsp\n"p->n_stsize);
451                 printf("        movq %%rsp,%%rsi\n");
452                 stasg(p);
mickey
1.1
453                 break;
ragge
1.19
454
455         case 'G'/* Floating point compare */
456                 fcomp(p);
457                 break;
458
ragge
1.7
459         case 'j'/* convert unsigned long to f/d */
460                 ultofd(p);
mickey
1.1
461                 break;
462
463         case 'M'/* Output sconv move, if needed */
464                 l = getlr(p'L');
465                 /* XXX fixneed: regnum */
466                 pr = DECRA(p->n_reg0);
467                 lr = DECRA(l->n_reg0);
ragge
1.6
468                 if (pr == lr)
469                         break;
470                 printf("        movb %s,%s\n"rbyte[lr], rbyte[pr]);
mickey
1.1
471                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
472                 break;
473
ragge
1.27
474         case 'N'/* output long reg name */
475                 printf("%s"rlong[getlr(p'1')->n_rval]);
476                 break;
477
ragge
1.16
478         case 'P'/* Put hidden argument in rdi */
479                 printf("\tleaq -%d(%%rbp),%%rdi\n"stkpos);
480                 break;
481
ragge
1.10
482         case 'Q'/* emit struct assign */
ragge
1.21
483                 stasg(p);
ragge
1.10
484                 break;
485
ragge
1.7
486         case 'R'/* print opname based on right type */
487         case 'L'/* print opname based on left type */
488                 switch (getlr(pc)->n_type) {
489                 case CHARcase UCHARs = 'b'break;
490                 case SHORTcase USHORTs = 'w'break;
491                 case INTcase UNSIGNEDs = 'l'break;
492                 defaults = 'q'break;
493                 printf("%c"s);
494                 }
495                 break;
ragge
1.14
496
497         case '8'/* special reg name printout (64-bit) */
498         case '1'/* special reg name printout (32-bit) */
ragge
1.7
499                 l = getlr(p'1');
ragge
1.14
500                 rt = c == '8' ? rnames : rlong;
501                 printf("%s"rt[l->n_rval]);
ragge
1.7
502                 break;
503
504         case 'g':
505                 p = p->n_left;
506                 /* FALLTHROUGH */
507         case 'f'/* float or double */
508                 printf("%c"p->n_type == FLOAT ? 's' : 'd');
509                 break;
510
511         case 'q'/* int or long */
512                 printf("%c"p->n_left->n_type == LONG ? 'q' : ' ');
513                 break;
514
mickey
1.1
515         default:
516                 comperr("zzzcode %c"c);
517         }
518 }
519
520 /*ARGSUSED*/
521 int
522 rewfld(NODE *p)
523 {
524         return(1);
525 }
526
527 int canaddr(NODE *);
528 int
529 canaddr(NODE *p)
530 {
531         int o = p->n_op;
532
533         if (o==NAME || o==REG || o==ICON || o==OREG ||
534             (o==UMUL && shumul(p->n_leftSOREG)))
535                 return(1);
536         return(0);
537 }
538
539 /*
540  * Does the bitfield shape match?
541  */
542 int
543 flshape(NODE *p)
544 {
545         int o = p->n_op;
546
547         if (o == OREG || o == REG || o == NAME)
548                 return SRDIR/* Direct match */
549         if (o == UMUL && shumul(p->n_leftSOREG))
550                 return SROREG/* Convert into oreg */
551         return SRREG/* put it into a register */
552 }
553
554 /* INTEMP shapes must not contain any temporary registers */
555 /* XXX should this go away now? */
556 int
557 shtemp(NODE *p)
558 {
559         return 0;
560 #if 0
561         int r;
562
563         if (p->n_op == STARG )
564                 p = p->n_left;
565
566         switch (p->n_op) {
567         case REG:
568                 return (!istreg(p->n_rval));
569
570         case OREG:
571                 r = p->n_rval;
572                 if (R2TEST(r)) {
573                         if (istreg(R2UPK1(r)))
574                                 return(0);
575                         r = R2UPK2(r);
576                 }
577                 return (!istreg(r));
578
579         case UMUL:
580                 p = p->n_left;
581                 return (p->n_op != UMUL && shtemp(p));
582         }
583
584         if (optype(p->n_op) != LTYPE)
585                 return(0);
586         return(1);
587 #endif
588 }
589
590 void
591 adrcon(CONSZ val)
592 {
593         printf("$" CONFMTval);
594 }
595
596 void
597 conput(FILE *fpNODE *p)
598 {
ragge
1.17
599         long val = p->n_lval;
mickey
1.1
600
601         switch (p->n_op) {
602         case ICON:
603                 if (p->n_name[0] != '\0') {
604                         fprintf(fp"%s"p->n_name);
605                         if (val)
ragge
1.17
606                                 fprintf(fp"+%ld"val);
mickey
1.1
607                 } else
ragge
1.17
608                         fprintf(fp"%ld"val);
mickey
1.1
609                 return;
610
611         default:
612                 comperr("illegal conput, p %p"p);
613         }
614 }
615
616 /*ARGSUSED*/
617 void
618 insput(NODE *p)
619 {
620         comperr("insput");
621 }
622
623 /*
624  * Write out the upper address, like the upper register of a 2-register
625  * reference, or the next memory location.
ragge
1.17
626  * XXX - not needed on amd64
mickey
1.1
627  */
628 void
629 upput(NODE *pint size)
630 {
631
632         size /= SZCHAR;
633         switch (p->n_op) {
634         case REG:
635                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
636                 break;
637
638         case NAME:
639         case OREG:
640                 p->n_lval += size;
641                 adrput(stdoutp);
642                 p->n_lval -= size;
643                 break;
644         case ICON:
645                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
646                 break;
647         default:
648                 comperr("upput bad op %d size %d"p->n_opsize);
649         }
650 }
651
652 void
653 adrput(FILE *ioNODE *p)
654 {
655         int r;
ragge
1.5
656         char **rc;
mickey
1.1
657         /* output an address, with offsets, from p */
658
659         if (p->n_op == FLD)
660                 p = p->n_left;
661
662         switch (p->n_op) {
663
664         case NAME:
665                 if (p->n_name[0] != '\0') {
ragge
1.23
666                         if (p->n_lval != 0)
667                                 fprintf(ioCONFMT "+"p->n_lval);
ragge
1.22
668                         fprintf(io"%s(%%rip)"p->n_name);
mickey
1.1
669                 } else
670                         fprintf(ioCONFMTp->n_lval);
671                 return;
672
673         case OREG:
674                 r = p->n_rval;
675                 if (p->n_name[0])
676                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
677                 if (p->n_lval)
ragge
1.17
678                         fprintf(io"%lld"p->n_lval);
mickey
1.1
679                 if (R2TEST(r)) {
ragge
1.18
680                         int r1 = R2UPK1(r);
681                         int r2 = R2UPK2(r);
682                         int sh = R2UPK3(r);
683
684                         fprintf(io"(%s,%s,%d)"
685                             r1 == MAXREGS ? "" : rnames[r1],
686                             r2 == MAXREGS ? "" : rnames[r2], sh);
mickey
1.1
687                 } else
688                         fprintf(io"(%s)"rnames[p->n_rval]);
689                 return;
690         case ICON:
691 #ifdef PCC_DEBUG
692                 /* Sanitycheck for PIC, to catch adressable constants */
693                 if (kflag && p->n_name[0]) {
694                         static int foo;
695
696                         if (foo++ == 0) {
697                                 printf("\nfailing...\n");
698                                 fwalk(pe2print0);
699                                 comperr("pass2 conput");
700                         }
701                 }
702 #endif
703                 /* addressable value of the constant */
704                 fputc('$'io);
705                 conput(iop);
706                 return;
707
708         case REG:
709                 switch (p->n_type) {
ragge
1.5
710                 case CHAR:
711                 case UCHAR:
712                         rc = rbyte;
mickey
1.1
713                         break;
714                 case SHORT:
715                 case USHORT:
ragge
1.5
716                         rc = rshort;
717                         break;
718                 case INT:
719                 case UNSIGNED:
720                         rc = rlong;
mickey
1.1
721                         break;
722                 default:
ragge
1.5
723                         rc = rnames;
724                         break;
mickey
1.1
725                 }
ragge
1.5
726                 fprintf(io"%s"rc[p->n_rval]);
mickey
1.1
727                 return;
728
729         default:
730                 comperr("illegal address, op %d, node %p"p->n_opp);
731                 return;
732
733         }
734 }
735
736 static char *
737 ccbranches[] = {
738         "je",           /* jumpe */
739         "jne",          /* jumpn */
740         "jle",          /* jumple */
741         "jl",           /* jumpl */
742         "jge",          /* jumpge */
743         "jg",           /* jumpg */
744         "jbe",          /* jumple (jlequ) */
745         "jb",           /* jumpl (jlssu) */
746         "jae",          /* jumpge (jgequ) */
747         "ja",           /* jumpg (jgtru) */
748 };
749
750
751 /*   printf conditional and unconditional branches */
752 void
753 cbgen(int oint lab)
754 {
755         if (o < EQ || o > UGT)
756                 comperr("bad conditional branch: %s"opst[o]);
757         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
758 }
759
760 static void
761 fixcalls(NODE *pvoid *arg)
762 {
763         /* Prepare for struct return by allocating bounce space on stack */
764         switch (p->n_op) {
765         case STCALL:
766         case USTCALL:
767                 if (p->n_stsize+p2autooff > stkpos)
768                         stkpos = p->n_stsize+p2autooff;
769                 break;
770         }
771 }
772
773 void
774 myreader(struct interpass *ipole)
775 {
776         struct interpass *ip;
777
778         stkpos = p2autooff;
779         DLIST_FOREACH(ipipoleqelem) {
780                 if (ip->type != IP_NODE)
781                         continue;
782                 walkf(ip->ip_nodefixcalls0);
783         }
784         if (stkpos > p2autooff)
785                 p2autooff = stkpos;
786         if (stkpos > p2maxautooff)
787                 p2maxautooff = stkpos;
788         if (x2debug)
789                 printip(ipole);
790 }
791
792 /*
793  * Remove some PCONVs after OREGs are created.
794  */
795 static void
796 pconv2(NODE *pvoid *arg)
797 {
798         NODE *q;
799
800         if (p->n_op == PLUS) {
801                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
802                         if (p->n_right->n_op != ICON)
803                                 return;
804                         if (p->n_left->n_op != PCONV)
805                                 return;
806                         if (p->n_left->n_left->n_op != OREG)
807                                 return;
808                         q = p->n_left->n_left;
809                         nfree(p->n_left);
810                         p->n_left = q;
811                         /*
812                          * This will be converted to another OREG later.
813                          */
814                 }
815         }
816 }
817
818 void
819 mycanon(NODE *p)
820 {
821         walkf(ppconv20);
822 }
823
824 void
825 myoptim(struct interpass *ip)
826 {
827 }
828
829 void
830 rmove(int sint dTWORD t)
831 {
832
833         switch (t) {
ragge
1.11
834         case INT:
835         case UNSIGNED:
836                 printf("        movl %s,%s\n"rlong[s], rlong[d]);
mickey
1.1
837                 break;
838         case CHAR:
839         case UCHAR:
ragge
1.4
840                 printf("        movb %s,%s\n"rbyte[s], rbyte[d]);
841                 break;
842         case SHORT:
843         case USHORT:
844                 printf("        movw %s,%s\n"rshort[s], rshort[d]);
mickey
1.1
845                 break;
846         case FLOAT:
ragge
1.11
847                 printf("        movss %s,%s\n"rnames[s], rnames[d]);
848                 break;
mickey
1.1
849         case DOUBLE:
ragge
1.11
850                 printf("        movsd %s,%s\n"rnames[s], rnames[d]);
851                 break;
mickey
1.1
852         case LDOUBLE:
853                 /* a=b()*c(); will generate this */
854                 comperr("bad float rmove: %d %d"sd);
855                 break;
856         default:
ragge
1.11
857                 printf("        movq %s,%s\n"rnames[s], rnames[d]);
858                 break;
mickey
1.1
859         }
860 }
861
862 /*
863  * For class c, find worst-case displacement of the number of
864  * registers in the array r[] indexed by class.
865  */
866 int
867 COLORMAP(int cint *r)
868 {
869
870         switch (c) {
871         case CLASSA:
ragge
1.4
872                 return r[CLASSA] < 14;
mickey
1.1
873         case CLASSB:
ragge
1.4
874                 return r[CLASSB] < 16;
ragge
1.21
875         case CLASSC:
876                 return r[CLASSC] < CREGCNT;
mickey
1.1
877         }
878         return 0/* XXX gcc */
879 }
880
881 char *rnames[] = {
ragge
1.4
882         "%rax""%rdx""%rcx""%rbx""%rsi""%rdi""%rbp""%rsp",
883         "%r8""%r9""%r10""%r11""%r12""%r13""%r14""%r15",
884         "%xmm0""%xmm1""%xmm2""%xmm3""%xmm4""%xmm5""%xmm6""%xmm7",
885         "%xmm8""%xmm9""%xmm10""%xmm11""%xmm12""%xmm13""%xmm14",
886         "%xmm15",
887 };
888
889 /* register names for shorter sizes */
890 char *rbyte[] = {
891         "%al""%dl""%cl""%bl""%sil""%dil""%bpl""%spl",
892         "%r8b""%r9b""%r10b""%r11b""%r12b""%r13b""%r14b""%r15b"
893 };
894 char *rshort[] = {
895         "%ax""%dx""%cx""%bx""%si""%di""%bp""%sp",
896         "%r8w""%r9w""%r10w""%r11w""%r12w""%r13w""%r14w""%r15w"
897 };
898 char *rlong[] = {
mickey
1.1
899         "%eax""%edx""%ecx""%ebx""%esi""%edi""%ebp""%esp",
ragge
1.7
900         "%r8d""%r9d""%r10d""%r11d""%r12d""%r13d""%r14d""%r15d"
mickey
1.1
901 };
902
ragge
1.4
903
mickey
1.1
904 /*
905  * Return a class suitable for a specific type.
906  */
907 int
908 gclass(TWORD t)
909 {
ragge
1.21
910         if (t == LDOUBLE)
911                 return CLASSC;
912         if (t == FLOAT || t == DOUBLE)
mickey
1.1
913                 return CLASSB;
914         return CLASSA;
915 }
916
ragge
1.21
917 static int
918 argsiz(NODE *p)
919 {
920         TWORD t = p->n_type;
921
922         if (p->n_left->n_op == REG)
923                 return 0/* not on stack */
924         if (t == LDOUBLE)
925                 return 16;
926         if (p->n_op == STASG)
927                 return p->n_stsize;
928         return 8;
929 }
930
mickey
1.1
931 /*
932  * Calculate argument sizes.
933  */
934 void
935 lastcall(NODE *p)
936 {
937         NODE *op = p;
938         int size = 0;
939
940         p->n_qual = 0;
941         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
942                 return;
943         for (p = p->n_rightp->n_op == CMp = p->n_left)
944                 size += argsiz(p->n_right);
945         size += argsiz(p);
ragge
1.10
946         size = (size+15) & ~15;
947         if (size)
948                 printf("        subq $%d,%s\n"sizernames[RSP]);
mickey
1.1
949         op->n_qual = size/* XXX */
950 }
951
952 /*
953  * Special shapes.
954  */
955 int
956 special(NODE *pint shape)
957 {
958         int o = p->n_op;
959
960         switch (shape) {
961         case SFUNCALL:
962                 if (o == STCALL || o == USTCALL)
963                         return SRREG;
964                 break;
965         case SPCON:
966                 if (o != ICON || p->n_name[0] ||
967                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
968                         break;
969                 return SRDIR;
970         case SMIXOR:
971                 return tshape(pSZERO);
972         case SMILWXOR:
973                 if (o != ICON || p->n_name[0] ||
974                     p->n_lval == 0 || p->n_lval & 0xffffffff)
975                         break;
976                 return SRDIR;
977         case SMIHWXOR:
978                 if (o != ICON || p->n_name[0] ||
979                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
980                         break;
981                 return SRDIR;
ragge
1.12
982         case SCON32:
983                 if (o != ICON || p->n_name[0])
984                         break;
985                 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT)
986                         break;
987                 return SRDIR;
988         default:
989                 cerror("special: %x\n"shape);
mickey
1.1
990         }
991         return SRNOPE;
992 }
993
994 /*
995  * Target-dependent command-line options.
996  */
997 void
998 mflags(char *str)
999 {
1000 }
1001
1002 /*
1003  * Do something target-dependent for xasm arguments.
1004  */
1005 int
1006 myxasm(struct interpass *ipNODE *p)
1007 {
ragge
1.15
1008         return 0;
ragge
1.4
1009 #if 0
mickey
1.1
1010         struct interpass *ip2;
1011         NODE *in = 0, *ut = 0;
1012         TWORD t;
1013         char *w;
1014         int reg;
1015         int cw;
1016
1017         cw = xasmcode(p->n_name);
1018         if (cw & (XASMASG|XASMINOUT))
1019                 ut = p->n_left;
1020         if ((cw & XASMASG) == 0)
1021                 in = p->n_left;
1022
1023         switch (XASMVAL(cw)) {
1024         case 'D'reg = EDIbreak;
1025         case 'S'reg = ESIbreak;
1026         case 'a'reg = EAXbreak;
1027         case 'b'reg = EBXbreak;
1028         case 'c'reg = ECXbreak;
1029         case 'd'reg = EDXbreak;
1030         case 't'reg = 0break;
1031         case 'u'reg = 1break;
1032         case 'A'reg = EAXEDXbreak;
1033         case 'q'/* XXX let it be CLASSA as for now */
1034                 p->n_name = tmpstrdup(p->n_name);
1035                 w = strchr(p->n_name'q');
1036                 *w = 'r';
1037                 return 0;
1038         default:
1039                 return 0;
1040         }
1041         p->n_name = tmpstrdup(p->n_name);
1042         for (w = p->n_name; *ww++)
1043                 ;
1044         w[-1] = 'r'/* now reg */
1045         t = p->n_left->n_type;
1046         if (reg == EAXEDX) {
1047                 p->n_label = CLASSC;
1048         } else {
1049                 p->n_label = CLASSA;
1050                 if (t == CHAR || t == UCHAR) {
1051                         p->n_label = CLASSB;
1052                         reg = reg * 2 + 8;
1053                 }
1054         }
1055         if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
1056                 p->n_label = CLASSD;
1057                 reg += 037;
1058         }
1059
1060         if (in && ut)
1061                 in = tcopy(in);
1062         p->n_left = mklnode(REG0regt);
1063         if (ut) {
1064                 ip2 = ipnode(mkbinode(ASSIGNuttcopy(p->n_left), t));
1065                 DLIST_INSERT_AFTER(ipip2qelem);
1066         }
1067         if (in) {
1068                 ip2 = ipnode(mkbinode(ASSIGNtcopy(p->n_left), int));
1069                 DLIST_INSERT_BEFORE(ipip2qelem);
1070         }
ragge
1.4
1071 #endif
mickey
1.1
1072         return 1;
1073 }
1074
1075 void
1076 targarg(char *wvoid *arg)
1077 {
1078         NODE **ary = arg;
1079         NODE *p, *q;
1080
1081         p = ary[(int)w[1]-'0']->n_left;
1082         if (optype(p->n_op) != LTYPE)
1083                 comperr("bad xarg op %d"p->n_op);
1084         q = tcopy(p);
1085         if (q->n_op == REG) {
1086                 if (*w == 'k') {
1087                         q->n_type = INT;
1088                 } else if (*w != 'w') {
ragge
1.24
1089                         cerror("targarg"); /* XXX ??? */
mickey
1.1
1090                         if (q->n_type > UCHAR) {
1091                                 regno(q) = regno(q)*2+8;
1092                                 if (*w == 'h')
1093                                         regno(q)++;
1094                         }
1095                         q->n_type = INT;
1096                 } else
1097                         q->n_type = SHORT;
1098         }
1099         adrput(stdoutq);
1100         tfree(q);
1101 }
1102
1103 /*
1104  * target-specific conversion of numeric arguments.
1105  */
1106 int
1107 numconv(void *ipvoid *p1void *q1)
1108 {
1109         NODE *p = p1, *q = q1;
1110         int cw = xasmcode(q->n_name);
1111
1112         switch (XASMVAL(cw)) {
1113         case 'a':
1114         case 'b':
1115         case 'c':
1116         case 'd':
1117                 p->n_name = tmpcalloc(2);
1118                 p->n_name[0] = XASMVAL(cw);
1119                 return 1;
1120         default:
1121                 return 0;
1122         }
1123 }
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-10-31 22:35 +0100