Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20140528162811

Diff

Diff from 1.175 to:

Annotations

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

Annotated File View

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