Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20150104191723

Diff

Diff from 1.60 to:

Annotations

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

Annotated File View

ragge
1.60
1 /*      $Id: local2.c,v 1.60 2015/01/04 19:17:23 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[];
ragge
1.47
45 static int needframe;
mickey
1.1
46
47 /*
48  * Print out the prolog assembler.
49  * addto and regoff are already calculated.
50  */
51 static void
52 prtprolog(struct interpass_prolog *ippint addto)
53 {
54         int i;
55
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))
plunky
1.51
65                         printf("\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
ragge
1.47
88 /*
89  * Traverse a tree to check if we need to emit a frame at all.
90  * We emit it if:
91  * - any function call
92  * - rsp or rbp referenced
93  * Return 1 if frame is needed, 0 otherwise.
94  */
95 static int
96 chkf(NODE *p)
97 {
98         int o = p->n_op;
99
100         if ((o == REG || o == OREG) && (regno(p) == RBP || regno(p) == RSP))
101                 return 1;
102         if (callop(o))
103                 return 1;
104         if (optype(o) == UTYPE)
105                 return chkf(p->n_left);
106         else if (optype(o) == BITYPE)
107                 return chkf(p->n_left) || chkf(p->n_right);
108         return 0;
109 }
110
111 static int
112 chkframe(struct interpass_prolog *ipp)
113 {
114         struct interpass *ip;
115
116         DLIST_FOREACH(ip, &ipp->ipp_ipqelem) {
117                 if (ip->type == IP_EPILOG)
118                         break;
119                 if (ip->type == IP_NODE) {
120                         if (chkf(ip->ip_node))
121                                 return 1;
122                 }
123         }
124         return 0;
125 }
126
mickey
1.1
127 void
128 prologue(struct interpass_prolog *ipp)
129 {
130         int addto;
131
132         ftype = ipp->ipp_type;
133
ragge
1.47
134         if (xdeljumps)
135                 needframe = chkframe(ipp);
ragge
1.48
136         else
137                 needframe = 1;
ragge
1.47
138
mickey
1.1
139 #ifdef LANG_F77
140         if (ipp->ipp_vis)
141                 printf("        .globl %s\n"ipp->ipp_name);
ragge
1.10
142         printf("        .align 16\n");
mickey
1.1
143         printf("%s:\n"ipp->ipp_name);
144 #endif
145         /*
146          * We here know what register to save and how much to 
147          * add to the stack.
148          */
149         addto = offcalc(ipp);
ragge
1.47
150         if (addto)
151                 needframe = 1;
152         if (needframe)
153                 prtprolog(ippaddto);
mickey
1.1
154 }
155
156 void
157 eoftn(struct interpass_prolog *ipp)
158 {
159         int i;
160
161         if (ipp->ipp_ip.ip_lbl == 0)
162                 return/* no code needs to be generated */
163
ragge
1.47
164         if (needframe) {
165                 /* return from function code */
166                 for (i = 0i < MAXREGSi++)
167                         if (TESTBIT(ipp->ipp_regsi))
plunky
1.51
168                                 printf("        movq -%d(%s),%s\n",
ragge
1.47
169                                     regoff[i], rnames[FPREG], rnames[i]);
170
171                 /* struct return needs special treatment */
172                 if (ftype == STRTY || ftype == UNIONTY) {
173                         printf("        movl 8(%%ebp),%%eax\n");
174                         printf("        leave\n");
175                         printf("        ret $%d\n"4);
176                 } else {
177                         printf("        leave\n");
178                         printf("        ret\n");
179                 }
180         } else
181                 printf("\tret\n");
mickey
1.1
182
ragge
1.37
183 #ifndef MACHOABI
ragge
1.10
184         printf("\t.size %s,.-%s\n"ipp->ipp_nameipp->ipp_name);
ragge
1.37
185 #endif
mickey
1.1
186 }
187
188 /*
189  * add/sub/...
190  *
191  * Param given:
192  */
193 void
194 hopcode(int fint o)
195 {
196         char *str;
197
198         switch (o) {
199         case PLUS:
200                 str = "add";
201                 break;
202         case MINUS:
203                 str = "sub";
204                 break;
205         case AND:
206                 str = "and";
207                 break;
208         case OR:
209                 str = "or";
210                 break;
211         case ER:
212                 str = "xor";
213                 break;
214         default:
215                 comperr("hopcode2: %d"o);
216                 str = 0/* XXX gcc */
217         }
218         printf("%s%c"strf);
219 }
220
221 /*
222  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
223  */
224 int
mickey
1.2
225 tlen(NODE *p)
mickey
1.1
226 {
227         switch(p->n_type) {
228                 case CHAR:
229                 case UCHAR:
230                         return(1);
231
232                 case SHORT:
233                 case USHORT:
234                         return(SZSHORT/SZCHAR);
235
236                 case DOUBLE:
237                         return(SZDOUBLE/SZCHAR);
238
239                 case INT:
240                 case UNSIGNED:
241                         return(SZINT/SZCHAR);
242
243                 case LONG:
244                 case ULONG:
245                 case LONGLONG:
246                 case ULONGLONG:
247                         return SZLONGLONG/SZCHAR;
248
249                 default:
250                         if (!ISPTR(p->n_type))
251                                 comperr("tlen type %d not pointer");
252                         return SZPOINT(p->n_type)/SZCHAR;
253                 }
254 }
255
ragge
1.19
256 /*
257  * Compare two floating point numbers.
258  */
259 static void
260 fcomp(NODE *p)  
261 {
262
ragge
1.33
263         if (p->n_left->n_op != REG)
ragge
1.19
264                 comperr("bad compare %p\n"p);
ragge
1.33
265         if ((p->n_su & DORIGHT) == 0)
plunky
1.49
266                 expand(p0"\tfxch\n");
267         expand(p0"\tfucomip %st(1),%st\n"); /* emit compare insn  */
268         expand(p0"\tfstp %st(0)\n");        /* pop fromstack */
ragge
1.33
269         zzzcode(p'U');
ragge
1.19
270 }
271
mickey
1.1
272 int
273 fldexpand(NODE *pint cookiechar **cp)
274 {
ragge
1.44
275         comperr("fldexpand");
276         return 0;
mickey
1.1
277 }
278
279 static void
ragge
1.21
280 stasg(NODE *p)
mickey
1.1
281 {
ragge
1.60
282         struct attr *ap = attr_find(p->n_apATTR_P2STRUCT);
ragge
1.21
283         expand(pINAREG"     leaq AL,%rdi\n");
ragge
1.60
284         if (ap->iarg(0) >= 8)
285                 printf("\tmovl $%d,%%ecx\n\trep movsq\n"ap->iarg(0) >> 3);
286         if (ap->iarg(0) & 4)
ragge
1.21
287                 printf("\tmovsl\n");
ragge
1.60
288         if (ap->iarg(0) & 2)
ragge
1.21
289                 printf("\tmovsw\n");
ragge
1.60
290         if (ap->iarg(0) & 1)
ragge
1.21
291                 printf("\tmovsb\n");
mickey
1.1
292 }
293
ragge
1.25
294 #define E(x)    expand(p, 0, x)
mickey
1.1
295 /*
ragge
1.7
296  * Generate code to convert an unsigned long to xmm float/double.
mickey
1.1
297  */
298 static void
ragge
1.7
299 ultofd(NODE *p)
mickey
1.1
300 {
301
ragge
1.7
302         E("     movq AL,A1\n");
ragge
1.9
303         E("     testq A1,A1\n");
ragge
1.7
304         E("     js 2f\n");
305         E("     cvtsi2sZfq A1,A3\n");
306         E("     jmp 3f\n");
307         E("2:\n");
308         E("     movq A1,A2\n");
309         E("     shrq A2\n");
ragge
1.9
310         E("     andq $1,A1\n");
ragge
1.7
311         E("     orq A1,A2\n");
312         E("     cvtsi2sZfq A2,A3\n");
313         E("     addsZf A3,A3\n");
314         E("3:\n");
ragge
1.25
315 }
316
317 /*
318  * Generate code to convert an x87 long double to an unsigned long.
319  * This is ugly :-/
320  */
321 static void
322 ldtoul(NODE *p)
323 {
324
325         E("     subq $16,%rsp\n");
326         E("     movl $0x5f000000,(%rsp)\n"); /* More than long can have */
327         E("     flds (%rsp)\n");
328         if (p->n_left->n_op == REG) {
ragge
1.40
329                 E("     fxch\n");
ragge
1.25
330         } else
331                 E("     fldt AL\n");
332         E("     fucomi %st(1), %st\n");
333         E("     jae 2f\n");
334
335         E("     fstp %st(1)\n");         /* Pop huge val from stack */
336         E("     fnstcw (%rsp)\n");       /* store cw */
337         E("     movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
338         E("     fldcw 4(%rsp)\n");       /* new cw */
339         E("     fistpll 8(%rsp)\n");     /* save val */
340         E("     fldcw (%rsp)\n");        /* fetch old cw */
341         E("     movq 8(%rsp),A1\n");
342
343         E("     jmp 3f\n");
344
345         E("2:\n");
346
347         E("     fsubp %st, %st(1)\n");
348         E("     fnstcw (%rsp)\n");      
349         E("     movw $0x0f3f,4(%rsp)\n");
350         E("     fldcw 4(%rsp)\n");
351         E("     fistpll 8(%rsp)\n");
352         E("     fldcw (%rsp)\n");
353         E("     movabsq $0x8000000000000000,A1\n");
354         E("     xorq 8(%rsp),A1\n");
355
356         E("3:   addq $16,%rsp\n");
357 }
ragge
1.26
358
359 /*
360  * Generate code to convert an SSE float/double to an unsigned long.
361  */     
362 static void     
363 fdtoul(NODE *p
364 {
ragge
1.41
365         if (p->n_left->n_type == FLOAT)
366                 E("     movabsq $0x5f000000,A1\n");
367         else
368                 E("     movabsq $0x43e0000000000000,A1\n");
ragge
1.26
369         E("     movd A1,A3\n");
ragge
1.41
370         E("     ucomisZg A3,AL\n");
ragge
1.26
371         E("     jae 2f\n");
ragge
1.41
372         E("     cvttsZg2siq AL,A1\n");
ragge
1.26
373         E("     jmp 3f\n");
374         E("2:\n");
ragge
1.41
375         E("     subsZg A3,AL\n");
376         E("     cvttsZg2siq AL,A1\n");
ragge
1.26
377         E("     movabsq $0x8000000000000000,A2\n");
378         E("     xorq A2,A1\n");
379         E("3:\n");
380 }
ragge
1.7
381 #undef E
mickey
1.1
382
383 void
384 zzzcode(NODE *pint c)
385 {
ragge
1.60
386         struct attr *ap, *ap2;
ragge
1.6
387         NODE *l;
ragge
1.7
388         int prlrs;
ragge
1.14
389         char **rt;
mickey
1.1
390
391         switch (c) {
392         case 'A'/* swap st0 and st1 if right is evaluated second */
393                 if ((p->n_su & DORIGHT) == 0) {
394                         if (logop(p->n_op))
395                                 printf("        fxch\n");
396                         else
397                                 printf("r");
398                 }
399                 break;
400
ragge
1.25
401         case 'B'/* ldouble to unsigned long cast */
402                 ldtoul(p);
403                 break;
404
ragge
1.26
405         case 'b'/* float/double to unsigned long cast */
406                 fdtoul(p);
407                 break;
408
mickey
1.1
409         case 'C':  /* remove from stack after subroutine call */
410                 pr = p->n_qual;
411                 if (p->n_op == UCALL)
412                         return/* XXX remove ZC from UCALL */
413                 if (pr)
ragge
1.10
414                         printf("        addq $%d, %s\n"prrnames[RSP]);
ragge
1.53
415 #define STRREG 6
416 #define STRSSE 8
417 #define STRIF  9
418 #define STRFI  10
ragge
1.54
419 #define STRX87 11
ragge
1.60
420                 ap = attr_find(p->n_apATTR_P2STRUCT);
421                 ap2 = attr_find(p->n_apATTR_AMD64_CMPLRET);
ragge
1.54
422                 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
ragge
1.60
423                     ap->iarg(0) == 32 && ap2->iarg(0) == STRX87) {
ragge
1.54
424                         printf("\tfstpt -%d(%%rbp)\n"stkpos);
425                         printf("\tfstpt -%d(%%rbp)\n"stkpos-16);
426                         printf("\tleaq -%d(%%rbp),%%rax\n"stkpos);
427                 }
428                 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
ragge
1.60
429                     ap->iarg(0) <= 16) {
ragge
1.46
430                         /* store reg-passed structs on stack */
ragge
1.60
431                         if (ap2->iarg(0) == STRREG || ap2->iarg(0) == STRIF)
ragge
1.53
432                                 printf("\tmovq %%rax,-%d(%%rbp)\n"stkpos);
433                         else
434                                 printf("\tmovsd %%xmm0,-%d(%%rbp)\n"stkpos);
ragge
1.60
435                         if (ap->iarg(0) > 8) {
436                                 if (ap2->iarg(0) == STRREG)
ragge
1.57
437                                         printf("\tmovq %%rdx");
ragge
1.60
438                                 else if (ap2->iarg(0) == STRFI)
ragge
1.57
439                                         printf("\tmovq %%rax");
ragge
1.60
440                                 else if (ap2->iarg(0) == STRIF)
ragge
1.57
441                                         printf("\tmovsd %%xmm0");
ragge
1.53
442                                 else
ragge
1.57
443                                         printf("\tmovsd %%xmm1");
444                                 printf(",-%d(%%rbp)\n"stkpos-8);
ragge
1.53
445                         }
ragge
1.46
446                         printf("\tleaq -%d(%%rbp),%%rax\n"stkpos);
447                 }
mickey
1.1
448                 break;
449
450         case 'F'/* Structure argument */
ragge
1.60
451                 ap = attr_find(p->n_apATTR_P2STRUCT);
452                 printf("        subq $%d,%%rsp\n"ap->iarg(0));
ragge
1.21
453                 printf("        movq %%rsp,%%rsi\n");
454                 stasg(p);
mickey
1.1
455                 break;
ragge
1.19
456
457         case 'G'/* Floating point compare */
458                 fcomp(p);
459                 break;
460
ragge
1.7
461         case 'j'/* convert unsigned long to f/d */
462                 ultofd(p);
mickey
1.1
463                 break;
464
465         case 'M'/* Output sconv move, if needed */
466                 l = getlr(p'L');
467                 /* XXX fixneed: regnum */
468                 pr = DECRA(p->n_reg0);
469                 lr = DECRA(l->n_reg0);
ragge
1.6
470                 if (pr == lr)
471                         break;
472                 printf("        movb %s,%s\n"rbyte[lr], rbyte[pr]);
mickey
1.1
473                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
474                 break;
475
ragge
1.27
476         case 'N'/* output long reg name */
477                 printf("%s"rlong[getlr(p'1')->n_rval]);
478                 break;
479
ragge
1.16
480         case 'P'/* Put hidden argument in rdi */
ragge
1.60
481                 ap = attr_find(p->n_apATTR_P2STRUCT);
482                 ap2 = attr_find(p->n_apATTR_AMD64_CMPLRET);
483                 if (ap->iarg(0) > 16 && ap2->iarg(0) != STRX87)
ragge
1.46
484                         printf("\tleaq -%d(%%rbp),%%rdi\n"stkpos);
ragge
1.16
485                 break;
486
ragge
1.10
487         case 'Q'/* emit struct assign */
ragge
1.21
488                 stasg(p);
ragge
1.10
489                 break;
490
ragge
1.7
491         case 'R'/* print opname based on right type */
492         case 'L'/* print opname based on left type */
493                 switch (getlr(pc)->n_type) {
494                 case CHARcase UCHARs = 'b'break;
495                 case SHORTcase USHORTs = 'w'break;
496                 case INTcase UNSIGNEDs = 'l'break;
497                 defaults = 'q'break;
498                 printf("%c"s);
499                 }
500                 break;
ragge
1.14
501
ragge
1.28
502         case 'U': { /* output branch insn for ucomi */
503                 static char *fpcb[] = { "jz""jnz""jbe""jc""jnc""ja" };
504                 if (p->n_op < EQ || p->n_op > GT)
505                         comperr("bad fp branch");
ragge
1.33
506                 if (p->n_op == NE || p->n_op == GT || p->n_op == GE)
507                         expand(p0"  jp LC\n");
508                 else if (p->n_op == EQ)
509                         printf("\tjp 1f\n");
ragge
1.28
510                 printf("        %s "fpcb[p->n_op - EQ]);
511                 expand(p0"LC\n");
ragge
1.33
512                 if (p->n_op == EQ)
513                         printf("1:\n");
ragge
1.28
514                 break;
515                 }
516
ragge
1.14
517         case '8'/* special reg name printout (64-bit) */
518         case '1'/* special reg name printout (32-bit) */
ragge
1.7
519                 l = getlr(p'1');
ragge
1.14
520                 rt = c == '8' ? rnames : rlong;
521                 printf("%s"rt[l->n_rval]);
ragge
1.7
522                 break;
523
524         case 'g':
525                 p = p->n_left;
526                 /* FALLTHROUGH */
527         case 'f'/* float or double */
528                 printf("%c"p->n_type == FLOAT ? 's' : 'd');
529                 break;
530
531         case 'q'/* int or long */
532                 printf("%c"p->n_left->n_type == LONG ? 'q' : ' ');
533                 break;
534
mickey
1.1
535         default:
536                 comperr("zzzcode %c"c);
537         }
538 }
539
540 int canaddr(NODE *);
541 int
542 canaddr(NODE *p)
543 {
544         int o = p->n_op;
545
546         if (o==NAME || o==REG || o==ICON || o==OREG ||
547             (o==UMUL && shumul(p->n_leftSOREG)))
548                 return(1);
549         return(0);
550 }
551
552 /*
553  * Does the bitfield shape match?
554  */
555 int
556 flshape(NODE *p)
557 {
ragge
1.44
558         comperr("flshape");
559         return(0);
mickey
1.1
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:
plunky
1.51
643                 printf("%%%s", &rnames[p->n_rval][3]);
mickey
1.1
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:
plunky
1.51
653                 printf("$" CONFMTp->n_lval >> 32);
mickey
1.1
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         switch (p->n_op) {
668
669         case NAME:
670                 if (p->n_name[0] != '\0') {
ragge
1.23
671                         if (p->n_lval != 0)
672                                 fprintf(ioCONFMT "+"p->n_lval);
ragge
1.22
673                         fprintf(io"%s(%%rip)"p->n_name);
mickey
1.1
674                 } else
675                         fprintf(ioCONFMTp->n_lval);
676                 return;
677
678         case OREG:
679                 r = p->n_rval;
680                 if (p->n_name[0])
681                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
682                 if (p->n_lval)
ragge
1.17
683                         fprintf(io"%lld"p->n_lval);
mickey
1.1
684                 if (R2TEST(r)) {
ragge
1.18
685                         int r1 = R2UPK1(r);
686                         int r2 = R2UPK2(r);
687                         int sh = R2UPK3(r);
688
689                         fprintf(io"(%s,%s,%d)"
690                             r1 == MAXREGS ? "" : rnames[r1],
691                             r2 == MAXREGS ? "" : rnames[r2], sh);
mickey
1.1
692                 } else
693                         fprintf(io"(%s)"rnames[p->n_rval]);
694                 return;
695         case ICON:
696                 /* addressable value of the constant */
697                 fputc('$'io);
698                 conput(iop);
699                 return;
700
701         case REG:
702                 switch (p->n_type) {
ragge
1.5
703                 case CHAR:
704                 case UCHAR:
705                         rc = rbyte;
mickey
1.1
706                         break;
707                 case SHORT:
708                 case USHORT:
ragge
1.5
709                         rc = rshort;
710                         break;
711                 case INT:
712                 case UNSIGNED:
713                         rc = rlong;
mickey
1.1
714                         break;
715                 default:
ragge
1.5
716                         rc = rnames;
717                         break;
mickey
1.1
718                 }
ragge
1.5
719                 fprintf(io"%s"rc[p->n_rval]);
mickey
1.1
720                 return;
721
722         default:
723                 comperr("illegal address, op %d, node %p"p->n_opp);
724                 return;
725
726         }
727 }
728
729 static char *
730 ccbranches[] = {
731         "je",           /* jumpe */
732         "jne",          /* jumpn */
733         "jle",          /* jumple */
734         "jl",           /* jumpl */
735         "jge",          /* jumpge */
736         "jg",           /* jumpg */
737         "jbe",          /* jumple (jlequ) */
738         "jb",           /* jumpl (jlssu) */
739         "jae",          /* jumpge (jgequ) */
740         "ja",           /* jumpg (jgtru) */
741 };
742
743
744 /*   printf conditional and unconditional branches */
745 void
746 cbgen(int oint lab)
747 {
748         if (o < EQ || o > UGT)
749                 comperr("bad conditional branch: %s"opst[o]);
750         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
751 }
752
ragge
1.50
753 /*
754  * gcc xasm has the ability to generate different asm types
755  * via some magic.
756  *
757  * Only support AT&T asm for now.
758  */
759 static char *
760 adjustname(char *s)
761 {
762         int len = strlen(s);
763         char *d = tmpalloc(len+1);
764         int ijflvltlvl;
765
766         flvl = tlvl = 0;
767         for (i = j = 0i < leni++) {
768                 switch (s[i]) {
769                 case '{'tlvl++; break;
770                 case '}'if (tlvl)tlvl--; else flvl--; break;
771                 case '|'tlvl--; flvl++; break;
772                 default:
773                         if (flvl == 0)
774                                 d[j++] = s[i];
775                         break;
776                 }
777         }
778         d[j] = 0;
779         return d;
780 }
781
mickey
1.1
782 static void
783 fixcalls(NODE *pvoid *arg)
784 {
ragge
1.57
785         int ps;
786
mickey
1.1
787         /* Prepare for struct return by allocating bounce space on stack */
788         switch (p->n_op) {
789         case STCALL:
790         case USTCALL:
ragge
1.60
791                 ps = attr_find(p->n_apATTR_P2STRUCT)->iarg(0);
ragge
1.57
792                 if (ps < 16)
793                         ps = 16;
794                 if (ps+p2autooff > stkpos)
795                         stkpos = ps+p2autooff;
mickey
1.1
796                 break;
ragge
1.50
797         case XASM:
798                 p->n_name = adjustname(p->n_name);
799                 break;
mickey
1.1
800         }
801 }
802
803 void
804 myreader(struct interpass *ipole)
805 {
806         struct interpass *ip;
807
808         stkpos = p2autooff;
809         DLIST_FOREACH(ipipoleqelem) {
810                 if (ip->type != IP_NODE)
811                         continue;
812                 walkf(ip->ip_nodefixcalls0);
813         }
814         if (stkpos > p2autooff)
815                 p2autooff = stkpos;
816         if (stkpos > p2maxautooff)
817                 p2maxautooff = stkpos;
818         if (x2debug)
819                 printip(ipole);
820 }
821
822 /*
823  * Remove some PCONVs after OREGs are created.
824  */
825 static void
826 pconv2(NODE *pvoid *arg)
827 {
828         NODE *q;
829
830         if (p->n_op == PLUS) {
831                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
832                         if (p->n_right->n_op != ICON)
833                                 return;
834                         if (p->n_left->n_op != PCONV)
835                                 return;
836                         if (p->n_left->n_left->n_op != OREG)
837                                 return;
838                         q = p->n_left->n_left;
839                         nfree(p->n_left);
840                         p->n_left = q;
841                         /*
842                          * This will be converted to another OREG later.
843                          */
844                 }
845         }
846 }
847
848 void
849 mycanon(NODE *p)
850 {
851         walkf(ppconv20);
852 }
853
854 void
855 myoptim(struct interpass *ip)
856 {
857 }
858
859 void
860 rmove(int sint dTWORD t)
861 {
862
863         switch (t) {
ragge
1.11
864         case INT:
865         case UNSIGNED:
866                 printf("        movl %s,%s\n"rlong[s], rlong[d]);
mickey
1.1
867                 break;
868         case CHAR:
869         case UCHAR:
ragge
1.4
870                 printf("        movb %s,%s\n"rbyte[s], rbyte[d]);
871                 break;
872         case SHORT:
873         case USHORT:
874                 printf("        movw %s,%s\n"rshort[s], rshort[d]);
mickey
1.1
875                 break;
876         case FLOAT:
ragge
1.11
877                 printf("        movss %s,%s\n"rnames[s], rnames[d]);
878                 break;
mickey
1.1
879         case DOUBLE:
ragge
1.11
880                 printf("        movsd %s,%s\n"rnames[s], rnames[d]);
881                 break;
mickey
1.1
882         case LDOUBLE:
ragge
1.32
883 #ifdef notdef
mickey
1.1
884                 /* a=b()*c(); will generate this */
ragge
1.32
885                 /* XXX can it fail anyway? */
mickey
1.1
886                 comperr("bad float rmove: %d %d"sd);
ragge
1.32
887 #endif
mickey
1.1
888                 break;
889         default:
ragge
1.11
890                 printf("        movq %s,%s\n"rnames[s], rnames[d]);
891                 break;
mickey
1.1
892         }
893 }
894
895 /*
896  * For class c, find worst-case displacement of the number of
897  * registers in the array r[] indexed by class.
898  */
899 int
900 COLORMAP(int cint *r)
901 {
902
903         switch (c) {
904         case CLASSA:
ragge
1.4
905                 return r[CLASSA] < 14;
mickey
1.1
906         case CLASSB:
ragge
1.4
907                 return r[CLASSB] < 16;
ragge
1.21
908         case CLASSC:
909                 return r[CLASSC] < CREGCNT;
mickey
1.1
910         }
911         return 0/* XXX gcc */
912 }
913
914 char *rnames[] = {
ragge
1.4
915         "%rax""%rdx""%rcx""%rbx""%rsi""%rdi""%rbp""%rsp",
916         "%r8""%r9""%r10""%r11""%r12""%r13""%r14""%r15",
917         "%xmm0""%xmm1""%xmm2""%xmm3""%xmm4""%xmm5""%xmm6""%xmm7",
918         "%xmm8""%xmm9""%xmm10""%xmm11""%xmm12""%xmm13""%xmm14",
919         "%xmm15",
920 };
921
922 /* register names for shorter sizes */
923 char *rbyte[] = {
924         "%al""%dl""%cl""%bl""%sil""%dil""%bpl""%spl",
925         "%r8b""%r9b""%r10b""%r11b""%r12b""%r13b""%r14b""%r15b"
926 };
927 char *rshort[] = {
928         "%ax""%dx""%cx""%bx""%si""%di""%bp""%sp",
929         "%r8w""%r9w""%r10w""%r11w""%r12w""%r13w""%r14w""%r15w"
930 };
931 char *rlong[] = {
mickey
1.1
932         "%eax""%edx""%ecx""%ebx""%esi""%edi""%ebp""%esp",
ragge
1.7
933         "%r8d""%r9d""%r10d""%r11d""%r12d""%r13d""%r14d""%r15d"
mickey
1.1
934 };
935
ragge
1.4
936
mickey
1.1
937 /*
938  * Return a class suitable for a specific type.
939  */
940 int
941 gclass(TWORD t)
942 {
ragge
1.21
943         if (t == LDOUBLE)
944                 return CLASSC;
945         if (t == FLOAT || t == DOUBLE)
mickey
1.1
946                 return CLASSB;
947         return CLASSA;
948 }
949
ragge
1.21
950 static int
951 argsiz(NODE *p)
952 {
953         TWORD t = p->n_type;
954
955         if (p->n_left->n_op == REG)
956                 return 0/* not on stack */
957         if (t == LDOUBLE)
958                 return 16;
959         if (p->n_op == STASG)
ragge
1.60
960                 return attr_find(p->n_apATTR_P2STRUCT)->iarg(0);
ragge
1.21
961         return 8;
962 }
963
mickey
1.1
964 /*
965  * Calculate argument sizes.
966  */
967 void
968 lastcall(NODE *p)
969 {
970         NODE *op = p;
971         int size = 0;
972
973         p->n_qual = 0;
974         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
975                 return;
976         for (p = p->n_rightp->n_op == CMp = p->n_left)
977                 size += argsiz(p->n_right);
978         size += argsiz(p);
ragge
1.10
979         size = (size+15) & ~15;
980         if (size)
981                 printf("        subq $%d,%s\n"sizernames[RSP]);
mickey
1.1
982         op->n_qual = size/* XXX */
983 }
984
985 /*
986  * Special shapes.
987  */
988 int
989 special(NODE *pint shape)
990 {
991         int o = p->n_op;
992
993         switch (shape) {
994         case SFUNCALL:
995                 if (o == STCALL || o == USTCALL)
996                         return SRREG;
997                 break;
998         case SPCON:
999                 if (o != ICON || p->n_name[0] ||
1000                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
1001                         break;
1002                 return SRDIR;
1003         case SMIXOR:
1004                 return tshape(pSZERO);
1005         case SMILWXOR:
1006                 if (o != ICON || p->n_name[0] ||
1007                     p->n_lval == 0 || p->n_lval & 0xffffffff)
1008                         break;
1009                 return SRDIR;
1010         case SMIHWXOR:
1011                 if (o != ICON || p->n_name[0] ||
1012                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
1013                         break;
1014                 return SRDIR;
ragge
1.12
1015         case SCON32:
1016                 if (o != ICON || p->n_name[0])
1017                         break;
1018                 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT)
1019                         break;
1020                 return SRDIR;
1021         default:
1022                 cerror("special: %x\n"shape);
mickey
1.1
1023         }
1024         return SRNOPE;
1025 }
1026
1027 /*
1028  * Target-dependent command-line options.
1029  */
1030 void
1031 mflags(char *str)
1032 {
1033 }
1034
1035 /*
1036  * Do something target-dependent for xasm arguments.
1037  */
1038 int
1039 myxasm(struct interpass *ipNODE *p)
1040 {
1041         struct interpass *ip2;
ragge
1.30
1042         int Cmax[] = { 31631270xffff3255 };
mickey
1.1
1043         NODE *in = 0, *ut = 0;
1044         TWORD t;
1045         char *w;
1046         int reg;
ragge
1.30
1047         int ccwv;
mickey
1.1
1048
1049         cw = xasmcode(p->n_name);
1050         if (cw & (XASMASG|XASMINOUT))
1051                 ut = p->n_left;
1052         if ((cw & XASMASG) == 0)
1053                 in = p->n_left;
1054
ragge
1.39
1055         c = XASMVAL(cw);
1056 retry:  switch (c) {
ragge
1.30
1057         case 'D'reg = RDIbreak;
1058         case 'S'reg = RSIbreak;
ragge
1.35
1059         case 'A'
ragge
1.30
1060         case 'a'reg = RAXbreak;
1061         case 'b'reg = RBXbreak;
1062         case 'c'reg = RCXbreak;
1063         case 'd'reg = RDXbreak;
1064
ragge
1.43
1065         case 'Q'reg = RDXbreak/* Always dx for now */
1066
ragge
1.38
1067         case 'x':
ragge
1.34
1068         case 'q':
ragge
1.30
1069         case 't':
1070         case 'u':
mickey
1.1
1071                 p->n_name = tmpstrdup(p->n_name);
ragge
1.31
1072                 w = strchr(p->n_namec);
ragge
1.30
1073                 *w =