Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20081116133016

Diff

Diff from 1.116 to:

Annotations

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

Annotated File View

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