Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101111194553

Diff

Diff from 1.32 to:

Annotations

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

Annotated File View

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