Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101222152204

Diff

Diff from 1.38 to:

Annotations

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

Annotated File View

ragge
1.38
1 /*      $Id: local2.c,v 1.38 2010/12/22 15:22:04 ragge Exp $    */
mickey
1.1
2 /*
3  * Copyright (c) 2008 Michael Shalayeff
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 # include "pass2.h"
31 # include <ctype.h>
32 # include <string.h>
33
34 static int stkpos;
35
36 void
37 deflab(int label)
38 {
39         printf(LABFMT ":\n"label);
40 }
41
ragge
1.11
42 static int regoff[MAXREGS];
mickey
1.1
43 static TWORD ftype;
ragge
1.4
44 char *rbyte[], *rshort[], *rlong[];
mickey
1.1
45
46 /*
47  * Print out the prolog assembler.
48  * addto and regoff are already calculated.
49  */
50 static void
51 prtprolog(struct interpass_prolog *ippint addto)
52 {
53         int i;
54
ragge
1.5
55         /* XXX should look if there is any need to emit this */
mickey
1.2
56         printf("\tpushq %%rbp\n");
57         printf("\tmovq %%rsp,%%rbp\n");
ragge
1.10
58         addto = (addto+15) & ~15/* 16-byte aligned */
mickey
1.1
59         if (addto)
mickey
1.2
60                 printf("\tsubq $%d,%%rsp\n"addto);
ragge
1.10
61
62         /* save permanent registers */
mickey
1.1
63         for (i = 0i < MAXREGSi++)
ragge
1.10
64                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.11
65                         fprintf(stdout"\tmovq %s,-%d(%s)\n",
mickey
1.1
66                             rnames[i], regoff[i], rnames[FPREG]);
ragge
1.4
67 }
mickey
1.1
68
69 /*
70  * calculate stack size and offsets
71  */
72 static int
73 offcalc(struct interpass_prolog *ipp)
74 {
75         int iaddto;
76
77         addto = p2maxautooff;
78         if (addto >= AUTOINIT/SZCHAR)
79                 addto -= AUTOINIT/SZCHAR;
80         for (i = 0i < MAXREGSi++)
81                 if (TESTBIT(ipp->ipp_regsi)) {
ragge
1.10
82                         addto += SZLONG/SZCHAR;
mickey
1.1
83                         regoff[i] = addto;
84                 }
85         return addto;
86 }
87
88 void
89 prologue(struct interpass_prolog *ipp)
90 {
91         int addto;
92
93         ftype = ipp->ipp_type;
94
95 #ifdef LANG_F77
96         if (ipp->ipp_vis)
97                 printf("        .globl %s\n"ipp->ipp_name);
ragge
1.10
98         printf("        .align 16\n");
mickey
1.1
99         printf("%s:\n"ipp->ipp_name);
100 #endif
101         /*
102          * We here know what register to save and how much to 
103          * add to the stack.
104          */
105         addto = offcalc(ipp);
106         prtprolog(ippaddto);
107 }
108
109 void
110 eoftn(struct interpass_prolog *ipp)
111 {
112         int i;
113
114         if (ipp->ipp_ip.ip_lbl == 0)
115                 return/* no code needs to be generated */
116
117         /* return from function code */
118         for (i = 0i < MAXREGSi++)
119                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.10
120                         fprintf(stdout"       movq -%d(%s),%s\n",
mickey
1.1
121                             regoff[i], rnames[FPREG], rnames[i]);
122
123         /* struct return needs special treatment */
124         if (ftype == STRTY || ftype == UNIONTY) {
125                 printf("        movl 8(%%ebp),%%eax\n");
126                 printf("        leave\n");
127                 printf("        ret $%d\n"4);
128         } else {
129                 printf("        leave\n");
ragge
1.11
130                 printf("        ret\n");
mickey
1.1
131         }
ragge
1.37
132 #ifndef MACHOABI
ragge
1.10
133         printf("\t.size %s,.-%s\n"ipp->ipp_nameipp->ipp_name);
ragge
1.37
134 #endif
mickey
1.1
135 }
136
137 /*
138  * add/sub/...
139  *
140  * Param given:
141  */
142 void
143 hopcode(int fint o)
144 {
145         char *str;
146
147         switch (o) {
148         case PLUS:
149                 str = "add";
150                 break;
151         case MINUS:
152                 str = "sub";
153                 break;
154         case AND:
155                 str = "and";
156                 break;
157         case OR:
158                 str = "or";
159                 break;
160         case ER:
161                 str = "xor";
162                 break;
163         default:
164                 comperr("hopcode2: %d"o);
165                 str = 0/* XXX gcc */
166         }
167         printf("%s%c"strf);
168 }
169
170 /*
171  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
172  */
173 int
mickey
1.2
174 tlen(NODE *p)
mickey
1.1
175 {
176         switch(p->n_type) {
177                 case CHAR:
178                 case UCHAR:
179                         return(1);
180
181                 case SHORT:
182                 case USHORT:
183                         return(SZSHORT/SZCHAR);
184
185                 case DOUBLE:
186                         return(SZDOUBLE/SZCHAR);
187
188                 case INT:
189                 case UNSIGNED:
190                         return(SZINT/SZCHAR);
191
192                 case LONG:
193                 case ULONG:
194                 case LONGLONG:
195                 case ULONGLONG:
196                         return SZLONGLONG/SZCHAR;
197
198                 default:
199                         if (!ISPTR(p->n_type))
200                                 comperr("tlen type %d not pointer");
201                         return SZPOINT(p->n_type)/SZCHAR;
202                 }
203 }
204
ragge
1.19
205 /*
206  * Compare two floating point numbers.
207  */
208 static void
209 fcomp(NODE *p)  
210 {
211
ragge
1.33
212         if (p->n_left->n_op != REG)
ragge
1.19
213                 comperr("bad compare %p\n"p);
ragge
1.33
214         if ((p->n_su & DORIGHT) == 0)
215                 expand(p0"  fxch\n");
216         expand(p0"  fucomip %st(1),%st\n"); /* emit compare insn  */
217         expand(p0"  fstp %st(0)\n");        /* pop fromstack */
218         zzzcode(p'U');
ragge
1.19
219 }
220
mickey
1.1
221 int
222 fldexpand(NODE *pint cookiechar **cp)
223 {
224         CONSZ val;
225
226         if (p->n_op == ASSIGN)
227                 p = p->n_left;
228         switch (**cp) {
229         case 'S':
230                 printf("%d"UPKFSZ(p->n_rval));
231                 break;
232         case 'H':
233                 printf("%d"UPKFOFF(p->n_rval));
234                 break;
235         case 'M':
236         case 'N':
ragge
1.32
237                 val = (((((CONSZ)1 << (UPKFSZ(p->n_rval)-1))-1)<<1)|1);
mickey
1.1
238                 val <<= UPKFOFF(p->n_rval);
ragge
1.13
239                 if (p->n_type > UNSIGNED)
240                         printf("0x%llx", (**cp == 'M' ? val : ~val));
241                 else
242                         printf("0x%llx", (**cp == 'M' ? val : ~val)&0xffffffff);
mickey
1.1
243                 break;
244         default:
245                 comperr("fldexpand");
246         }
247         return 1;
248 }
249
250 static void
251 bfext(NODE *p)
252 {
253         int ch = 0sz = 0;
254
255         if (ISUNSIGNED(p->n_right->n_type))
256                 return;
257         switch (p->n_right->n_type) {
258         case CHAR:
259                 ch = 'b';
260                 sz = 8;
261                 break;
262         case SHORT:
263                 ch = 'w';
264                 sz = 16;
265                 break;
266         case INT:
267                 ch = 'l';
268                 sz = 32;
269                 break;
270         case LONG:
271                 ch = 'q';
272                 sz = 64;
273                 break;
274         default:
275                 comperr("bfext");
276         }
277
278         sz -= UPKFSZ(p->n_left->n_rval);
279         printf("\tshl%c $%d,"chsz);
280         adrput(stdoutgetlr(p'D'));
281         printf("\n\tsar%c $%d,"chsz);
282         adrput(stdoutgetlr(p'D'));
283         printf("\n");
284 }
285
286 static void
ragge
1.21
287 stasg(NODE *p)
mickey
1.1
288 {
ragge
1.21
289         expand(pINAREG"     leaq AL,%rdi\n");
290         if (p->n_stsize >= 8)
291                 printf("\tmovl $%d,%%ecx\n\trep movsq\n"p->n_stsize >> 3);
292         if (p->n_stsize & 3)
293                 printf("\tmovsl\n");
294         if (p->n_stsize & 2)
295                 printf("\tmovsw\n");
296         if (p->n_stsize & 1)
297                 printf("\tmovsb\n");
mickey
1.1
298 }
299
ragge
1.25
300 #define E(x)    expand(p, 0, x)
mickey
1.1
301 /*
ragge
1.7
302  * Generate code to convert an unsigned long to xmm float/double.
mickey
1.1
303  */
304 static void
ragge
1.7
305 ultofd(NODE *p)
mickey
1.1
306 {
307
ragge
1.7
308         E("     movq AL,A1\n");
ragge
1.9
309         E("     testq A1,A1\n");
ragge
1.7
310         E("     js 2f\n");
311         E("     cvtsi2sZfq A1,A3\n");
312         E("     jmp 3f\n");
313         E("2:\n");
314         E("     movq A1,A2\n");
315         E("     shrq A2\n");
ragge
1.9
316         E("     andq $1,A1\n");
ragge
1.7
317         E("     orq A1,A2\n");
318         E("     cvtsi2sZfq A2,A3\n");
319         E("     addsZf A3,A3\n");
320         E("3:\n");
ragge
1.25
321 }
322
323 /*
324  * Generate code to convert an x87 long double to an unsigned long.
325  * This is ugly :-/
326  */
327 static void
328 ldtoul(NODE *p)
329 {
330         int r;
331
332         r = getlr(p'1')->n_rval;
333
334         E("     subq $16,%rsp\n");
335         E("     movl $0x5f000000,(%rsp)\n"); /* More than long can have */
336         E("     flds (%rsp)\n");
337         if (p->n_left->n_op == REG) {
338                 E("     movq AL,(%rsp)\n");
339                 E("     fldt (%rsp)\n");
340         } else
341                 E("     fldt AL\n");
342         E("     fucomi %st(1), %st\n");
343         E("     jae 2f\n");
344
345         E("     fstp %st(1)\n");         /* Pop huge val from stack */
346         E("     fnstcw (%rsp)\n");       /* store cw */
347         E("     movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
348         E("     fldcw 4(%rsp)\n");       /* new cw */
349         E("     fistpll 8(%rsp)\n");     /* save val */
350         E("     fldcw (%rsp)\n");        /* fetch old cw */
351         E("     movq 8(%rsp),A1\n");
352
353         E("     jmp 3f\n");
354
355         E("2:\n");
356
357         E("     fsubp %st, %st(1)\n");
358         E("     fnstcw (%rsp)\n");      
359         E("     movw $0x0f3f,4(%rsp)\n");
360         E("     fldcw 4(%rsp)\n");
361         E("     fistpll 8(%rsp)\n");
362         E("     fldcw (%rsp)\n");
363         E("     movabsq $0x8000000000000000,A1\n");
364         E("     xorq 8(%rsp),A1\n");
365
366         E("3:   addq $16,%rsp\n");
367 }
ragge
1.26
368
369 /*
370  * Generate code to convert an SSE float/double to an unsigned long.
371  */     
372 static void     
373 fdtoul(NODE *p
374 {
375         E("     movabsq $0x43e0000000000000,A1\n");
376         E("     movd A1,A3\n");
377         E("     ucomisd A3,AL\n");
378         E("     jae 2f\n");
379         E("     cvttsd2siq AL,A1\n");
380         E("     jmp 3f\n");
381         E("2:\n");
382         E("     subsd A3,AL\n");
383         E("     cvttsd2siq AL,A1\n");
384         E("     movabsq $0x8000000000000000,A2\n");
385         E("     xorq A2,A1\n");
386         E("3:\n");
387 }
ragge
1.7
388 #undef E
mickey
1.1
389
390 void
391 zzzcode(NODE *pint c)
392 {
ragge
1.6
393         NODE *l;
ragge
1.7
394         int prlrs;
ragge
1.14
395         char **rt;
mickey
1.1
396
397         switch (c) {
398         case 'A'/* swap st0 and st1 if right is evaluated second */
399                 if ((p->n_su & DORIGHT) == 0) {
400                         if (logop(p->n_op))
401                                 printf("        fxch\n");
402                         else
403                                 printf("r");
404                 }
405                 break;
406
ragge
1.25
407         case 'B'/* ldouble to unsigned long cast */
408                 ldtoul(p);
409                 break;
410
ragge
1.26
411         case 'b'/* float/double to unsigned long cast */
412                 fdtoul(p);
413                 break;
414
mickey
1.1
415         case 'C':  /* remove from stack after subroutine call */
416                 pr = p->n_qual;
417                 if (p->n_op == UCALL)
418                         return/* XXX remove ZC from UCALL */
419                 if (pr)
ragge
1.10
420                         printf("        addq $%d, %s\n"prrnames[RSP]);
mickey
1.1
421                 break;
422
423         case 'E'/* Perform bitfield sign-extension */
424                 bfext(p);
425                 break;
426
427         case 'F'/* Structure argument */
ragge
1.21
428                 printf("        subq $%d,%%rsp\n"p->n_stsize);
429                 printf("        movq %%rsp,%%rsi\n");
430                 stasg(p);
mickey
1.1
431                 break;
ragge
1.19
432
433         case 'G'/* Floating point compare */
434                 fcomp(p);
435                 break;
436
ragge
1.7
437         case 'j'/* convert unsigned long to f/d */
438                 ultofd(p);
mickey
1.1
439                 break;
440
441         case 'M'/* Output sconv move, if needed */
442                 l = getlr(p'L');
443                 /* XXX fixneed: regnum */
444                 pr = DECRA(p->n_reg0);
445                 lr = DECRA(l->n_reg0);
ragge
1.6
446                 if (pr == lr)
447                         break;
448                 printf("        movb %s,%s\n"rbyte[lr], rbyte[pr]);
mickey
1.1
449                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
450                 break;
451
ragge
1.27
452         case 'N'/* output long reg name */
453                 printf("%s"rlong[getlr(p'1')->n_rval]);
454                 break;
455
ragge
1.16
456         case 'P'/* Put hidden argument in rdi */
457                 printf("\tleaq -%d(%%rbp),%%rdi\n"stkpos);
458                 break;
459
ragge
1.10
460         case 'Q'/* emit struct assign */
ragge
1.21
461                 stasg(p);
ragge
1.10
462                 break;
463
ragge
1.7
464         case 'R'/* print opname based on right type */
465         case 'L'/* print opname based on left type */
466                 switch (getlr(pc)->n_type) {
467                 case CHARcase UCHARs = 'b'break;
468                 case SHORTcase USHORTs = 'w'break;
469                 case INTcase UNSIGNEDs = 'l'break;
470                 defaults = 'q'break;
471                 printf("%c"s);
472                 }
473                 break;
ragge
1.14
474
ragge
1.28
475         case 'U': { /* output branch insn for ucomi */
476                 static char *fpcb[] = { "jz""jnz""jbe""jc""jnc""ja" };
477                 if (p->n_op < EQ || p->n_op > GT)
478                         comperr("bad fp branch");
ragge
1.33
479                 if (p->n_op == NE || p->n_op == GT || p->n_op == GE)
480                         expand(p0"  jp LC\n");
481                 else if (p->n_op == EQ)
482                         printf("\tjp 1f\n");
ragge
1.28
483                 printf("        %s "fpcb[p->n_op - EQ]);
484                 expand(p0"LC\n");
ragge
1.33
485                 if (p->n_op == EQ)
486                         printf("1:\n");
ragge
1.28
487                 break;
488                 }
489
ragge
1.14
490         case '8'/* special reg name printout (64-bit) */
491         case '1'/* special reg name printout (32-bit) */
ragge
1.7
492                 l = getlr(p'1');
ragge
1.14
493                 rt = c == '8' ? rnames : rlong;
494                 printf("%s"rt[l->n_rval]);
ragge
1.7
495                 break;
496
497         case 'g':
498                 p = p->n_left;
499                 /* FALLTHROUGH */
500         case 'f'/* float or double */
501                 printf("%c"p->n_type == FLOAT ? 's' : 'd');
502                 break;
503
504         case 'q'/* int or long */
505                 printf("%c"p->n_left->n_type == LONG ? 'q' : ' ');
506                 break;
507
mickey
1.1
508         default:
509                 comperr("zzzcode %c"c);
510         }
511 }
512
513 /*ARGSUSED*/
514 int
515 rewfld(NODE *p)
516 {
517         return(1);
518 }
519
520 int canaddr(NODE *);
521 int
522 canaddr(NODE *p)
523 {
524         int o = p->n_op;
525
526         if (o==NAME || o==REG || o==ICON || o==OREG ||
527             (o==UMUL && shumul(p->n_leftSOREG)))
528                 return(1);
529         return(0);
530 }
531
532 /*
533  * Does the bitfield shape match?
534  */
535 int
536 flshape(NODE *p)
537 {
538         int o = p->n_op;
539
540         if (o == OREG || o == REG || o == NAME)
541                 return SRDIR/* Direct match */
542         if (o == UMUL && shumul(p->n_leftSOREG))
543                 return SROREG/* Convert into oreg */
544         return SRREG/* put it into a register */
545 }
546
547 /* INTEMP shapes must not contain any temporary registers */
548 /* XXX should this go away now? */
549 int
550 shtemp(NODE *p)
551 {
552         return 0;
553 #if 0
554         int r;
555
556         if (p->n_op == STARG )
557                 p = p->n_left;
558
559         switch (p->n_op) {
560         case REG:
561                 return (!istreg(p->n_rval));
562
563         case OREG:
564                 r = p->n_rval;
565                 if (R2TEST(r)) {
566                         if (istreg(R2UPK1(r)))
567                                 return(0);
568                         r = R2UPK2(r);
569                 }
570                 return (!istreg(r));
571
572         case UMUL:
573                 p = p->n_left;
574                 return (p->n_op != UMUL && shtemp(p));
575         }
576
577         if (optype(p->n_op) != LTYPE)
578                 return(0);
579         return(1);
580 #endif
581 }
582
583 void
584 adrcon(CONSZ val)
585 {
586         printf("$" CONFMTval);
587 }
588
589 void
590 conput(FILE *fpNODE *p)
591 {
ragge
1.17
592         long val = p->n_lval;
mickey
1.1
593
594         switch (p->n_op) {
595         case ICON:
596                 if (p->n_name[0] != '\0') {
597                         fprintf(fp"%s"p->n_name);
598                         if (val)
ragge
1.17
599                                 fprintf(fp"+%ld"val);
mickey
1.1
600                 } else
ragge
1.17
601                         fprintf(fp"%ld"val);
mickey
1.1
602                 return;
603
604         default:
605                 comperr("illegal conput, p %p"p);
606         }
607 }
608
609 /*ARGSUSED*/
610 void
611 insput(NODE *p)
612 {
613         comperr("insput");
614 }
615
616 /*
617  * Write out the upper address, like the upper register of a 2-register
618  * reference, or the next memory location.
ragge
1.17
619  * XXX - not needed on amd64
mickey
1.1
620  */
621 void
622 upput(NODE *pint size)
623 {
624
625         size /= SZCHAR;
626         switch (p->n_op) {
627         case REG:
628                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
629                 break;
630
631         case NAME:
632         case OREG:
633                 p->n_lval += size;
634                 adrput(stdoutp);
635                 p->n_lval -= size;
636                 break;
637         case ICON:
638                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
639                 break;
640         default:
641                 comperr("upput bad op %d size %d"p->n_opsize);
642         }
643 }
644
645 void
646 adrput(FILE *ioNODE *p)
647 {
648         int r;
ragge
1.5
649         char **rc;
mickey
1.1
650         /* output an address, with offsets, from p */
651
652         if (p->n_op == FLD)
653                 p = p->n_left;
654
655         switch (p->n_op) {
656
657         case NAME:
658                 if (p->n_name[0] != '\0') {
ragge
1.23
659                         if (p->n_lval != 0)
660                                 fprintf(ioCONFMT "+"p->n_lval);
ragge
1.22
661                         fprintf(io"%s(%%rip)"p->n_name);
mickey
1.1
662                 } else
663                         fprintf(ioCONFMTp->n_lval);
664                 return;
665
666         case OREG:
667                 r = p->n_rval;
668                 if (p->n_name[0])
669                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
670                 if (p->n_lval)
ragge
1.17
671                         fprintf(io"%lld"p->n_lval);
mickey
1.1
672                 if (R2TEST(r)) {
ragge
1.18
673                         int r1 = R2UPK1(r);
674                         int r2 = R2UPK2(r);
675                         int sh = R2UPK3(r);
676
677                         fprintf(io"(%s,%s,%d)"
678                             r1 == MAXREGS ? "" : rnames[r1],
679                             r2 == MAXREGS ? "" : rnames[r2], sh);
mickey
1.1
680                 } else
681                         fprintf(io"(%s)"rnames[p->n_rval]);
682                 return;
683         case ICON:
684 #ifdef PCC_DEBUG
685                 /* Sanitycheck for PIC, to catch adressable constants */
686                 if (kflag && p->n_name[0]) {
687                         static int foo;
688
689                         if (foo++ == 0) {
690                                 printf("\nfailing...\n");
691                                 fwalk(pe2print0);
692                                 comperr("pass2 conput");
693                         }
694                 }
695 #endif
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
753 static void
754 fixcalls(NODE *pvoid *arg)
755 {
756         /* Prepare for struct return by allocating bounce space on stack */
757         switch (p->n_op) {
758         case STCALL:
759         case USTCALL:
760                 if (p->n_stsize+p2autooff > stkpos)
761                         stkpos = p->n_stsize+p2autooff;
762                 break;
763         }
764 }
765
766 void
767 myreader(struct interpass *ipole)
768 {
769         struct interpass *ip;
770
771         stkpos = p2autooff;
772         DLIST_FOREACH(ipipoleqelem) {
773                 if (ip->type != IP_NODE)
774                         continue;
775                 walkf(ip->ip_nodefixcalls0);
776         }
777         if (stkpos > p2autooff)
778                 p2autooff = stkpos;
779         if (stkpos > p2maxautooff)
780                 p2maxautooff = stkpos;
781         if (x2debug)
782                 printip(ipole);
783 }
784
785 /*
786  * Remove some PCONVs after OREGs are created.
787  */
788 static void
789 pconv2(NODE *pvoid *arg)
790 {
791         NODE *q;
792
793         if (p->n_op == PLUS) {
794                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
795                         if (p->n_right->n_op != ICON)
796                                 return;
797                         if (p->n_left->n_op != PCONV)
798                                 return;
799                         if (p->n_left->n_left->n_op != OREG)
800                                 return;
801                         q = p->n_left->n_left;
802                         nfree(p->n_left);
803                         p->n_left = q;
804                         /*
805                          * This will be converted to another OREG later.
806                          */
807                 }
808         }
809 }
810
811 void
812 mycanon(NODE *p)
813 {
814         walkf(ppconv20);
815 }
816
817 void
818 myoptim(struct interpass *ip)
819 {
820 }
821
822 void
823 rmove(int sint dTWORD t)
824 {
825
826         switch (t) {
ragge
1.11
827         case INT:
828         case UNSIGNED:
829                 printf("        movl %s,%s\n"rlong[s], rlong[d]);
mickey
1.1
830                 break;
831         case CHAR:
832         case UCHAR:
ragge
1.4
833                 printf("        movb %s,%s\n"rbyte[s], rbyte[d]);
834                 break;
835         case SHORT:
836         case USHORT:
837                 printf("        movw %s,%s\n"rshort[s], rshort[d]);
mickey
1.1
838                 break;
839         case FLOAT:
ragge
1.11
840                 printf("        movss %s,%s\n"rnames[s], rnames[d]);
841                 break;
mickey
1.1
842         case DOUBLE:
ragge
1.11
843                 printf("        movsd %s,%s\n"rnames[s], rnames[d]);
844                 break;
mickey
1.1
845         case LDOUBLE:
ragge
1.32
846 #ifdef notdef
mickey
1.1
847                 /* a=b()*c(); will generate this */
ragge
1.32
848                 /* XXX can it fail anyway? */
mickey
1.1
849                 comperr("bad float rmove: %d %d"sd);
ragge
1.32
850 #endif
mickey
1.1
851                 break;
852         default:
ragge
1.11
853                 printf("        movq %s,%s\n"rnames[s], rnames[d]);
854                 break;
mickey
1.1
855         }
856 }
857
858 /*
859  * For class c, find worst-case displacement of the number of
860  * registers in the array r[] indexed by class.
861  */
862 int
863 COLORMAP(int cint *r)
864 {
865
866         switch (c) {
867         case CLASSA:
ragge
1.4
868                 return r[CLASSA] < 14;
mickey
1.1
869         case CLASSB:
ragge
1.4
870                 return r[CLASSB] < 16;
ragge
1.21
871         case CLASSC:
872                 return r[CLASSC] < CREGCNT;
mickey
1.1
873         }
874         return 0/* XXX gcc */
875 }
876
877 char *rnames[] = {
ragge
1.4
878         "%rax""%rdx""%rcx""%rbx""%rsi""%rdi""%rbp""%rsp",
879         "%r8""%r9""%r10""%r11""%r12""%r13""%r14""%r15",
880         "%xmm0""%xmm1""%xmm2""%xmm3""%xmm4""%xmm5""%xmm6""%xmm7",
881         "%xmm8""%xmm9""%xmm10""%xmm11""%xmm12""%xmm13""%xmm14",
882         "%xmm15",
883 };
884
885 /* register names for shorter sizes */
886 char *rbyte[] = {
887         "%al""%dl""%cl""%bl""%sil""%dil""%bpl""%spl",
888         "%r8b""%r9b""%r10b""%r11b""%r12b""%r13b""%r14b""%r15b"
889 };
890 char *rshort[] = {
891         "%ax""%dx""%cx""%bx""%si""%di""%bp""%sp",
892         "%r8w""%r9w""%r10w""%r11w""%r12w""%r13w""%r14w""%r15w"
893 };
894 char *rlong[] = {
mickey
1.1
895         "%eax""%edx""%ecx""%ebx""%esi""%edi""%ebp""%esp",
ragge
1.7
896         "%r8d""%r9d""%r10d""%r11d""%r12d""%r13d""%r14d""%r15d"
mickey
1.1
897 };
898
ragge
1.4
899
mickey
1.1
900 /*
901  * Return a class suitable for a specific type.
902  */
903 int
904 gclass(TWORD t)
905 {
ragge
1.21
906         if (t == LDOUBLE)
907                 return CLASSC;
908         if (t == FLOAT || t == DOUBLE)
mickey
1.1
909                 return CLASSB;
910         return CLASSA;
911 }
912
ragge
1.21
913 static int
914 argsiz(NODE *p)
915 {
916         TWORD t = p->n_type;
917
918         if (p->n_left->n_op == REG)
919                 return 0/* not on stack */
920         if (t == LDOUBLE)
921                 return 16;
922         if (p->n_op == STASG)
923                 return p->n_stsize;
924         return 8;
925 }
926
mickey
1.1
927 /*
928  * Calculate argument sizes.
929  */
930 void
931 lastcall(NODE *p)
932 {
933         NODE *op = p;
934         int size = 0;
935
936         p->n_qual = 0;
937         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
938                 return;
939         for (p = p->n_rightp->n_op == CMp = p->n_left)
940                 size += argsiz(p->n_right);
941         size += argsiz(p);
ragge
1.10
942         size = (size+15) & ~15;
943         if (size)
944                 printf("        subq $%d,%s\n"sizernames[RSP]);
mickey
1.1
945         op->n_qual = size/* XXX */
946 }
947
948 /*
949  * Special shapes.
950  */
951 int
952 special(NODE *pint shape)
953 {
954         int o = p->n_op;
955
956         switch (shape) {
957         case SFUNCALL:
958                 if (o == STCALL || o == USTCALL)
959                         return SRREG;
960                 break;
961         case SPCON:
962                 if (o != ICON || p->n_name[0] ||
963                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
964                         break;
965                 return SRDIR;
966         case SMIXOR:
967                 return tshape(pSZERO);
968         case SMILWXOR:
969                 if (o != ICON || p->n_name[0] ||
970                     p->n_lval == 0 || p->n_lval & 0xffffffff)
971                         break;
972                 return SRDIR;
973         case SMIHWXOR:
974                 if (o != ICON || p->n_name[0] ||
975                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
976                         break;
977                 return SRDIR;
ragge
1.12
978         case SCON32:
979                 if (o != ICON || p->n_name[0])
980                         break;
981                 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT)
982                         break;
983                 return SRDIR;
984         default:
985                 cerror("special: %x\n"shape);
mickey
1.1
986         }
987         return SRNOPE;
988 }
989
990 /*
991  * Target-dependent command-line options.
992  */
993 void
994 mflags(char *str)
995 {
996 }
997
998 /*
999  * Do something target-dependent for xasm arguments.
1000  */
1001 int
1002 myxasm(struct interpass *ipNODE *p)
1003 {
1004         struct interpass *ip2;
ragge
1.30
1005         int Cmax[] = { 31631270xffff3255 };
mickey
1.1
1006         NODE *in = 0, *ut = 0;
1007         TWORD t;
1008         char *w;
1009         int reg;
ragge
1.30
1010         int ccwv;
mickey
1.1
1011
1012         cw = xasmcode(p->n_name);
1013         if (cw & (XASMASG|XASMINOUT))
1014                 ut = p->n_left;
1015         if ((cw & XASMASG) == 0)
1016                 in = p->n_left;
1017
ragge
1.31
1018         switch (c = XASMVAL(cw)) {
ragge
1.30
1019         case 'D'reg = RDIbreak;
1020         case 'S'reg = RSIbreak;
ragge
1.35
1021         case 'A'
ragge
1.30
1022         case 'a'reg = RAXbreak;
1023         case 'b'reg = RBXbreak;
1024         case 'c'reg = RCXbreak;
1025         case 'd'reg = RDXbreak;
1026
ragge
1.38
1027         case 'x':
ragge
1.34
1028         case 'q':
ragge
1.30
1029         case 't':
1030         case 'u':
mickey
1.1
1031                 p->n_name = tmpstrdup(p->n_name);
ragge
1.31
1032                 w = strchr(p->n_namec);
ragge
1.30
1033                 *w = 'r'/* now reg */
ragge
1.38
1034                 return c == 'q' || c == 'x' ? 0 : 1;
ragge
1.30
1035
1036         case 'I':
1037         case 'J':
1038         case 'K':
1039         case 'L':
1040         case 'M':
1041         case 'N':
1042                 if (p->n_left->n_op != ICON)
1043                         uerror("xasm arg not constant");
1044                 v = p->n_left->n_lval;
1045                 if ((c == 'K' && v < -128) ||
1046                     (c == 'L' && v != 0xff && v != 0xffff) ||
1047                     (c != 'K' && v < 0) ||
1048                     (v > Cmax[c-'I']))
1049                         uerror("xasm val out of range");
1050                 p->n_name = "i";
1051                 return 1;
1052
mickey
1.1
1053         default:
1054                 return 0;
1055         }
ragge
1.38
1056         /* If there are requested either memory or register, delete memory */
1057         w = p->n_name = tmpstrdup(p->n_name);
1058         if (*w == '=')
1059                 w++;
1060         *w++ = 'r';
1061         *w = 0;
1062
mickey
1.1
1063         t = p->n_left->n_type;
ragge
1.30
1064
1065         if (t == FLOAT || t == DOUBLE) {
1066                 p->n_label = CLASSB;
1067                 reg += 16;
1068         } else if (t == LDOUBLE) {
mickey
1.1
1069                 p->n_label = CLASSC;
ragge
1.30
1070                 reg += 32;
1071         } else
mickey
1.1
1072                 p->n_label = CLASSA;
1073
1074         if (in && ut)
1075                 in = tcopy(in);
1076         p->n_left = mklnode(REG0regt);
1077         if (ut) {
1078                 ip2 = ipnode(mkbinode(ASSIGNuttcopy(p->n_left), t));
1079                 DLIST_INSERT_AFTER(ipip2qelem);
1080         }
1081         if (in) {
1082                 ip2 = ipnode(mkbinode(ASSIGNtcopy(p->n_left), int));
1083                 DLIST_INSERT_BEFORE(ipip2qelem);
1084         }
ragge
1.30
1085
mickey
1.1
1086         return 1;
1087 }
1088
1089 void
ragge
1.29
1090 targarg(char *wvoid *argint n)
mickey
1.1
1091 {
1092         NODE **ary = arg;
1093         NODE *p, *q;
1094
ragge
1.29
1095         if (w[1] < '0' || w[1] > (n + '0'))
1096                 uerror("bad xasm arg number %c"w[1]);
1097         if (w[1] == (n + '0'))
1098                 p = ary[(int)w[1]-'0' - 1]; /* XXX */
1099         else
1100                 p = ary[(int)w[1]-'0'];
1101         p = p->n_left;
1102
mickey
1.1
1103         if (optype(p->n_op) != LTYPE)
1104                 comperr("bad xarg op %d"p->n_op);
1105         q = tcopy(p);
1106         if (q->n_op == REG) {
1107                 if (*w == 'k') {
1108                         q->n_type = INT;
1109                 } else if (*w != 'w') {
ragge
1.24
1110                         cerror("targarg"); /* XXX ??? */
mickey
1.1
1111                         if (q->n_type > UCHAR) {
1112                                 regno(q) = regno(q)*2+8;
1113                                 if (*w == 'h')
1114                                         regno(q)++;
1115                         }
1116                         q->n_type = INT;
1117                 } else
1118                         q->n_type = SHORT;
1119         }
1120         adrput(stdoutq);
1121         tfree(q);
1122 }
1123
1124 /*
1125  * target-specific conversion of numeric arguments.
1126  */
1127 int
1128 numconv(void *ipvoid *p1void *q1)
1129 {
1130         NODE *p = p1, *q = q1;
1131         int cw = xasmcode(q->n_name);