Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120422210740

Diff

Diff from 1.167 to:

Annotations

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

Annotated File View

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