Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20110921212309

Diff

Diff from 1.49 to:

Annotations

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

Annotated File View

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