Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101204204243

Diff

Diff from 1.35 to:

Annotations

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

Annotated File View

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