Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110821090748

Diff

Diff from 1.47 to:

Annotations

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

Annotated File View

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