Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20080622152459

Diff

Diff from 1.103 to:

Annotations

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

Annotated File View

ragge
1.103
1 /*      $Id: local2.c,v 1.103 2008/06/22 15:24:59 ragge Exp $   */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 # include "pass2.h"
30 # include <ctype.h>
ragge
1.65
31 # include <string.h>
ragge
1.1
32
33 void acon(NODE *p);
34 int argsize(NODE *p);
35
ragge
1.71
36 static int stkpos;
37
ragge
1.1
38 void
39 deflab(int label)
40 {
41         printf(LABFMT ":\n"label);
42 }
43
ragge
1.48
44 static int regoff[7];
ragge
1.28
45 static TWORD ftype;
ragge
1.1
46
ragge
1.45
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 {
ragge
1.93
54         static int lwnr;
ragge
1.48
55         int ij;
ragge
1.45
56
57         printf("        pushl %%ebp\n");
58         printf("        movl %%esp,%%ebp\n");
59         if (addto)
60                 printf("        subl $%d,%%esp\n"addto);
ragge
1.48
61         for (i = ipp->ipp_regsj = 0ii >>= 1j++)
62                 if (i & 1)
63                         fprintf(stdout"       movl %s,-%d(%s)\n",
64                             rnames[j], regoff[j], rnames[FPREG]);
ragge
1.93
65         if (kflag == 0)
66                 return;
ragge
1.96
67         /* if ebx are not saved to stack, it must be moved into another reg */
68         /* check and emit the move before GOT stuff */
69         if ((ipp->ipp_regs & (1 << EBX)) == 0) {
70                 struct interpass *ip = (struct interpass *)ipp;
71
72                 ip = DLIST_PREV(ipqelem);
73                 ip = DLIST_PREV(ipqelem);
74                 ip = DLIST_PREV(ipqelem);
75                 if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
76                     ip->ip_node->n_left->n_op != REG)
77                         comperr("prtprolog pic error");
78                 ip = (struct interpass *)ipp;
79                 ip = DLIST_NEXT(ipqelem);
80                 if (ip->type != IP_NODE || ip->ip_node->n_op != ASSIGN ||
81                     ip->ip_node->n_left->n_op != REG)
82                         comperr("prtprolog pic error2");
83                 printf("        movl %s,%s\n",
84                     rnames[ip->ip_node->n_right->n_rval],
85                     rnames[ip->ip_node->n_left->n_rval]);
86                 tfree(ip->ip_node);
87                 DLIST_REMOVE(ipqelem);
88         }
ragge
1.93
89         printf("        call .LW%d\n", ++lwnr);
90         printf(".LW%d:\n"lwnr);
91         printf("        popl %%ebx\n");
92         printf("        addl $_GLOBAL_OFFSET_TABLE_+[.-.LW%d], %%ebx\n",
93             lwnr);
ragge
1.45
94 }
95
96 /*
ragge
1.71
97  * calculate stack size and offsets
98  */
ragge
1.45
99 static int
100 offcalc(struct interpass_prolog *ipp)
101 {
ragge
1.48
102         int ijaddto;
ragge
1.45
103
104         addto = p2maxautooff;
ragge
1.71
105         if (addto >= AUTOINIT/SZCHAR)
106                 addto -= AUTOINIT/SZCHAR;
ragge
1.48
107         for (i = ipp->ipp_regsj = 0i ; i >>= 1j++) {
108                 if (i & 1) {
109                         addto += SZINT/SZCHAR;
110                         regoff[j] = addto;
111                 }
ragge
1.45
112         }
113         return addto;
114 }
115
ragge
1.49
116 void
117 prologue(struct interpass_prolog *ipp)
118 {
119         int addto;
120
121         ftype = ipp->ipp_type;
ragge
1.102
122 #ifdef LANG_F77
ragge
1.49
123         if (ipp->ipp_vis)
124                 printf("        .globl %s\n"ipp->ipp_name);
125         printf("        .align 4\n");
126         printf("%s:\n"ipp->ipp_name);
ragge
1.100
127 #endif
ragge
1.49
128         /*
129          * We here know what register to save and how much to 
130          * add to the stack.
131          */
132         addto = offcalc(ipp);
133         prtprolog(ippaddto);
134 }
135
136 void
137 eoftn(struct interpass_prolog *ipp)
138 {
139         int ij;
140
141         if (ipp->ipp_ip.ip_lbl == 0)
142                 return/* no code needs to be generated */
143
144         /* return from function code */
145         for (i = ipp->ipp_regsj = 0i ; i >>= 1j++) {
146                 if (i & 1)
147                         fprintf(stdout"       movl -%d(%s),%s\n",
148                             regoff[j], rnames[FPREG], rnames[j]);
149                         
150         }
151
152         /* struct return needs special treatment */
153         if (ftype == STRTY || ftype == UNIONTY) {
154                 printf("        movl 8(%%ebp),%%eax\n");
155                 printf("        leave\n");
156                 printf("        ret $4\n");
157         } else {
158                 printf("        leave\n");
159                 printf("        ret\n");
160         }
161 }
ragge
1.1
162
163 /*
164  * add/sub/...
165  *
166  * Param given:
167  */
168 void
169 hopcode(int fint o)
170 {
171         char *str;
172
173         switch (o) {
174         case PLUS:
175                 str = "add";
176                 break;
177         case MINUS:
178                 str = "sub";
179                 break;
180         case AND:
181                 str = "and";
182                 break;
183         case OR:
ragge
1.10
184                 str = "or";
ragge
1.1
185                 break;
186         case ER:
187                 str = "xor";
188                 break;
189         default:
ragge
1.14
190                 comperr("hopcode2: %d"o);
ragge
1.32
191                 str = 0/* XXX gcc */
ragge
1.1
192         }
ragge
1.7
193         printf("%s%c"strf);
ragge
1.1
194 }
195
ragge
1.72
196 /*
197  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
198  */
ragge
1.1
199 int
200 tlen(pNODE *p;
201 {
202         switch(p->n_type) {
203                 case CHAR:
204                 case UCHAR:
205                         return(1);
206
207                 case SHORT:
208                 case USHORT:
209                         return(SZSHORT/SZCHAR);
210
211                 case DOUBLE:
212                         return(SZDOUBLE/SZCHAR);
213
214                 case INT:
215                 case UNSIGNED:
216                 case LONG:
217                 case ULONG:
218                         return(SZINT/SZCHAR);
219
220                 case LONGLONG:
221                 case ULONGLONG:
222                         return SZLONGLONG/SZCHAR;
223
224                 default:
225                         if (!ISPTR(p->n_type))
ragge
1.14
226                                 comperr("tlen type %d not pointer");
ragge
1.39
227                         return SZPOINT(p->n_type)/SZCHAR;
ragge
1.1
228                 }
229 }
230
ragge
1.17
231 /*
232  * Emit code to compare two longlong numbers.
233  */
234 static void
235 twollcomp(NODE *p)
236 {
237         int o = p->n_op;
238         int s = getlab();
239         int e = p->n_label;
240         int cb1cb2;
241
242         if (o >= ULE)
243                 o -= (ULE-LE);
244         switch (o) {
245         case NE:
246                 cb1 = 0;
247                 cb2 = NE;
248                 break;
249         case EQ:
250                 cb1 = NE;
251                 cb2 = 0;
252                 break;
253         case LE:
254         case LT:
255                 cb1 = GT;
256                 cb2 = LT;
257                 break;
258         case GE:
259         case GT:
260                 cb1 = LT;
261                 cb2 = GT;
262                 break;
263         
ragge
1.32
264         default:
265                 cb1 = cb2 = 0/* XXX gcc */
ragge
1.17
266         }
267         if (p->n_op >= ULE)
268                 cb1 += 4cb2 += 4;
269         expand(p0"  cmpl UR,UL\n");
270         if (cb1cbgen(cb1s);
271         if (cb2cbgen(cb2e);
272         expand(p0"  cmpl AR,AL\n");
273         cbgen(p->n_ope);
274         deflab(s);
275 }
276
stefan
1.98
277 int
278 fldexpand(NODE *pint cookiechar **cp)
279 {
280         CONSZ val;
281
282         if (p->n_op == ASSIGN)
283                 p = p->n_left;
284         switch (**cp) {
285         case 'S':
286                 printf("%d"UPKFSZ(p->n_rval));
287                 break;
288         case 'H':
289                 printf("%d"UPKFOFF(p->n_rval));
290                 break;
291         case 'M':
292         case 'N':
stefan
1.99
293                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
stefan
1.98
294                 --val;
295                 val <<= UPKFOFF(p->n_rval);
stefan
1.99
296                 printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
stefan
1.98
297                 break;
298         default:
299                 comperr("fldexpand");
300         }
301         return 1;
302 }
303
ragge
1.22
304 static void
stefan
1.98
305 bfext(NODE *p)
ragge
1.22
306 {
stefan
1.98
307         int ch = 0sz = 0;
308
309         if (ISUNSIGNED(p->n_right->n_type))
310                 return;
311         switch (p->n_right->n_type) {
312         case CHAR:
313                 ch = 'b';
314                 sz = 8;
315                 break;
316         case SHORT:
317                 ch = 'w';
318                 sz = 16;
319                 break;
320         case INT:
321         case LONG:
322                 ch = 'l';
323                 sz = 32;
324                 break;
325         default:
326                 comperr("bfext");
ragge
1.22
327         }
328
stefan
1.98
329         sz -= UPKFSZ(p->n_left->n_rval);
330         printf("\tshl%c $%d,"chsz);
331         adrput(stdoutgetlr(p'D'));
332         printf("\n\tsar%c $%d,"chsz);
333         adrput(stdoutgetlr(p'D'));
334         printf("\n");
ragge
1.22
335 }
336
ragge
1.23
337 /*
338  * Push a structure on stack as argument.
339  * the scratch registers are already free here
340  */
341 static void
342 starg(NODE *p)
343 {
344         FILE *fp = stdout;
345
346         fprintf(fp"   subl $%d,%%esp\n"p->n_stsize);
347         fprintf(fp"   pushl $%d\n"p->n_stsize);
348         expand(p0"  pushl AL\n");
349         expand(p0"  leal 8(%esp),A1\n");
350         expand(p0"  pushl A1\n");
351         fprintf(fp"   call memcpy\n");
352         fprintf(fp"   addl $12,%%esp\n");
353 }
354
ragge
1.25
355 /*
356  * Compare two floating point numbers.
357  */
358 static void
359 fcomp(NODE *p)  
360 {
361         
ragge
1.83
362         if (p->n_left->n_op == REG) {
363                 if (p->n_su & DORIGHT)
364                         expand(p0"  fxch\n");
ragge
1.25
365                 expand(p0"  fucompp\n");    /* emit compare insn  */
ragge
1.83
366         } else if (p->n_left->n_type == DOUBLE)
ragge
1.27
367                 expand(p0"  fcompl AL\n");  /* emit compare insn  */
368         else if (p->n_left->n_type == FLOAT)
369                 expand(p0"  fcomp AL\n");   /* emit compare insn  */
ragge
1.25
370         else
ragge
1.27
371                 comperr("bad compare %p\n"p);
ragge
1.25
372         expand(p0"  fnstsw %ax\n"); /* move status reg to ax */
373         
374         switch (p->n_op) {
375         case EQ:
376                 expand(p0"  andb $64,%ah\n  jne LC\n");
377                 break;
378         case NE:
379                 expand(p0"  andb $64,%ah\n  je LC\n");
380                 break;
381         case LE:
ragge
1.27
382                 expand(p0"  andb $65,%ah\n  cmpb $1,%ah\n   jne LC\n");
ragge
1.25
383                 break;
384         case LT:
ragge
1.27
385                 expand(p0"  andb $65,%ah\n  je LC\n");
ragge
1.25
386                 break;
387         case GT:
ragge
1.27
388                 expand(p0"  andb $1,%ah\n   jne LC\n");
ragge
1.25
389                 break;
390         case GE:
ragge
1.27
391                 expand(p0"  andb $65,%ah\n  jne LC\n");
ragge
1.25
392                 break;
393         default:
394                 comperr("fcomp op %d\n"p->n_op);
395         }
396 }
397
ragge
1.29
398 /*
399  * Convert an unsigned long long to floating point number.
400  */
401 static void
402 ulltofp(NODE *p)
403 {
404         static int loadlab;
405         int jmplab;
406
407         if (loadlab == 0) {
408                 loadlab = getlab();
409                 expand(p0"  .data\n");
410                 printf(LABFMT ":        .long 0,0x80000000,0x403f\n"loadlab);
411                 expand(p0"  .text\n");
412         }
413         jmplab = getlab();
414         expand(p0"  pushl UL\n      pushl AL\n");
415         expand(p0"  fildq (%esp)\n");
416         expand(p0"  addl $8,%esp\n");
417         expand(p0"  cmpl $0,UL\n");
418         printf("        jge " LABFMT "\n"jmplab);
419         printf("        fldt " LABFMT "\n"loadlab);
420         printf("        faddp %%st,%%st(1)\n");
421         printf(LABFMT ":\n"jmplab);
422 }
423
ragge
1.69
424 static int
425 argsiz(NODE *p)
426 {
427         TWORD t = p->n_type;
428
ragge
1.81
429         if (t < LONGLONG || t == FLOAT || t > BTMASK)
ragge
1.69
430                 return 4;
431         if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
432                 return 8;
433         if (t == LDOUBLE)
434                 return 12;
ragge
1.81
435         if (t == STRTY || t == UNIONTY)
ragge
1.69
436                 return p->n_stsize;
437         comperr("argsiz");
438         return 0;
439 }
440
ragge
1.1
441 void
442 zzzcode(NODE *pint c)
443 {
ragge
1.59
444         NODE *r, *l;
ragge
1.87
445         int prlrs;
ragge
1.69
446         char *ch;
ragge
1.1
447
448         switch (c) {
ragge
1.84
449         case 'A'/* swap st0 and st1 if right is evaluated second */
ragge
1.83
450                 if ((p->n_su & DORIGHT) == 0) {
451                         if (logop(p->n_op))
452                                 printf("        fxch\n");
453                         else
454                                 printf("r");
455                 }
456                 break;
ragge
1.9
457
ragge
1.12
458         case 'C':  /* remove from stack after subroutine call */
ragge
1.71
459                 pr = p->n_qual;
ragge
1.80
460                 if (p->n_op == STCALL || p->n_op == USTCALL)
ragge
1.71
461                         pr += 4;
ragge
1.69
462                 if (p->n_op == UCALL)
463                         return/* XXX remove ZC from UCALL */
ragge
1.71
464                 if (pr)
465                         printf("        addl $%d, %s\n"prrnames[ESP]);
ragge
1.12
466                 break;
ragge
1.17
467
468         case 'D'/* Long long comparision */
469                 twollcomp(p);
470                 break;
ragge
1.12
471
stefan
1.98
472         case 'E'/* Perform bitfield sign-extension */
473                 bfext(p);
ragge
1.22
474                 break;
475
ragge
1.23
476         case 'F'/* Structure argument */
ragge
1.71
477                 if (p->n_stalign != 0/* already on stack */
478                         starg(p);
ragge
1.23
479                 break;
480
ragge
1.25
481         case 'G'/* Floating point compare */
482                 fcomp(p);
483                 break;
484
ragge
1.29
485         case 'J'/* convert unsigned long long to floating point */
486                 ulltofp(p);
487                 break;
488
ragge
1.59
489         case 'M'/* Output sconv move, if needed */
490                 l = getlr(p'L');
491                 /* XXX fixneed: regnum */
ragge
1.68
492                 pr = DECRA(p->n_reg0);
493                 lr = DECRA(l->n_reg0);
ragge
1.66
494                 if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
495                     (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
ragge
1.59
496                         ;
497                 else
ragge
1.66
498                         printf("        movb %%%cl,%s\n",
499                             rnames[lr][2], rnames[pr]);
ragge
1.59
500                 l->n_rval = l->n_reg = p->n_reg/* XXX - not pretty */
501                 break;
ragge
1.67
502
503         case 'N'/* output extended reg name */
504                 printf("%s"rnames[getlr(p'1')->n_rval]);
505                 break;
506
ragge
1.69
507         case 'O'/* print out emulated ops */
ragge
1.76
508                 pr = 16;
509                 if (p->n_op == RS || p->n_op == LS) {
ragge
1.70
510                         expand(pINAREG"\tpushl AR\n");
ragge
1.76
511                         pr = 12;
512                 } else
ragge
1.70
513                         expand(pINCREG"\tpushl UR\n\tpushl AR\n");
ragge
1.69
514                 expand(pINCREG"\tpushl UL\n\tpushl AL\n");
515                 if (p->n_op == DIV && p->n_type == ULONGLONGch = "udiv";
516                 else if (p->n_op == DIVch = "div";
517                 else if (p->n_op == MULch = "mul";
518                 else if (p->n_op == MOD && p->n_type == ULONGLONGch = "umod";
519                 else if (p->n_op == MODch = "mod";
520                 else if (p->n_op == RS && p->n_type == ULONGLONGch = "lshr";
521                 else if (p->n_op == RSch = "ashr";
522                 else if (p->n_op == LSch = "ashl";
523                 else ch = 0comperr("ZO");
ragge
1.76
524                 printf("\tcall __%sdi3\n\taddl $%d,%s\n"chprrnames[ESP]);
ragge
1.69
525                 break;
526
ragge
1.71
527         case 'P'/* push hidden argument on stack */
528                 r = (NODE *)p->n_sue;
ragge
1.76
529                 printf("\tleal -%d(%%ebp),"stkpos);
ragge
1.71
530                 adrput(stdoutgetlr(p'1'));
531                 printf("\n\tpushl ");
532                 adrput(stdoutgetlr(p'1'));
533                 putchar('\n');
534                 break;
535
536         case 'Q'/* emit struct assign */
537                 /* XXX - optimize for small structs */
538                 printf("\tpushl $%d\n"p->n_stsize);
539                 expand(pINAREG"\tpushl AR\n");
540                 expand(pINAREG"\tleal AL,%eax\n\tpushl %eax\n");
541                 printf("\tcall memcpy\n");
ragge
1.77
542                 printf("\taddl $12,%%esp\n");
ragge
1.71
543                 break;
544
ragge
1.73
545         case 'S'/* emit eventual move after cast from longlong */
546                 pr = DECRA(p->n_reg0);
547                 lr = p->n_left->n_rval;
548                 switch (p->n_type) {
549                 case CHAR:
550                 case UCHAR:
ragge
1.75
551                         if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
552                             rnames[pr][1] == rnames[lr][1])
553                                 break;
554                         if (rnames[lr][2] == 'x') {
555                                 printf("\tmovb %%%cl,%s\n",
556                                     rnames[lr][1], rnames[pr]);
557                                 break;
558                         }
ragge
1.87
559                         /* Must go via stack */
560                         s = BITOOR(freetemp(1));
561                         printf("\tmovl %%e%ci,%d(%%ebp)\n"rnames[lr][1], s);
562                         printf("\tmovb %d(%%ebp),%s\n"srnames[pr]);
563 //                      comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
ragge
1.73
564                         break;
ragge
1.74
565
ragge
1.79
566                 case SHORT:
567                 case USHORT:
568                         if (rnames[lr][1] == rnames[pr][2] &&
569                             rnames[lr][2] == rnames[pr][3])
570                                 break;
571                         printf("\tmovw %%%c%c,%%%s\n",
572                             rnames[lr][1], rnames[lr][2], rnames[pr]+2);
573                         break;
ragge
1.74
574                 case INT:
575                 case UNSIGNED:
ragge
1.78
576                         if (rnames[lr][1] == rnames[pr][2] &&
577                             rnames[lr][2] == rnames[pr][3])
578                                 break;
579                         printf("\tmovl %%e%c%c,%s\n",
580                                     rnames[lr][1], rnames[lr][2], rnames[pr]);
ragge
1.74
581                         break;
582
ragge
1.73
583                 default:
ragge
1.78
584                         if (rnames[lr][1] == rnames[pr][2] &&
585                             rnames[lr][2] == rnames[pr][3])
586                                 break;
587                         comperr("SCONV2 %s->%s"rnames[lr], rnames[pr]);
ragge
1.73
588                         break;
589                 }
590                 break;
591
ragge
1.1
592         default:
ragge
1.14
593                 comperr("zzzcode %c"c);
ragge
1.1
594         }
595 }
596
597 /*ARGSUSED*/
598 int
599 rewfld(NODE *p)
600 {
601         return(1);
602 }
603
604 int canaddr(NODE *);
605 int
606 canaddr(NODE *p)
607 {
608         int o = p->n_op;
609
610         if (o==NAME || o==REG || o==ICON || o==OREG ||
ragge
1.12
611             (o==UMUL && shumul(p->n_left)))
ragge
1.1
612                 return(1);
613         return(0);
614 }
615
ragge
1.21
616 /*
617  * Does the bitfield shape match?
618  */
ragge
1.1
619 int
620 flshape(NODE *p)
621 {
ragge
1.22
622         int o = p->n_op;
623
624         if (o == OREG || o == REG || o == NAME)
625                 return SRDIR/* Direct match */
626         if (o == UMUL && shumul(p->n_left))
627                 return SROREG/* Convert into oreg */
628         return SRREG/* put it into a register */
ragge
1.1
629 }
630
631 /* INTEMP shapes must not contain any temporary registers */
ragge
1.15
632 /* XXX should this go away now? */
ragge
1.1
633 int
634 shtemp(NODE *p)
635 {
ragge
1.15
636         return 0;
637 #if 0
ragge
1.1
638         int r;
639
640         if (p->n_op == STARG )
641                 p = p->n_left;
642
643         switch (p->n_op) {
644         case REG:
645                 return (!istreg(p->n_rval));
646
647         case OREG:
648                 r = p->n_rval;
649                 if (R2TEST(r)) {
650                         if (istreg(R2UPK1(r)))
651                                 return(0);
652                         r = R2UPK2(r);
653                 }
654                 return (!istreg(r));
655
ragge
1.12
656         case UMUL:
ragge
1.1
657                 p = p->n_left;
ragge
1.12
658                 return (p->n_op != UMUL && shtemp(p));
ragge
1.1
659         }
660
661         if (optype(p->n_op) != LTYPE)
662                 return(0);
663         return(1);
ragge
1.15
664 #endif
ragge
1.1
665 }
666
667 void
668 adrcon(CONSZ val)
669 {
ragge
1.2
670         printf("$" CONFMTval);
ragge
1.1
671 }
672
673 void
ragge
1.14
674 conput(FILE *fpNODE *p)
ragge
1.1
675 {
ragge
1.17
676         int val = p->n_lval;
677
ragge
1.1
678         switch (p->n_op) {
679         case ICON:
ragge
1.17
680                 if (p->n_name[0] != '\0') {
ragge
1.14
681                         fprintf(fp"%s"p->n_name);
ragge
1.17
682                         if (val)
683                                 fprintf(fp"+%d"val);
684                 } else
685                         fprintf(fp"%d"val);
ragge
1.1
686                 return;
687
688         default:
ragge
1.74
689                 comperr("illegal conput, p %p"p);
ragge
1.1
690         }
691 }
692
693 /*ARGSUSED*/
694 void
695 insput(NODE *p)
696 {
ragge
1.14
697         comperr("insput");
ragge
1.1
698 }
699
700 /*
701  * Write out the upper address, like the upper register of a 2-register
702  * reference, or the next memory location.
703  */
704 void
705 upput(NODE *pint size)
706 {
707
ragge
1.17
708         size /= SZCHAR;
ragge
1.1
709         switch (p->n_op) {
710         case REG:
ragge
1.63
711                 fprintf(stdout"%%%s", &rnames[p->n_rval][3]);
ragge
1.1
712                 break;
713
714         case NAME:
715         case OREG:
716                 p->n_lval += size;
ragge
1.12
717                 adrput(stdoutp);
ragge
1.1
718                 p->n_lval -= size;
719                 break;
720         case ICON:
ragge
1.17
721                 fprintf(stdout"$" CONFMTp->n_lval >> 32);
ragge
1.1
722                 break;
723         default:
ragge
1.14
724                 comperr("upput bad op %d size %d"p->n_opsize);
ragge
1.1
725         }
726 }
727
728 void
ragge
1.12
729 adrput(FILE *ioNODE *p)
ragge
1.1
730 {
731         int r;
732         /* output an address, with offsets, from p */
733
734         if (p->n_op == FLD)
735                 p = p->n_left;
736
737         switch (p->n_op) {
738
739         case NAME:
ragge
1.88
740                 if (p->n_name[0] != '\0') {
ragge
1.13
741                         fputs(p->n_nameio);
ragge
1.88
742                         if (p->n_lval != 0)
743                                 fprintf(io"+" CONFMTp->n_lval);
744                 } else
745                         fprintf(ioCONFMTp->n_lval);
ragge
1.1
746                 return;
747
748         case OREG:
749                 r = p->n_rval;
ragge
1.92
750                 if (p->n_name[0])
751                         printf("%s%s"p->n_namep->n_lval ? "+" : "");
ragge
1.17
752                 if (p->n_lval)
753                         fprintf(io"%d", (int)p->n_lval);
ragge
1.82
754                 if (R2TEST(r)) {
755                         fprintf(io"(%s,%s,4)"rnames[R2UPK1(r)],
756                             rnames[R2UPK2(r)]);
757                 } else
758                         fprintf(io"(%s)"rnames[p->n_rval]);
ragge
1.1
759                 return;
760         case ICON:
ragge
1.97
761 #ifdef PCC_DEBUG
762                 /* Sanitycheck for PIC, to catch adressable constants */
763                 if (kflag && p->n_name[0]) {
764                         static int foo;
765
766                         if (foo++ == 0) {
767                                 printf("\nfailing...\n");
768                                 fwalk(pe2print0);
769                                 comperr("pass2 conput");
770                         }
771                 }
772 #endif
ragge
1.1
773                 /* addressable value of the constant */
ragge
1.14
774                 fputc('$'io);
775                 conput(iop);
ragge
1.1
776                 return;
777
778         case REG:
ragge
1.66
779                 switch (p->n_type) {
780                 case LONGLONG:
781                 case ULONGLONG:
ragge
1.63
782                         fprintf(io"%%%c%c%c"rnames[p->n_rval][0],
783                             rnames[p->n_rval][1], rnames[p->n_rval][2]);
ragge
1.66
784                         break;
785                 case SHORT:
786                 case USHORT:
787                         fprintf(io"%%%s", &rnames[p->n_rval][2]);
788                         break;
789                 default:
ragge
1.63
790                         fprintf(io"%s"rnames[p->n_rval]);
ragge
1.66
791                 }
ragge
1.1
792                 return;
793
794         default:
ragge
1.26
795                 comperr("illegal address, op %d, node %p"p->n_opp);
ragge
1.1
796                 return;
797
798         }
799 }
800
ragge
1.6
801 static char *
802 ccbranches[] = {
803         "je",           /* jumpe */
804         "jne",          /* jumpn */
805         "jle",          /* jumple */
806         "jl",           /* jumpl */
807         "jge",          /* jumpge */
808         "jg",           /* jumpg */
809         "jbe",          /* jumple (jlequ) */
810         "jb",           /* jumpl (jlssu) */
811         "jae",          /* jumpge (jgequ) */
812         "ja",           /* jumpg (jgtru) */
813 };
814
ragge
1.1
815
816 /*   printf conditional and unconditional branches */
817 void
ragge
1.6
818 cbgen(int oint lab)
ragge
1.1
819 {
ragge
1.6
820         if (o < EQ || o > UGT)
ragge
1.14
821                 comperr("bad conditional branch: %s"opst[o]);
ragge
1.6
822         printf("        %s " LABFMT "\n"ccbranches[o-EQ], lab);
ragge
1.1
823 }
824
ragge
1.28
825 static void
ragge
1.71
826 fixcalls(NODE *p)
ragge
1.28
827 {
ragge
1.83
828         /* Prepare for struct return by allocating bounce space on stack */
ragge
1.71
829         switch (p->n_op) {
830         case STCALL:
831         case USTCALL:
ragge
1.77
832                 if (p->n_stsize+p2autooff > stkpos)
833                         stkpos = p->n_stsize+p2autooff;
ragge
1.71
834                 break;
835         }
ragge
1.83
836 }
837
838 /*
839  * Must store floats in memory if there are two function calls involved.
840  */
841 static int
842 storefloat(struct interpass *ipNODE *p)
843 {
844         int lr;
845
846         switch (optype(p->n_op)) {
847         case BITYPE:
848                 l = storefloat(ipp->n_left);
849                 r = storefloat(ipp->n_right);
850                 if (p->n_op == CM)
851                         return 0/* arguments, don't care */
852                 if (callop(p->n_op))
853                         return 1/* found one */
854 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
855         (p)->n_type == LDOUBLE)
856                 if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
857                         /* must store one. store left */
858                         struct interpass *nip;
859                         TWORD t = p->n_left->n_type;
860                         NODE *ll;
861                         int off;
862
863                         off = BITOOR(freetemp(szty(t)));
864                         ll = mklnode(OREGoffFPREGt);
865                         nip = ipnode(mkbinode(ASSIGNllp->n_leftt));
866                         p->n_left = mklnode(OREGoffFPREGt);
867                         DLIST_INSERT_BEFORE(ipnipqelem);
868                 }
869                 return l|r;
870
871         case UTYPE:
872                 l = storefloat(ipp->n_left);
873                 if (callop(p->n_op))
874                         l = 1;
875                 return l;
876         default:
877                 return 0;
878         }
ragge
1.28
879 }
ragge
1.1
880
881 void
ragge
1.71
882 myreader(struct interpass *ipole)
883 {
884         struct interpass *ip;
885
886         stkpos = p2autooff;
887         DLIST_FOREACH(ipipoleqelem) {
888                 if (ip->type != IP_NODE)
889                         continue;
890                 walkf(ip->ip_nodefixcalls);
ragge
1.83
891                 storefloat(ipip->ip_node);
ragge
1.1
892         }
ragge
1.77
893         if (stkpos > p2autooff)
894                 p2autooff = stkpos;
895         if (stkpos > p2maxautooff)
896                 p2maxautooff = stkpos;
ragge
1.71
897         if (x2debug)
898                 printip(ipole);
ragge
1.1
899 }
900
901 /*
902  * Remove some PCONVs after OREGs are created.
903  */
904 static void
905 pconv2(NODE *p)
906 {
907         NODE *q;
908
909         if (p->n_op == PLUS) {
910                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
911                         if (p->n_right->n_op != ICON)
912                                 return;
913                         if (p->n_left->n_op != PCONV)
914                                 return;
915                         if (p->n_left->n_left->n_op != OREG)
916                                 return;
917                         q = p->n_left->n_left;
918                         nfree(p->n_left);
919                         p->n_left = q;
920                         /*
921                          * This will be converted to another OREG later.
922                          */
923                 }
924         }
925 }
926
927 void
928 mycanon(NODE *p)
929 {
930         walkf(ppconv2);
931 }
932
ragge
1.25
933 void
ragge
1.1
934 myoptim(struct interpass *ip)
935 {
936 }
ragge
1.17
937
ragge
1.86
938 static char rl[] =
939   { EAXEAXEAXEAXEAXEDXEDXEDXEDXECXECXECXEBXEBXESI };
940 static char rh[] =
941   { EDXECXEBXESIEDIECXEBXESIEDIEBXESIEDIESIEDIEDI };
ragge
1.85
942
ragge
1.46
943 void
ragge
1.65
944 rmove(int sint dTWORD t)
ragge
1.46
945 {
ragge
1.85
946         int slshdldh;
947
ragge
1.65
948         switch (t) {
949         case LONGLONG:
950         case ULONGLONG:
ragge
1.85
951 #if 1
ragge
1.86
952                 sl = rl[s-EAXEDX];
953                 sh = rh[s-EAXEDX];
954                 dl = rl[d-EAXEDX];
955                 dh = rh[d-EAXEDX];
ragge
1.85
956
957                 /* sanity checks, remove when satisfied */
958                 if (memcmp(rnames[s], rnames[sl]+13) != 0 ||
959                     memcmp(rnames[s]+3rnames[sh]+13) != 0)
960                         comperr("rmove source error");
961                 if (memcmp(rnames[d], rnames[dl]+13) != 0 ||
962                     memcmp(rnames[d]+3rnames[dh]+13) != 0)
963                         comperr("rmove dest error");
964 #define SW(x,y) { int i = x; x = y; y = i; }
965                 if (sl == dh || sh == dl) {
966                         /* Swap if moving to itself */
967                         SW(slsh);
968                         SW(dldh);
969                 }
970                 if (sl != dl)
971                         printf("        movl %s,%s\n"rnames[sl], rnames[dl]);
972                 if (sh != dh)
973                         printf("        movl %s,%s\n"rnames[sh], rnames[dh]);
974 #else
ragge
1.65
975                 if (memcmp(rnames[s], rnames[d], 3) != 0)
976                         printf("        movl %%%c%c%c,%%%c%c%c\n",
977                             rnames[s][0],rnames[s][1],rnames[s][2],
978                             rnames[d][0],rnames[d][1],rnames[d][2]);
979                 if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
980                         printf("        movl %%%c%c%c,%%%c%c%c\n",
981                             rnames[s][3],rnames[s][4],rnames[s][5],
982                             rnames[d][3],rnames[d][4],rnames[d][5]);
ragge
1.85
983 #endif
ragge
1.65
984                 break;
985         case CHAR:
986         case UCHAR:
987                 printf("        movb %s,%s\n"rnames[s], rnames[d]);
988                 break;
989         case FLOAT:
990         case DOUBLE:
991         case LDOUBLE:
ragge
1.72
992 #ifdef notdef
993                 /* a=b()*c(); will generate this */
ragge
1.68
994                 comperr("bad float rmove: %d %d"sd);
ragge
1.72
995 #endif
996                 break;
ragge
1.52
997         default:
ragge
1.65
998                 printf("        movl %s,%s\n"rnames[s], rnames[d]);
ragge
1.59
999         }
1000 }
1001
ragge
1.51
1002 /*
ragge
1.57
1003  * For class c, find worst-case displacement of the number of
1004  * registers in the array r[] indexed by class.
1005  */
1006 int
1007 COLORMAP(int cint *r)
1008 {
1009         int num;
1010
1011         switch (c) {