Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20140524201125

Diff

Diff from 1.173 to:

Annotations

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

Annotated File View

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