Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110601084330

Diff

Diff from 1.45 to:

Annotations

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

Annotated File View

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