Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20100920170148

Diff

Diff from 1.20 to:

Annotations

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

Annotated File View

ragge
1.20
1 /*      $Id: local2.c,v 1.20 2010/09/20 17:01: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[];
mickey
1.1
45
46 /*
47  * Print out the prolog assembler.
48  * addto and regoff are already calculated.
49  */
50 static void
51 prtprolog(struct interpass_prolog *ippint addto)
52 {
53         int i;
54
ragge
1.5
55         /* XXX should look if there is any need to emit this */
mickey
1.2
56         printf("\tpushq %%rbp\n");
57         printf("\tmovq %%rsp,%%rbp\n");
ragge
1.10
58         addto = (addto+15) & ~15/* 16-byte aligned */
mickey
1.1
59         if (addto)
mickey
1.2
60                 printf("\tsubq $%d,%%rsp\n"addto);
ragge
1.10
61
62         /* save permanent registers */
mickey
1.1
63         for (i = 0i < MAXREGSi++)
ragge
1.10
64                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.11
65                         fprintf(stdout"\tmovq %s,-%d(%s)\n",
mickey
1.1
66                             rnames[i], regoff[i], rnames[FPREG]);
ragge
1.4
67 }
mickey
1.1
68
69 /*
70  * calculate stack size and offsets
71  */
72 static int
73 offcalc(struct interpass_prolog *ipp)
74 {
75         int iaddto;
76
77         addto = p2maxautooff;
78         if (addto >= AUTOINIT/SZCHAR)
79                 addto -= AUTOINIT/SZCHAR;
80         for (i = 0i < MAXREGSi++)
81                 if (TESTBIT(ipp->ipp_regsi)) {
ragge
1.10
82                         addto += SZLONG/SZCHAR;
mickey
1.1
83                         regoff[i] = addto;
84                 }
85         return addto;
86 }
87
88 void
89 prologue(struct interpass_prolog *ipp)
90 {
91         int addto;
92
93         ftype = ipp->ipp_type;
94
95 #ifdef LANG_F77
96         if (ipp->ipp_vis)
97                 printf("        .globl %s\n"ipp->ipp_name);
ragge
1.10
98         printf("        .align 16\n");
mickey
1.1
99         printf("%s:\n"ipp->ipp_name);
100 #endif
101         /*
102          * We here know what register to save and how much to 
103          * add to the stack.
104          */
105         addto = offcalc(ipp);
106         prtprolog(ippaddto);
107 }
108
109 void
110 eoftn(struct interpass_prolog *ipp)
111 {
112         int i;
113
114         if (ipp->ipp_ip.ip_lbl == 0)
115                 return/* no code needs to be generated */
116
117         /* return from function code */
118         for (i = 0i < MAXREGSi++)
119                 if (TESTBIT(ipp->ipp_regsi))
ragge
1.10
120                         fprintf(stdout"       movq -%d(%s),%s\n",
mickey
1.1
121                             regoff[i], rnames[FPREG], rnames[i]);
122
123         /* struct return needs special treatment */
124         if (ftype == STRTY || ftype == UNIONTY) {
125                 printf("        movl 8(%%ebp),%%eax\n");
126                 printf("        leave\n");
127                 printf("        ret $%d\n"4);
128         } else {
129                 printf("        leave\n");
ragge
1.11
130                 printf("        ret\n");
mickey
1.1
131         }
ragge
1.10
132         printf("\t.size %s,.-%s\n"ipp->ipp_nameipp->ipp_name);
mickey
1.1
133 }
134
135 /*
136  * add/sub/...
137  *
138  * Param given:
139  */
140 void
141 hopcode(int fint o)
142 {
143         char *str;
144
145         switch (o) {
146         case PLUS:
147                 str = "add";
148                 break;
149         case MINUS:
150                 str = "sub";
151                 break;
152         case AND:
153                 str = "and";
154                 break;
155         case OR:
156                 str = "or";
157                 break;
158         case ER:
159                 str = "xor";
160                 break;
161         default:
162                 comperr("hopcode2: %d"o);
163                 str = 0/* XXX gcc */
164         }
165         printf("%s%c"strf);
166 }
167
168 /*
169  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
170  */
171 int
mickey
1.2
172 tlen(NODE *p)
mickey
1.1
173 {
174         switch(p->n_type) {
175                 case CHAR:
176                 case UCHAR:
177                         return(1);
178
179                 case SHORT:
180                 case USHORT:
181                         return(SZSHORT/SZCHAR);
182
183                 case DOUBLE:
184                         return(SZDOUBLE/SZCHAR);
185
186                 case INT:
187                 case UNSIGNED:
188                         return(SZINT/SZCHAR);
189
190                 case LONG:
191                 case ULONG:
192                 case LONGLONG:
193                 case ULONGLONG:
194                         return SZLONGLONG/SZCHAR;
195
196                 default:
197                         if (!ISPTR(p->n_type))
198                                 comperr("tlen type %d not pointer");
199                         return SZPOINT(p->n_type)/SZCHAR;
200                 }
201 }
202
ragge
1.19
203 /*
204  * Compare two floating point numbers.
205  */
206 static void
207 fcomp(NODE *p)  
208 {
209
210         if (p->n_left->n_op == REG) {
211                 if (p->n_su & DORIGHT)
212                         expand(p0"  fxch\n");
213                 expand(p0"  fucompp\n");    /* emit compare insn  */
214         } else
215                 comperr("bad compare %p\n"p);
216         expand(p0"  fnstsw %ax\n"); /* move status reg to ax */
217         
218         switch (p->n_op) {
219         case EQ:
220                 expand(p0"  andb $69,%ah\n  xorb $64,%ah\n  je LC\n");
221                 break;
222         case NE:
223                 expand(p0"  andb $69,%ah\n  xorb $64,%ah\n  jne LC\n");
224                 break;
225         case LE:
226                 expand(p0"  andb $69,%ah\n  xorb $1,%ah\n   jne LC\n");
227                 break;
228         case LT:
229                 expand(p0"  andb $69,%ah\n  je LC\n");
230                 break;
231         case GT:
232                 expand(p0"  andb $1,%ah\n   jne LC\n");
233                 break;
234         case GE:
235                 expand(p0"  andb $69,%ah\n  jne LC\n");
236                 break;
237         default:
238                 comperr("fcomp op %d\n"p->n_op);
239         }
240 }
241
242
gmcgarry
1.3
243 #if 0
mickey
1.1
244 /*
245  * Emit code to compare two longlong numbers.
246  */
247 static void
248 twollcomp(NODE *p)
249 {
250         int o = p->n_op;
mickey
1.2
251         int s = getlab2();
mickey
1.1
252         int e = p->n_label;
253         int cb1cb2;
254
255         if (o >= ULE)
256                 o -= (ULE-LE);
257         switch (o) {
258         case NE:
259                 cb1 = 0;
260                 cb2 = NE;
261                 break;
262         case EQ:
263                 cb1 = NE;
264                 cb2 = 0;
265                 break;
266         case LE:
267         case LT:
268                 cb1 = GT;
269                 cb2 = LT;
270                 break;
271         case GE:
272         case GT:
273                 cb1 = LT;
274                 cb2 = GT;
275                 break;
276         
277         default:
278                 cb1 = cb2 = 0/* XXX gcc */
279         }
280         if (p->n_op >= ULE)
281                 cb1 += 4cb2 += 4;
282         expand(p0"  cmpl UR,UL\n");
283         if (cb1cbgen(cb1s);
284         if (cb2cbgen(cb2e);
285         expand(p0"  cmpl AR,AL\n");
286         cbgen(p->n_ope);
287         deflab(s);
288 }
gmcgarry
1.3
289 #endif
mickey
1.1
290
291 int
292 fldexpand(NODE *pint cookiechar **cp)
293 {
294         CONSZ val;
295
296         if (p->n_op == ASSIGN)
297                 p = p->n_left;
298         switch (**cp) {
299         case 'S':
300                 printf("%d"UPKFSZ(p->n_rval));
301                 break;
302         case 'H':
303                 printf("%d"UPKFOFF(p->n_rval));
304                 break;
305         case 'M':
306         case 'N':
307                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
308                 --val;
309                 val <<= UPKFOFF(p->n_rval);
ragge
1.13
310                 if (p->n_type > UNSIGNED)
311                         printf("0x%llx", (**cp == 'M' ? val : ~val));
312                 else
313                         printf("0x%llx", (**cp == 'M' ? val : ~val)&0xffffffff);
mickey
1.1
314                 break;
315         default:
316                 comperr("fldexpand");
317         }
318         return 1;
319 }
320
321 static void
322 bfext(NODE *p)
323 {
324         int ch = 0sz = 0;
325
326         if (ISUNSIGNED(p->n_right->n_type))
327                 return;
328         switch (p->n_right->n_type) {
329         case CHAR:
330                 ch = 'b';
331                 sz = 8;
332                 break;
333         case SHORT:
334                 ch = 'w';
335                 sz = 16;
336                 break;
337         case INT:
338                 ch = 'l';
339                 sz = 32;
340                 break;
341         case LONG:
342                 ch = 'q';
343                 sz = 64;
344                 break;
345         default:
346                 comperr("bfext");
347         }
348
349         sz -= UPKFSZ(p->n_left->n_rval);
350         printf("\tshl%c $%d,"chsz);
351         adrput(stdoutgetlr(p'D'));
352         printf("\n\tsar%c $%d,"chsz);
353         adrput(stdoutgetlr(p'D'));
354         printf("\n");
355 }
ragge
1.11
356 #if 0
mickey
1.1
357
358 /*
359  * Push a structure on stack as argument.
360  * the scratch registers are already free here
361  */
362 static void
363 starg(NODE *p)
364 {
365         FILE *fp = stdout;
366
367         fprintf(fp"   subl $%d,%%esp\n"p->n_stsize);
368         fprintf(fp"   pushl $%d\n"p->n_stsize);
369         expand(p0"  pushl AL\n");
370         expand(p0"  leal 8(%esp),A1\n");
371         expand(p0"  pushl A1\n");
372         fprintf(fp"   call memcpy\n");
373         fprintf(fp"   addl $12,%%esp\n");
374 }
375
ragge
1.7
376 #endif
mickey
1.1
377 /*
ragge
1.7
378  * Generate code to convert an unsigned long to xmm float/double.
mickey
1.1
379  */
380 static void
ragge
1.7
381 ultofd(NODE *p)
mickey
1.1
382 {
383
ragge
1.7
384 #define E(x)    expand(p, 0, x)
385         E("     movq AL,A1\n");
ragge
1.9
386         E("     testq A1,A1\n");
ragge
1.7
387         E("     js 2f\n");
388         E("     cvtsi2sZfq A1,A3\n");
389         E("     jmp 3f\n");
390         E("2:\n");
391         E("     movq A1,A2\n");
392         E("     shrq A2\n");
ragge
1.9
393         E("     andq $1,A1\n");
ragge
1.7
394         E("     orq A1,A2\n");
395         E("     cvtsi2sZfq A2,A3\n");
396         E("     addsZf A3,A3\n");
397         E("3:\n");
398 #undef E
mickey
1.1
399 }
400
401 static int
402 argsiz(NODE *p)
403 {
404         TWORD t = p->n_type;
405
ragge
1.10
406         if (p->n_left->n_op == REG)
407                 return 0/* not on stack */
mickey
1.1
408         if (t == LDOUBLE)
409                 return 16;
410         if (t == STRTY || t == UNIONTY)
411                 return p->n_stsize;
ragge
1.10
412         return 8;
mickey
1.1
413 }
414
415 void
416 zzzcode(NODE *pint c)
417 {
ragge
1.6
418         NODE *l;
ragge
1.7
419         int prlrs;
ragge
1.14
420         char **rt;
mickey
1.1
421
422         switch (c) {
423         case 'A'/* swap st0 and st1 if right is evaluated second */
424                 if ((p->n_su & DORIGHT) == 0) {
425                         if (logop(p->n_op))
426                                 printf("        fxch\n");
427                         else
428                                 printf("r");
429                 }
430                 break;
431
432         case 'C':  /* remove from stack after subroutine call */
433                 pr = p->n_qual;
434                 if (p->n_op == UCALL)
435                         return/* XXX remove ZC from UCALL */
436                 if (pr)
ragge
1.10
437                         printf("        addq $%d, %s\n"prrnames[RSP]);
mickey
1.1
438                 break;
439
440         case 'E'/* Perform bitfield sign-extension */
441                 bfext(p);
442                 break;
443
ragge
1.11
444 #if 0
mickey
1.1
445         case 'F'/* Structure argument */
446                 if (p->n_stalign != 0/* already on stack */
447                         starg(p);
448                 break;
ragge
1.7
449 #endif
ragge
1.19
450
451         case 'G'/* Floating point compare */
452                 fcomp(p);
453                 break;
454
ragge
1.7
455         case 'j'/* convert unsigned long to f/d */
456                 ultofd(p);
mickey
1.1
457                 break;
458
459         case 'M'/* Output sconv move, if needed */
460                 l = getlr(p'L');
461                 /* XXX fixneed: regnum */
462                 pr = DECRA(p->n_reg0);
463                 lr = DECRA(l->n_reg0);
ragge
1.6
464                 if (pr == lr)
465                         break;
466                 printf("        movb %s,%s\n"rbyte[lr], rbyte[pr]);
mickey
1.1
467                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
468                 break;
469
ragge
1.6
470 #if 0
mickey
1.1
471         case 'N'/* output extended reg name */
472                 printf("%s"rnames[getlr(p'1')->n_rval]);
473                 break;
ragge
1.16
474 #endif
475
476         case 'P'/* Put hidden argument in rdi */
477                 printf("\tleaq -%d(%%rbp),%%rdi\n"stkpos);
478                 break;
479
480 #if 0
mickey
1.1
481
482         case 'S'/* emit eventual move after cast from longlong */
483                 pr = DECRA(p->n_reg0);
484                 lr = p->n_left->n_rval;
485                 switch (p->n_type) {
486                 case CHAR:
487                 case UCHAR:
488                         if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
489                             rnames[pr][1] == rnames[lr][1])
490                                 break;
491                         if (rnames[lr][2] == 'x') {
492                                 printf("\tmovb %%%cl,%s\n",
493                                     rnames[lr][1], rnames[pr]);
494                                 break;
495                         }
496                         /* Must go via stack */
497                         s = BITOOR(freetemp(1));
498                         printf("\tmovl %%e%ci,%d(%%rbp)\n"rnames[lr][1], s);
499                         printf("\tmovb %d(%%rbp),%s\n"srnames[pr]);
500                         comperr("SCONV1 %s->%s"rnames[lr], rnames[pr]);
501                         break;
502
503                 case SHORT:
504                 case USHORT:
505                         if (rnames[lr][1] == rnames[pr][2] &&
506                             rnames[lr][2] == rnames[pr][3])
507                                 break;
508                         printf("\tmovw %%%c%c,%%%s\n",
509                             rnames[lr][1], rnames[lr][2], rnames[pr]+2);
510                         comperr("SCONV2 %s->%s"rnames[lr], rnames[pr]);
511                         break;
512                 case INT:
513                 case UNSIGNED:
514                         if (rnames[lr][1] == rnames[pr][2] &&
515                             rnames[lr][2] == rnames[pr][3])
516                                 break;
517                         printf("\tmovl %%e%c%c,%s\n",
518                                     rnames[lr][1], rnames[lr][2], rnames[pr]);
519                         comperr("SCONV3 %s->%s"rnames[lr], rnames[pr]);
520                         break;
521
522                 default:
523                         if (rnames[lr][1] == rnames[pr][2] &&
524                             rnames[lr][2] == rnames[pr][3])
525                                 break;
526                         comperr("SCONV4 %s->%s"rnames[lr], rnames[pr]);
527                         break;
528                 }
529                 break;
ragge
1.4
530 #endif
ragge
1.10
531         case 'Q'/* emit struct assign */
532                 /* XXX - optimize for small structs */
533                 printf("\tmovq $%d,%%rdx\n"p->n_stsize);
534                 expand(pINAREG"\tmovq AR,%rsi\n");
535                 expand(pINAREG"\tleaq AL,%rdi\n\n");
536                 printf("\tcall memcpy\n");
537                 break;
538
ragge
1.7
539         case 'R'/* print opname based on right type */
540         case 'L'/* print opname based on left type */
541                 switch (getlr(pc)->n_type) {
542                 case CHARcase UCHARs = 'b'break;
543                 case SHORTcase USHORTs = 'w'break;
544                 case INTcase UNSIGNEDs = 'l'break;
545                 defaults = 'q'break;
546                 printf("%c"s);
547                 }
548                 break;
ragge
1.14
549
550         case '8'/* special reg name printout (64-bit) */
551         case '1'/* special reg name printout (32-bit) */
ragge
1.7
552                 l = getlr(p'1');
ragge
1.14
553                 rt = c == '8' ? rnames : rlong;
554                 printf("%s"rt[l->n_rval]);
ragge
1.7
555                 break;
556
557         case 'g':
558                 p = p->n_left;
559                 /* FALLTHROUGH */
560         case 'f'/* float or double */
561                 printf("%c"p->n_type == FLOAT ? 's' : 'd');
562                 break;
563
564         case 'q'/* int or long */
565                 printf("%c"p->n_left->n_type == LONG ? 'q' : ' ');
566                 break;
567
mickey
1.1
568         default:
569                 comperr("zzzcode %c"c);
570         }
571 }
572
573 /*ARGSUSED*/
574 int
575 rewfld(NODE *p)
576 {
577         return(1);
578 }
579
580 int canaddr(NODE *);
581 int
582 canaddr(NODE *p)
583 {
584         int o = p->n_op;
585
586         if (o==NAME || o==REG || o==ICON || o==OREG ||
587             (o==UMUL && shumul(p->n_leftSOREG)))
588                 return(1);
589         return(0);
590 }
591
592 /*
593  * Does the bitfield shape match?
594  */
595 int
596 flshape(NODE *p)
597 {
598         int o = p->n_op;
599
600         if (o == OREG || o == REG || o == NAME)
601                 return SRDIR/* Direct match */
602         if (o == UMUL && shumul(p->n_leftSOREG))
603                 return SROREG/* Convert into oreg */
604         return SRREG/* put it into a register */
605 }
606
607 /* INTEMP shapes must not contain any temporary registers */
608 /* XXX should this go away now? */
609 int
610 shtemp(NODE *p)
611 {
612         return 0;
613 #if 0
614         int r;
615
616         if (p->n_op == STARG )
617                 p = p->n_left;
618
619         switch (p->n_op) {
620         case REG:
621                 return (!istreg(p->n_rval));
622
623         case OREG:
624                 r = p->n_rval;
625                 if (R2TEST(r)) {
626                         if (istreg(R2UPK1(r)))
627                                 return(0);
628                         r = R2UPK2(r);
629                 }
630                 return (!istreg(r));
631
632         case UMUL:
633                 p = p->n_left;
634                 return (p->n_op != UMUL && shtemp(p));
635         }
636
637         if (optype(p->n_op) != LTYPE)
638                 return(0);
639         return(1);
640 #endif
641 }
642
643 void
644 adrcon(CONSZ val)
645 {
646         printf("$" CONFMTval);
647 }
648
649 void
650 conput(FILE *fpNODE *p)
651 {
ragge
1.17
652         long val = p->n_lval;
mickey
1.1
653
654         switch (p->n_op) {
655         case ICON:
656                 if (p->n_name[0] != '\0') {
657                         fprintf(fp"%s"p->n_name);
658                         if (val)
ragge
1.17
659                                 fprintf(fp"+%ld"val);
mickey
1.1
660                 } else
ragge
1.17
661                         fprintf(fp"%ld"val);
mickey
1.1
662                 return;
663
664         default:
665                 comperr("illegal conput, p %p"p);
666         }
667 }
668
669 /*ARGSUSED*/
670 void
671 insput(NODE *p)
672 {
673         comperr("insput");
674 }
675
676 /*
677  * Write out the upper address, like the upper register of a 2-register
678  * reference, or the next memory location.
ragge
1.17
679  * XXX - not needed on amd64
mickey
1.1
680  */
681 void
682 upput(NODE *pint size)
683 {
684
685         size /= SZCHAR;
686         switch (p->n_op) {
687         case REG:
688                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
689                 break;
690
691         case NAME:
692         case OREG:
693                 p->n_lval += size;
694                 adrput(stdoutp);
695                 p->n_lval -= size;
696                 break;
697         case ICON:
698                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
699                 break;
700         default:
701                 comperr("upput bad op %d size %d"p->n_opsize);
702         }
703 }
704
705 void
706 adrput(FILE *ioNODE *p)
707 {
708         int r;
ragge
1.5
709         char **rc;
mickey
1.1
710         /* output an address, with offsets, from p */
711
712         if (p->n_op == FLD)
713                 p = p->n_left;
714
715         switch (p->n_op) {
716
717         case NAME:
718                 if (p->n_name[0] != '\0') {
719                         fputs(p->n_nameio);
720                         if (p->n_lval != 0)
721                                 fprintf(io"+" CONFMTp->n_lval);
722                 } else
723                         fprintf(ioCONFMTp->n_lval);
724                 return;
725
726         case OREG:
727                 r = p->n_rval;
728                 if (p->n_name[0])
729                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
730                 if (p->n_lval)
ragge
1.17
731                         fprintf(io"%lld"p->n_lval);
mickey
1.1
732                 if (R2TEST(r)) {
ragge
1.18
733                         int r1 = R2UPK1(r);
734                         int r2 = R2UPK2(r);
735                         int sh = R2UPK3(r);
736
737                         fprintf(io"(%s,%s,%d)"
738                             r1 == MAXREGS ? "" : rnames[r1],
739                             r2 == MAXREGS ? "" : rnames[r2], sh);
mickey
1.1
740                 } else
741                         fprintf(io"(%s)"rnames[p->n_rval]);
742                 return;
743         case ICON:
744 #ifdef PCC_DEBUG
745                 /* Sanitycheck for PIC, to catch adressable constants */
746                 if (kflag && p->n_name[0]) {
747                         static int foo;
748
749                         if (foo++ == 0) {
750                                 printf("\nfailing...\n");
751                                 fwalk(pe2print0);
752                                 comperr("pass2 conput");
753                         }
754                 }
755 #endif
756                 /* addressable value of the constant */
757                 fputc('$'io);
758                 conput(iop);
759                 return;
760
761         case REG:
762                 switch (p->n_type) {
ragge
1.5
763                 case CHAR:
764                 case UCHAR:
765                         rc = rbyte;
mickey
1.1
766                         break;
767                 case SHORT:
768                 case USHORT:
ragge
1.5
769                         rc = rshort;
770                         break;
771                 case INT:
772                 case UNSIGNED:
773                         rc = rlong;
mickey
1.1
774                         break;
775                 default:
ragge
1.5
776                         rc = rnames;
777                         break;
mickey
1.1
778                 }
ragge
1.5
779                 fprintf(io"%s"rc[p->n_rval]);
mickey
1.1
780                 return;
781
782         default:
783                 comperr("illegal address, op %d, node %p"p->n_opp);
784                 return;
785
786         }
787 }
788
789 static char *
790 ccbranches[] = {
791         "je",           /* jumpe */
792         "jne",          /* jumpn */
793         "jle",          /* jumple */
794         "jl",           /* jumpl */
795         "jge",          /* jumpge */
796         "jg",           /* jumpg */
797         "jbe",          /* jumple (jlequ) */
798         "jb",           /* jumpl (jlssu) */
799         "jae",          /* jumpge (jgequ) */
800         "ja",           /* jumpg (jgtru) */
801 };
802
803
804 /*   printf conditional and unconditional branches */
805 void
806 cbgen(int oint lab)
807 {
808         if (o < EQ || o > UGT)
809                 comperr("bad conditional branch: %s"opst[o]);
810         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
811 }
812
813 static void
814 fixcalls(NODE *pvoid *arg)
815 {
816         /* Prepare for struct return by allocating bounce space on stack */
817         switch (p->n_op) {
818         case STCALL:
819         case USTCALL:
820                 if (p->n_stsize+p2autooff > stkpos)
821                         stkpos = p->n_stsize+p2autooff;
822                 break;
823         }
824 }
825
826 void
827 myreader(struct interpass *ipole)
828 {
829         struct interpass *ip;
830
831         stkpos = p2autooff;
832         DLIST_FOREACH(ipipoleqelem) {
833                 if (ip->type != IP_NODE)
834                         continue;
835                 walkf(ip->ip_nodefixcalls0);
836         }
837         if (stkpos > p2autooff)
838                 p2autooff = stkpos;
839         if (stkpos > p2maxautooff)
840                 p2maxautooff = stkpos;
841         if (x2debug)
842                 printip(ipole);
843 }
844
845 /*
846  * Remove some PCONVs after OREGs are created.
847  */
848 static void
849 pconv2(NODE *pvoid *arg)
850 {
851         NODE *q;
852
853         if (p->n_op == PLUS) {
854                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
855                         if (p->n_right->n_op != ICON)
856                                 return;
857                         if (p->n_left->n_op != PCONV)
858                                 return;
859                         if (p->n_left->n_left->n_op != OREG)
860                                 return;
861                         q = p->n_left->n_left;
862                         nfree(p->n_left);
863                         p->n_left = q;
864                         /*
865                          * This will be converted to another OREG later.
866                          */
867                 }
868         }
869 }
870
871 void
872 mycanon(NODE *p)
873 {
874         walkf(ppconv20);
875 }
876
877 void
878 myoptim(struct interpass *ip)
879 {
880 }
881
882 void
883 rmove(int sint dTWORD t)
884 {
885
886         switch (t) {
ragge
1.11
887         case INT:
888         case UNSIGNED:
889                 printf("        movl %s,%s\n"rlong[s], rlong[d]);
mickey
1.1
890                 break;
891         case CHAR:
892         case UCHAR:
ragge
1.4
893                 printf("        movb %s,%s\n"rbyte[s], rbyte[d]);
894                 break;
895         case SHORT:
896         case USHORT:
897                 printf("        movw %s,%s\n"rshort[s], rshort[d]);
mickey
1.1
898                 break;
899         case FLOAT:
ragge
1.11
900                 printf("        movss %s,%s\n"rnames[s], rnames[d]);
901                 break;
mickey
1.1
902         case DOUBLE:
ragge
1.11
903                 printf("        movsd %s,%s\n"rnames[s], rnames[d]);
904                 break;
mickey
1.1
905         case LDOUBLE:
906                 /* a=b()*c(); will generate this */
907                 comperr("bad float rmove: %d %d"sd);
908                 break;
909         default:
ragge
1.11
910                 printf("        movq %s,%s\n"rnames[s], rnames[d]);
911                 break;
mickey
1.1
912         }
913 }
914
915 /*
916  * For class c, find worst-case displacement of the number of
917  * registers in the array r[] indexed by class.
918  */
919 int
920 COLORMAP(int cint *r)
921 {
922
923         switch (c) {
924         case CLASSA:
ragge
1.4
925                 return r[CLASSA] < 14;
mickey
1.1
926         case CLASSB:
ragge
1.4
927                 return r[CLASSB] < 16;
mickey
1.1
928         }
929         return 0/* XXX gcc */
930 }
931
932 char *rnames[] = {
ragge
1.4
933         "%rax""%rdx""%rcx""%rbx""%rsi""%rdi""%rbp""%rsp",
934         "%r8""%r9""%r10""%r11""%r12""%r13""%r14""%r15",
935         "%xmm0""%xmm1""%xmm2""%xmm3""%xmm4""%xmm5""%xmm6""%xmm7",
936         "%xmm8""%xmm9""%xmm10""%xmm11""%xmm12""%xmm13""%xmm14",
937         "%xmm15",
938 };
939
940 /* register names for shorter sizes */
941 char *rbyte[] = {
942         "%al""%dl""%cl""%bl""%sil""%dil""%bpl""%spl",
943         "%r8b""%r9b""%r10b""%r11b""%r12b""%r13b""%r14b""%r15b"
944 };
945 char *rshort[] = {
946         "%ax""%dx""%cx""%bx""%si""%di""%bp""%sp",
947         "%r8w""%r9w""%r10w""%r11w""%r12w""%r13w""%r14w""%r15w"
948 };
949 char *rlong[] = {
mickey
1.1
950         "%eax""%edx""%ecx""%ebx""%esi""%edi""%ebp""%esp",
ragge
1.7
951         "%r8d""%r9d""%r10d""%r11d""%r12d""%r13d""%r14d""%r15d"
mickey
1.1
952 };
953
ragge
1.4
954
mickey
1.1
955 /*
956  * Return a class suitable for a specific type.
957  */
958 int
959 gclass(TWORD t)
960 {
ragge
1.4
961         if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
mickey
1.1
962                 return CLASSB;
963         return CLASSA;
964 }
965
966 /*
967  * Calculate argument sizes.
968  */
969 void
970 lastcall(NODE *p)
971 {
972         NODE *op = p;
973         int size = 0;
974
975         p->n_qual = 0;
976         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
977                 return;
978         for (p = p->n_rightp->n_op == CMp = p->n_left)
979                 size += argsiz(p->n_right);
980         size += argsiz(p);
ragge
1.10
981         size = (size+15) & ~15;
982         if (size)
983                 printf("        subq $%d,%s\n"sizernames[RSP]);
mickey
1.1
984         op->n_qual = size/* XXX */
985 }
986
987 /*
988  * Special shapes.
989  */
990 int
991 special(NODE *pint shape)
992 {
993         int o = p->n_op;
994
995         switch (shape) {
996         case SFUNCALL:
997                 if (o == STCALL || o == USTCALL)
998                         return SRREG;
999                 break;
1000         case SPCON:
1001                 if (o != ICON || p->n_name[0] ||
1002                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
1003                         break;
1004                 return SRDIR;
1005         case SMIXOR:
1006                 return tshape(pSZERO);
1007         case SMILWXOR:
1008                 if (o != ICON || p->n_name[0] ||
1009                     p->n_lval == 0 || p->n_lval & 0xffffffff)
1010                         break;
1011                 return SRDIR;
1012         case SMIHWXOR:
1013                 if (o != ICON || p->n_name[0] ||
1014                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
1015                         break;
1016                 return SRDIR;
ragge
1.12
1017         case SCON32:
1018                 if (o != ICON || p->n_name[0])
1019                         break;
1020                 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT)
1021                         break;
1022                 return SRDIR;
1023         default:
1024                 cerror("special: %x\n"shape);
mickey
1.1
1025         }
1026         return SRNOPE;
1027 }
1028
1029 /*
1030  * Target-dependent command-line options.
1031  */
1032 void
1033 mflags(char *str)
1034 {
1035 }
1036
1037 /*
1038  * Do something target-dependent for xasm arguments.
1039  */
1040 int
1041 myxasm(struct interpass *ipNODE *p)
1042 {
ragge
1.15
1043         return 0;
ragge
1.4
1044 #if 0
mickey
1.1
1045         struct interpass *ip2;
1046         NODE *in = 0, *ut = 0;
1047         TWORD t;
1048         char *w;
1049         int reg;
1050         int cw;
1051
1052         cw = xasmcode(p->n_name);
1053         if (cw & (XASMASG|XASMINOUT))
1054                 ut = p->n_left;
1055         if ((cw & XASMASG) == 0)
1056                 in = p->n_left;
1057
1058         switch (XASMVAL(cw)) {
1059         case 'D'reg = EDIbreak;
1060         case 'S'reg = ESIbreak;
1061         case 'a'reg = EAXbreak;
1062         case 'b'reg = EBXbreak;
1063         case 'c'reg = ECXbreak;
1064         case 'd'reg = EDXbreak;
1065         case 't'reg = 0break;
1066         case 'u'reg = 1break;
1067         case 'A'reg = EAXEDXbreak;
1068         case 'q'/* XXX let it be CLASSA as for now */
1069                 p->n_name = tmpstrdup(p->n_name);
1070                 w = strchr(p->n_name'q');
1071                 *w = 'r';
1072                 return 0;
1073         default:
1074                 return 0;
1075         }
1076         p->n_name = tmpstrdup(p->n_name);
1077         for (w = p->n_name; *ww++)
1078                 ;
1079         w[-1] = 'r'/* now reg */
1080         t = p->n_left->n_type;
1081         if (reg == EAXEDX) {
1082                 p->n_label = CLASSC;
1083         } else {
1084                 p->n_label = CLASSA;
1085                 if (t == CHAR || t == UCHAR) {
1086                         p->n_label = CLASSB;
1087                         reg = reg * 2 + 8;
1088                 }
1089         }
1090         if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
1091                 p->n_label = CLASSD;
1092                 reg += 037;
1093         }
1094
1095         if (in && ut)
1096                 in = tcopy(in);
1097         p->n_left = mklnode(REG0regt);
1098         if (ut) {
1099                 ip2 = ipnode(mkbinode(ASSIGNuttcopy(p->n_left), t));
1100                 DLIST_INSERT_AFTER(ipip2qelem);
1101         }
1102         if (in) {
1103                 ip2 = ipnode(mkbinode(ASSIGNtcopy(p->n_left), int));
1104                 DLIST_INSERT_BEFORE(ipip2qelem);
1105         }
ragge
1.4
1106 #endif
mickey
1.1
1107         return 1;
1108 }
1109
1110 void
1111 targarg(char *wvoid *arg)
1112 {
ragge
1.4
1113 cerror("targarg");
1114 #if 0
mickey
1.1
1115         NODE **ary = arg;
1116         NODE *p, *q;
1117
1118         p = ary[(int)w[1]-'0']->n_left;
1119         if (optype(p->n_op) != LTYPE)
1120                 comperr("bad xarg op %d"p->n_op);
1121         q = tcopy(p);
1122         if (q->n_op == REG) {
1123                 if (*w == 'k') {
1124                         q->n_type = INT;
1125                 } else if (*w != 'w') {
1126                         if (q->n_type > UCHAR) {
1127                                 regno(q) = regno(q)*2+8;
1128                                 if (*w == 'h')
1129                                         regno(q)++;
1130                         }
1131                         q->n_type = INT;
1132                 } else
1133                         q->n_type = SHORT;
1134         }
1135         adrput(stdoutq);
1136         tfree(q);
ragge
1.4
1137 #endif
mickey
1.1
1138 }
1139
1140 /*
1141  * target-specific conversion of numeric arguments.
1142  */
1143 int
1144 numconv(void *ipvoid *p1void *q1)
1145 {
1146         NODE *p = p1, *q = q1;
1147         int cw = xasmcode(q->n_name);
1148
1149         switch