1 /*        Id: local2.c,v 1.28 2015/01/04 19:17:23 ragge Exp           */
2 /*        $NetBSD: local2.c,v 1.1.1.6 2016/02/09 20:28:31 plunky Exp $          */
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "pass1.h"  /* for cftnsp */
31 #include "pass2.h"
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #if defined(MACHOABI)
37 #define EXPREFIX    "_"
38 #else
39 #define EXPREFIX    ""
40 #endif
41 
42 #define LOWREG                0
43 #define HIREG                 1
44 
45 char *rnames[] = {
46           REGPREFIX "r0", REGPREFIX "r1",
47           REGPREFIX "r2", REGPREFIX "r3",
48           REGPREFIX "r4", REGPREFIX "r5",
49           REGPREFIX "r6", REGPREFIX "r7",
50           REGPREFIX "r8", REGPREFIX "r9",
51           REGPREFIX "r10", REGPREFIX "r11",
52           REGPREFIX "r12", REGPREFIX "r13",
53           REGPREFIX "r14", REGPREFIX "r15",
54           REGPREFIX "r16", REGPREFIX "r17",
55           REGPREFIX "r18", REGPREFIX "r19",
56           REGPREFIX "r20", REGPREFIX "r21",
57           REGPREFIX "r22", REGPREFIX "r23",
58           REGPREFIX "r24", REGPREFIX "r25",
59           REGPREFIX "r26", REGPREFIX "r27",
60           REGPREFIX "r28", REGPREFIX "r29",
61           REGPREFIX "r30", REGPREFIX "r31",
62           "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0",
63           "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16",
64           "r19r18", "r21r20", "r23r22", "r25r24", "r27r26",
65           "r29r28", "r31r30",
66           REGPREFIX "f0", REGPREFIX "f1",
67           REGPREFIX "f2", REGPREFIX "f3",
68           REGPREFIX "f4", REGPREFIX "f5",
69           REGPREFIX "f6", REGPREFIX "f7",
70           REGPREFIX "f8", REGPREFIX "f9",
71           REGPREFIX "f10", REGPREFIX "f11",
72           REGPREFIX "f12", REGPREFIX "f13",
73           REGPREFIX "f14", REGPREFIX "f15",
74           REGPREFIX "f16", REGPREFIX "f17",
75           REGPREFIX "f18", REGPREFIX "f19",
76           REGPREFIX "f20", REGPREFIX "f21",
77           REGPREFIX "f22", REGPREFIX "f23",
78           REGPREFIX "f24", REGPREFIX "f25",
79           REGPREFIX "f26", REGPREFIX "f27",
80           REGPREFIX "f28", REGPREFIX "f29",
81           REGPREFIX "f30", REGPREFIX "f31",
82 };
83 
84 static int argsize(NODE *p);
85 
86 static int p2calls;
87 static int p2temps;           /* TEMPs which aren't autos yet */
88 static int p2framesize;
89 static int p2maxstacksize;
90 
91 void
deflab(int label)92 deflab(int label)
93 {
94           printf(LABFMT ":\n", label);
95 }
96 
97 static TWORD ftype;
98 
99 /*
100  * Print out the prolog assembler.
101  */
102 void
prologue(struct interpass_prolog * ipp)103 prologue(struct interpass_prolog *ipp)
104 {
105           int addto;
106 
107 #ifdef PCC_DEBUG
108           if (x2debug)
109                     printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%lx, autos=%d, tmpnum=%d, lblnum=%d\n",
110                               ipp->ipp_ip.type,
111                               ipp->ipp_ip.lineno,
112                               ipp->ipp_name,
113                               ipp->ipp_vis,
114                               ipp->ipp_type,
115                               ipp->ipp_regs[0],
116                               ipp->ipp_autos,
117                               ipp->ip_tmpnum,
118                               ipp->ip_lblnum);
119 #endif
120 
121           ftype = ipp->ipp_type;
122 
123           addto = p2framesize;
124 
125           if (p2calls != 0 || kflag) {
126                     /* get return address (not required for leaf function) */
127                     printf("\tmflr %s\n", rnames[R0]);
128                     printf("\tstw %s,8(%s)\n", rnames[R0], rnames[R1]);
129           }
130           /* save registers R30 and R31 */
131           printf("\tstmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
132 #ifdef FPREG
133           printf("\tmr %s,%s\n", rnames[FPREG], rnames[R1]);
134 #endif
135           /* create the new stack frame */
136           if (addto > 32767) {
137                     printf("\tlis %s,%d\n", rnames[R0], (-addto) >> 16);
138                     printf("\tori %s,%s,%d\n", rnames[R0],
139                         rnames[R0], (-addto) & 0xffff);
140                     printf("\tstwux %s,%s,%s\n", rnames[R1],
141                         rnames[R1], rnames[R0]);
142           } else {
143                     printf("\tstwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]);
144           }
145 
146           if (kflag) {
147 #if defined(ELFABI)
148                     printf("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n");
149                     printf("\tmflr %s\n", rnames[GOTREG]);
150 #elif defined(MACHOABI)
151                     printf("\tbcl 20,31,L%s$pb\n", ipp->ipp_name + 1);
152                     printf("L%s$pb:\n", ipp->ipp_name + 1);
153                     printf("\tmflr %s\n", rnames[GOTREG]);
154 #endif
155           }
156 
157 }
158 
159 
160 void
eoftn(struct interpass_prolog * ipp)161 eoftn(struct interpass_prolog *ipp)
162 {
163 
164 #ifdef PCC_DEBUG
165           if (x2debug)
166                     printf("eoftn:\n");
167 #endif
168 
169           if (ipp->ipp_ip.ip_lbl == 0)
170                     return; /* no code needs to be generated */
171 
172           /* struct return needs special treatment */
173           if (ftype == STRTY || ftype == UNIONTY)
174                     cerror("eoftn");
175 
176           /* unwind stack frame */
177           printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]);
178           if (p2calls != 0 || kflag) {
179                     printf("\tlwz %s,8(%s)\n", rnames[R0], rnames[R1]);
180                     printf("\tmtlr %s\n", rnames[R0]);
181           }
182           printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
183           printf("\tblr\n");
184 }
185 
186 /*
187  * add/sub/...
188  *
189  * Param given:
190  */
191 void
hopcode(int f,int o)192 hopcode(int f, int o)
193 {
194           char *str;
195 
196           switch (o) {
197           case PLUS:
198                     str = "addw";
199                     break;
200           case MINUS:
201                     str = "subw";
202                     break;
203           case AND:
204                     str = "and";
205                     break;
206           case OR:
207                     str = "or";
208                     break;
209           case ER:
210                     str = "xor";
211                     break;
212           default:
213                     comperr("hopcode2: %d", o);
214                     str = 0; /* XXX gcc */
215           }
216           printf("%s%c", str, f);
217 }
218 
219 /*
220  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
221  */
222 int
tlen(NODE * p)223 tlen(NODE *p)
224 {
225           switch(p->n_type) {
226                     case CHAR:
227                     case UCHAR:
228                               return(1);
229 
230                     case SHORT:
231                     case USHORT:
232                               return(SZSHORT/SZCHAR);
233 
234                     case DOUBLE:
235                               return(SZDOUBLE/SZCHAR);
236 
237                     case INT:
238                     case UNSIGNED:
239                     case LONG:
240                     case ULONG:
241                               return(SZINT/SZCHAR);
242 
243                     case LONGLONG:
244                     case ULONGLONG:
245                               return SZLONGLONG/SZCHAR;
246 
247                     default:
248                               if (!ISPTR(p->n_type))
249                                         comperr("tlen type %d not pointer");
250                               return SZPOINT(p->n_type)/SZCHAR;
251                     }
252 }
253 
254 /*
255  * Emit code to compare two longlong numbers.
256  */
257 static void
twollcomp(NODE * p)258 twollcomp(NODE *p)
259 {
260           int o = p->n_op;
261           int s = getlab2();
262           int e = p->n_label;
263           int cb1, cb2;
264 
265           if (o >= ULE)
266                     o -= (ULE-LE);
267           switch (o) {
268           case NE:
269                     cb1 = 0;
270                     cb2 = NE;
271                     break;
272           case EQ:
273                     cb1 = NE;
274                     cb2 = 0;
275                     break;
276           case LE:
277           case LT:
278                     cb1 = GT;
279                     cb2 = LT;
280                     break;
281           case GE:
282           case GT:
283                     cb1 = LT;
284                     cb2 = GT;
285                     break;
286 
287           default:
288                     cb1 = cb2 = 0; /* XXX gcc */
289           }
290           if (p->n_op >= ULE)
291                     cb1 += 4, cb2 += 4;
292           if (p->n_op >= ULE)
293                     expand(p, 0, "\tcmplw UL,UR" COM "compare 64-bit values (upper)\n");
294           else
295                     expand(p, 0, "\tcmpw UL,UR" COM "compare 64-bit values (upper)\n");
296           if (cb1) cbgen(cb1, s);
297           if (cb2) cbgen(cb2, e);
298           if (p->n_op >= ULE)
299                     expand(p, 0, "\tcmplw AL,AR" COM "(and lower)\n");
300           else
301                     expand(p, 0, "\tcmpw AL,AR" COM "(and lower)\n");
302           cbgen(p->n_op, e);
303           deflab(s);
304 }
305 
306 static void
shiftop(NODE * p)307 shiftop(NODE *p)
308 {
309           NODE *r = p->n_right;
310           TWORD ty = p->n_type;
311 
312           if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) {
313                     expand(p, INBREG, "\tsrwi A1,AL,32-AR" COM "64-bit left-shift\n");
314                     expand(p, INBREG, "\tslwi U1,UL,AR\n");
315                     expand(p, INBREG, "\tor U1,U1,A1\n");
316                     expand(p, INBREG, "\tslwi A1,AL,AR\n");
317           } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) {
318                     expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n");
319                     if (r->n_lval == 32)
320                               expand(p, INBREG, "\tmr U1,AL\n");
321                     else
322                               expand(p, INBREG, "\tslwi U1,AL,AR-32\n");
323           } else if (p->n_op == LS && r->n_op == ICON) {
324                     expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n");
325                     expand(p, INBREG, "\tli U1,0\n");
326           } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) {
327                     expand(p, INBREG, "\tslwi U1,UL,32-AR" COM "64-bit right-shift\n");
328                     expand(p, INBREG, "\tsrwi A1,AL,AR\n");
329                     expand(p, INBREG, "\tor A1,A1,U1\n");
330                     if (ty == LONGLONG)
331                               expand(p, INBREG, "\tsrawi U1,UL,AR\n");
332                     else
333                               expand(p, INBREG, "\tsrwi U1,UL,AR\n");
334           } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) {
335                     if (ty == LONGLONG)
336                               expand(p, INBREG, "\tli U1,-1" COM "64-bit right-shift\n");
337                     else
338                               expand(p, INBREG, "\tli U1,0" COM "64-bit right-shift\n");
339                     if (r->n_lval == 32)
340                               expand(p, INBREG, "\tmr A1,UL\n");
341                     else if (ty == LONGLONG)
342                               expand(p, INBREG, "\tsrawi A1,UL,AR-32\n");
343                     else
344                               expand(p, INBREG, "\tsrwi A1,UL,AR-32\n");
345           } else if (p->n_op == RS && r->n_op == ICON) {
346                     expand(p, INBREG, "\tli A1,0" COM "64-bit right-shift\n");
347                     expand(p, INBREG, "\tli U1,0\n");
348           }
349 }
350 
351 /*
352  * Structure assignment.
353  */
354 static void
stasg(NODE * p)355 stasg(NODE *p)
356 {
357           NODE *l = p->n_left;
358           int val = l->n_lval;
359 
360         /* R3 = dest, R4 = src, R5 = len */
361         printf("\tli %s,%d\n", rnames[R5], attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0));
362         if (l->n_op == OREG) {
363                 printf("\taddi %s,%s,%d\n", rnames[R3], rnames[regno(l)], val);
364         } else if (l->n_op == NAME) {
365 #if defined(ELFABI)
366                 printf("\tli %s,", rnames[R3]);
367                 adrput(stdout, l);
368                     printf("@ha\n");
369                 printf("\taddi %s,%s,", rnames[R3], rnames[R3]);
370                 adrput(stdout, l);
371                     printf("@l\n");
372 #elif defined(MACHOABI)
373                 printf("\tli %s,ha16(", rnames[R3]);
374                 adrput(stdout, l);
375                     printf(")\n");
376                 printf("\taddi %s,%s,lo16(", rnames[R3], rnames[R3]);
377                 adrput(stdout, l);
378                     printf(")\n");
379 #endif
380         }
381           if (kflag) {
382 #if defined(ELFABI)
383                   printf("\tbl %s@got(30)\n", EXPREFIX "memcpy");
384 #elif defined(MACHOABI)
385                   printf("\tbl L%s$stub\n", EXPREFIX "memcpy");
386                     addstub(&stublist, EXPREFIX "memcpy");
387 #endif
388           } else {
389                   printf("\tbl %s\n", EXPREFIX "memcpy");
390           }
391 }
392 
393 static void
fpemul(NODE * p)394 fpemul(NODE *p)
395 {
396           NODE *l = p->n_left;
397           char *ch = NULL;
398 
399           if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3";
400           else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3";
401           else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3";
402 
403           else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3";
404           else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3";
405           else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3";
406 
407           else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3";
408           else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3";
409           else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3";
410 
411           else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3";
412           else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3";
413           else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3";
414 
415           else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2";
416           else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2";
417           else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2";
418 
419           else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2";
420           else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2";
421           else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2";
422 
423           else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2";
424           else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2";
425           else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2";
426 
427           else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2";
428           else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2";
429           else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2";
430 
431           else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2";
432           else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2";
433           else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2";
434 
435           else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2";
436           else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2";
437           else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2";
438 
439           else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2";
440           else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2";
441           else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2";
442 
443           else if (p->n_op == SCONV && p->n_type == FLOAT) {
444                     if (l->n_type == DOUBLE) ch = "truncdfsf2";
445                     else if (l->n_type == LDOUBLE) ch = "truncdfsf2";
446                     else if (l->n_type == ULONGLONG) ch = "floatunsdisf";
447                     else if (l->n_type == LONGLONG) ch = "floatdisf";
448                     else if (l->n_type == LONG) ch = "floatsisf";
449                     else if (l->n_type == ULONG) ch = "floatunsisf";
450                     else if (l->n_type == INT) ch = "floatsisf";
451                     else if (l->n_type == UNSIGNED) ch = "floatunsisf";
452           } else if (p->n_op == SCONV && p->n_type == DOUBLE) {
453                     if (l->n_type == FLOAT) ch = "extendsfdf2";
454                     else if (l->n_type == LDOUBLE) ch = "truncdfdf2";
455                     else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
456                     else if (l->n_type == LONGLONG) ch = "floatdidf";
457                     else if (l->n_type == LONG) ch = "floatsidf";
458                     else if (l->n_type == ULONG) ch = "floatunssidf";
459                     else if (l->n_type == INT) ch = "floatsidf";
460                     else if (l->n_type == UNSIGNED) ch = "floatunssidf";
461           } else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
462                     if (l->n_type == FLOAT) ch = "extendsfdf2";
463                     else if (l->n_type == DOUBLE) ch = "extenddfdf2";
464                     else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
465                     else if (l->n_type == LONGLONG) ch = "floatdidf";
466                     else if (l->n_type == LONG) ch = "floatsidf";
467                     else if (l->n_type == ULONG) ch = "floatunssidf";
468                     else if (l->n_type == INT) ch = "floatsidf";
469                     else if (l->n_type == UNSIGNED) ch = "floatunsidf";
470           } else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
471                     if (l->n_type == FLOAT) ch = "fixunssfdi";
472                     else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
473                     else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
474           } else if (p->n_op == SCONV && p->n_type == LONGLONG) {
475                     if (l->n_type == FLOAT) ch = "fixsfdi";
476                     else if (l->n_type == DOUBLE) ch = "fixdfdi";
477                     else if (l->n_type == LDOUBLE) ch = "fixdfdi";
478           } else if (p->n_op == SCONV && p->n_type == LONG) {
479                     if (l->n_type == FLOAT) ch = "fixsfdi";
480                     else if (l->n_type == DOUBLE) ch = "fixdfdi";
481                     else if (l->n_type == LDOUBLE) ch = "fixdfdi";
482           } else if (p->n_op == SCONV && p->n_type == ULONG) {
483                     if (l->n_type == FLOAT) ch = "fixunssfdi";
484                     else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
485                     else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
486           } else if (p->n_op == SCONV && p->n_type == INT) {
487                     if (l->n_type == FLOAT) ch = "fixsfsi";
488                     else if (l->n_type == DOUBLE) ch = "fixdfsi";
489                     else if (l->n_type == LDOUBLE) ch = "fixdfsi";
490           } else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
491                     if (l->n_type == FLOAT) ch = "fixunssfsi";
492                     else if (l->n_type == DOUBLE) ch = "fixunsdfsi";
493                     else if (l->n_type == LDOUBLE) ch = "fixunsdfsi";
494           }
495 
496           if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op);
497 
498           if (kflag) {
499 #if defined(ELFABI)
500                     printf("\tbl __%s%s@got(30)" COM "soft-float\n", EXPREFIX, ch);
501 #elif defined(MACHOABI)
502                     char buf[32];
503                     printf("\tbl L__%s%s$stub" COM "soft-float\n", EXPREFIX, ch);
504                     snprintf(buf, 32, "__%s%s", EXPREFIX, ch);
505                     addstub(&stublist, buf);
506 #endif
507           } else {
508                     printf("\tbl __%s%s" COM "soft-float\n", EXPREFIX, ch);
509           }
510 
511           if (p->n_op >= EQ && p->n_op <= GT)
512                     printf("\tcmpwi %s,0\n", rnames[R3]);
513 }
514 
515 /*
516  * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
517  */
518 
519 static void
emul(NODE * p)520 emul(NODE *p)
521 {
522           char *ch = NULL;
523 
524         if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3";
525         else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG ||
526             DEUNSIGN(p->n_type) == INT))
527                 ch = "ashlsi3";
528 
529         else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3";
530         else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT))
531                 ch = "lshrsi3";
532 
533         else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3";
534         else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT))
535                 ch = "ashrsi3";
536 
537         else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3";
538         else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT))
539                 ch = "divsi3";
540 
541         else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3";
542         else if (p->n_op == DIV && (p->n_type == ULONG ||
543             p->n_type == UNSIGNED))
544                 ch = "udivsi3";
545 
546         else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3";
547         else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT))
548                 ch = "modsi3";
549 
550         else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3";
551         else if (p->n_op == MOD && (p->n_type == ULONG ||
552             p->n_type == UNSIGNED))
553                 ch = "umodsi3";
554 
555         else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3";
556         else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT))
557                 ch = "mulsi3";
558 
559         else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2";
560         else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2";
561 
562           else ch = 0, comperr("ZE");
563           if (kflag) {
564 #if defined(ELFABI)
565                     printf("\tbl __%s%s@got(30)" COM "emulated op\n", EXPREFIX, ch);
566 #elif defined(MACHOABI)
567                     char buf[32];
568                     printf("\tbl L__%s%s$stub" COM "emulated op\n", EXPREFIX, ch);
569                     snprintf(buf, 32, "__%s%s", EXPREFIX, ch);
570                     addstub(&stublist, buf);
571 #endif
572           } else {
573                     printf("\tbl __%s%s" COM "emulated operation\n", EXPREFIX, ch);
574           }
575 }
576 
577 /*
578  *  Floating-point conversions (int -> float/double & float/double -> int)
579  */
580 
581 static void
ftoi(NODE * p)582 ftoi(NODE *p)
583 {
584           NODE *l = p->n_left;
585 
586           printf(COM "start conversion float/(l)double to int\n");
587 
588           if (l->n_op != OREG) {
589                     expand(p, 0, "\tstw AL,-4");
590                     printf("(%s)\n", rnames[SPREG]);
591                     if (l->n_type == FLOAT)
592                               expand(p, 0, "\tlfs A2,");
593                     else
594                               expand(p, 0, "\tlfd A2,\n");
595                     printf("-4(%s)\n", rnames[SPREG]);
596           } else {
597                     if (l->n_type == FLOAT)
598                               expand(p, 0, "\tlfs A2,AL\n");
599                     else
600                               expand(p, 0, "\tlfd A2,AL\n");
601           }
602 
603           expand(p, 0, "\tfctiwz A2,A2\n");
604           expand(p, 0, "\tstfd A2,");
605           printf("-8(%s)\n", rnames[SPREG]);
606           expand(p, 0, "\tlwz A1,");
607           printf("-4(%s)\n", rnames[SPREG]);
608 
609           printf(COM "end conversion\n");
610 }
611 
612 static void
ftou(NODE * p)613 ftou(NODE *p)
614 {
615           static int lab = 0;
616           NODE *l = p->n_left;
617           int lab1 = getlab2();
618           int lab2 = getlab2();
619 
620           printf(COM "start conversion of float/(l)double to unsigned\n");
621 
622           if (lab == 0) {
623                     lab = getlab2();
624                     expand(p, 0, "\t.data\n");
625                     printf(LABFMT ":\t.long 0x41e00000\n\t.long 0\n", lab);
626                     expand(p, 0, "\t.text\n");
627           }
628 
629           if (l->n_op != OREG) {
630                     expand(p, 0, "\tstw AL,");
631                     printf("-4(%s)\n", rnames[SPREG]);
632                     if (l->n_type == FLOAT)
633                               expand(p, 0, "\tlfs A3,");
634                     else
635                               expand(p, 0, "\tlfd A3,");
636                     printf("-4(%s)\n", rnames[SPREG]);
637 
638           } else {
639                     if (l->n_type == FLOAT)
640                               expand(p, 0, "\tlfs A3,AL\n");
641                     else
642                               expand(p, 0, "\tlfd A3,AL\n");
643           }
644 
645 #if 0
646           if (kflag) {
647                     expand(p, 0, "\taddis A1,");
648                     printf("%s,ha16(", rnames[R31]);
649                     printf(LABFMT, lab);
650                     printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
651                     expand(p, 0, "\tlfd A2,lo16(");
652                     printf(LABFMT, lab);
653                     printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
654                     expand(p, 0, "(A1)\n");
655           } else {
656                     expand(p, 0, "\tlfd A2,");
657                     printf(LABFMT "\n", lab);
658           }
659 #endif
660 
661 #if defined(ELFABI)
662 
663           expand(p, 0, "\taddis A1,");
664           printf("%s," LABFMT "@ha\n", rnames[R31], lab);
665           expand(p, 0, "\tlfd A2,");
666           printf(LABFMT "@l", lab);
667           expand(p, 0, "(A1)\n");
668 
669 #elif defined(MACHOABI)
670 
671           expand(p, 0, "\taddis A1,");
672           printf("%s,ha16(", rnames[R31]);
673           printf(LABFMT, lab);
674           if (kflag)
675                     printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
676           printf(")\n");
677           expand(p, 0, "\tlfd A2,lo16(");
678           printf(LABFMT, lab);
679           if (kflag)
680                     printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
681           expand(p, 0, ")(A1)\n");
682 
683 #endif
684 
685           expand(p, 0, "\tfcmpu cr7,A3,A2\n");
686           printf("\tcror 30,29,30\n");
687           printf("\tbeq cr7,"LABFMT "\n", lab1);
688 
689           expand(p, 0, "\tfctiwz A2,A3\n");
690           expand(p, 0, "\tstfd A2,");
691           printf("-8(%s)\n", rnames[SPREG]);
692           expand(p, 0, "\tlwz A1,");
693           printf("-4(%s)\n", rnames[SPREG]);
694           printf("\tba " LABFMT "\n", lab2);
695 
696           deflab(lab1);
697 
698         expand(p, 0, "\tfsub A2,A3,A2\n");
699         expand(p, 0, "\tfctiwz A2,A2\n");
700           expand(p, 0, "\tstfd A2,");
701           printf("-8(%s)\n", rnames[SPREG]);
702           expand(p, 0, "\tlwz A1,");
703           printf("-4(%s)\n", rnames[SPREG]);
704         expand(p, 0, "\txoris A1,A1,0x8000\n");
705 
706           deflab(lab2);
707 
708           printf(COM "end conversion\n");
709 }
710 
711 static void
itof(NODE * p)712 itof(NODE *p)
713 {
714           static int labu = 0;
715           static int labi = 0;
716           int lab;
717           NODE *l = p->n_left;
718 
719           printf(COM "start conversion (u)int to float/(l)double\n");
720 
721           if (labi == 0 && l->n_type == INT) {
722                     labi = getlab2();
723                     expand(p, 0, "\t.data\n");
724                     printf(LABFMT ":\t.long 0x43300000\n\t.long 0x80000000\n", labi);
725                     expand(p, 0, "\t.text\n");
726           } else if (labu == 0 && l->n_type == UNSIGNED) {
727                     labu = getlab2();
728                     expand(p, 0, "\t.data\n");
729                     printf(LABFMT ":\t.long 0x43300000\n\t.long 0x00000000\n", labu);
730                     expand(p, 0, "\t.text\n");
731           }
732 
733           if (l->n_type == INT) {
734                     expand(p, 0, "\txoris A1,AL,0x8000\n");
735                     lab = labi;
736           } else {
737                     lab = labu;
738           }
739           expand(p, 0, "\tstw A1,");
740           printf("-4(%s)\n", rnames[SPREG]);
741         expand(p, 0, "\tlis A1,0x4330\n");
742         expand(p, 0, "\tstw A1,");
743           printf("-8(%s)\n", rnames[SPREG]);
744         expand(p, 0, "\tlfd A3,");
745           printf("-8(%s)\n", rnames[SPREG]);
746 
747 #if 0
748           if (kflag) {
749                     expand(p, 0, "\taddis A1,");
750                     printf("%s,ha16(", rnames[R31]);
751                     printf(LABFMT, lab);
752                     printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
753                     expand(p, 0, "\tlfd A2,lo16(");
754                     printf(LABFMT, lab);
755                     printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
756                     expand(p, 0, "(A1)\n");
757           } else {
758                     expand(p, 0, "\tlfd A2,");
759                     printf(LABFMT "\n", lab);
760           }
761 #endif
762 
763 #if defined(ELFABI)
764 
765           expand(p, 0, "\taddis A1,");
766           printf("%s," LABFMT "@ha\n", rnames[R31], lab);
767           expand(p, 0, "\tlfd A2,");
768           printf(LABFMT "@l", lab);
769           expand(p, 0, "(A1)\n");
770 
771 #elif defined(MACHOABI)
772 
773           expand(p, 0, "\taddis A1,");
774           printf("%s,ha16(", rnames[R31]);
775           printf(LABFMT, lab);
776           if (kflag)
777                     printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
778           printf(")\n");
779           expand(p, 0, "\tlfd A2,lo16(");
780           printf(LABFMT, lab);
781           if (kflag)
782                     printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname));
783           expand(p, 0, ")(A1)\n");
784 
785 #endif
786 
787           expand(p, 0, "\tfsub A3,A3,A2\n");
788           if (p->n_type == FLOAT)
789                     expand(p, 0, "\tfrsp A3,A3\n");
790 
791           printf(COM "end conversion\n");
792 }
793 
794 
795 static void
fpconv(NODE * p)796 fpconv(NODE *p)
797 {
798           NODE *l = p->n_left;
799 
800 #ifdef PCC_DEBUG
801           if (p->n_op != SCONV)
802                     cerror("fpconv 1");
803 #endif
804 
805           if (DEUNSIGN(l->n_type) == INT)
806                     itof(p);
807           else if (p->n_type == INT)
808                     ftoi(p);
809           else if (p->n_type == UNSIGNED)
810                     ftou(p);
811           else
812                     cerror("unhandled floating-point conversion");
813 
814 }
815 
816 void
zzzcode(NODE * p,int c)817 zzzcode(NODE *p, int c)
818 {
819           switch (c) {
820 
821           case 'C': /* floating-point conversions */
822                     fpconv(p);
823                     break;
824 
825           case 'D': /* long long comparision */
826                     twollcomp(p);
827                     break;
828 
829           case 'E': /* print out emulated ops */
830                     emul(p);
831                     break;
832 
833           case 'F': /* print out emulate floating-point ops */
834                     fpemul(p);
835                     break;
836 
837           case 'O': /* 64-bit left and right shift operators */
838                     shiftop(p);
839                     break;
840 
841           case 'Q': /* emit struct assign */
842                     stasg(p);
843                     break;
844 
845           default:
846                     comperr("zzzcode %c", c);
847           }
848 }
849 
850 /*ARGSUSED*/
851 int
rewfld(NODE * p)852 rewfld(NODE *p)
853 {
854           return(1);
855 }
856 
857 int canaddr(NODE *);
858 int
canaddr(NODE * p)859 canaddr(NODE *p)
860 {
861           int o = p->n_op;
862 
863           if (o == NAME || o == REG || o == ICON || o == OREG ||
864               (o == UMUL && shumul(p->n_left, SOREG)))
865                     return(1);
866           return 0;
867 }
868 
869 int
fldexpand(NODE * p,int cookie,char ** cp)870 fldexpand(NODE *p, int cookie, char **cp)
871 {
872           CONSZ val;
873           int shft;
874 
875           if (p->n_op == ASSIGN)
876                     p = p->n_left;
877 
878           if (features(FEATURE_BIGENDIAN))
879                     shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval);
880           else
881                     shft = UPKFOFF(p->n_rval);
882 
883           switch (**cp) {
884           case 'S':
885                     printf("%d", UPKFSZ(p->n_rval));
886                     break;
887           case 'H':
888                     printf("%d", shft);
889                     break;
890           case 'M':
891           case 'N':
892                     val = (CONSZ)1 << UPKFSZ(p->n_rval);
893                     --val;
894                     val <<= shft;
895                     printf(CONFMT, (**cp == 'M' ? val : ~val)  & 0xffffffff);
896                     break;
897           default:
898                     comperr("fldexpand");
899           }
900           return 1;
901 }
902 
903 /*
904  * Does the bitfield shape match?
905  */
906 int
flshape(NODE * p)907 flshape(NODE *p)
908 {
909           int o = p->n_op;
910 
911           if (o == OREG || o == REG || o == NAME)
912                     return SRDIR; /* Direct match */
913           if (o == UMUL && shumul(p->n_left, SOREG))
914                     return SROREG; /* Convert into oreg */
915           return SRREG; /* put it into a register */
916 }
917 
918 /* INTEMP shapes must not contain any temporary registers */
919 /* XXX should this go away now? */
920 int
shtemp(NODE * p)921 shtemp(NODE *p)
922 {
923           printf("; shtemp\n");
924           return 0;
925 #if 0
926           int r;
927 
928           if (p->n_op == STARG )
929                     p = p->n_left;
930 
931           switch (p->n_op) {
932           case REG:
933                     return (!istreg(regno(p)));
934 
935           case OREG:
936                     r = regno(p);
937                     if (R2TEST(r)) {
938                               if (istreg(R2UPK1(r)))
939                                         return(0);
940                               r = R2UPK2(r);
941                     }
942                     return (!istreg(r));
943 
944           case UMUL:
945                     p = p->n_left;
946                     return (p->n_op != UMUL && shtemp(p));
947           }
948 
949           if (optype(p->n_op) != LTYPE)
950                     return(0);
951           return(1);
952 #endif
953 }
954 
955 void
adrcon(CONSZ val)956 adrcon(CONSZ val)
957 {
958           printf( CONFMT, val);
959 }
960 
961 void
conput(FILE * fp,NODE * p)962 conput(FILE *fp, NODE *p)
963 {
964           int val = p->n_lval;
965 
966           switch (p->n_op) {
967           case ICON:
968                     if (p->n_name[0] != '\0') {
969                               fprintf(fp, "%s", p->n_name);
970                               if (val)
971                                         fprintf(fp, "+%d", val);
972                     } else {
973                               if (GCLASS(p->n_type) == CLASSB)
974                                         fprintf(fp, CONFMT, p->n_lval >> 32);
975                               else
976                                         fprintf(fp, "%d", val);
977                     }
978                     return;
979 
980           default:
981                     comperr("illegal conput, p %p", p);
982           }
983 }
984 
985 /*ARGSUSED*/
986 void
insput(NODE * p)987 insput(NODE *p)
988 {
989           comperr("insput");
990 }
991 
992 /*
993  * Print lower or upper name of 64-bit register.
994  */
995 static void
reg64name(int reg,int hi)996 reg64name(int reg, int hi)
997 {
998           int idx;
999           int off = 0;
1000 
1001           idx = (reg > R14R15 ? (2*(reg - R14R15) + R14) : (reg - R3R4 + R3));
1002 
1003           if ((hi == HIREG && !features(FEATURE_BIGENDIAN)) ||
1004               (hi == LOWREG && features(FEATURE_BIGENDIAN)))
1005                     off = 1;
1006 
1007           printf("%s" , rnames[idx + off]);
1008 }
1009 
1010 /*
1011  * Write out the upper address, like the upper register of a 2-register
1012  * reference, or the next memory location.
1013  */
1014 void
upput(NODE * p,int size)1015 upput(NODE *p, int size)
1016 {
1017           size /= SZCHAR;
1018           switch (p->n_op) {
1019           case REG:
1020                     reg64name(regno(p), HIREG);
1021                     break;
1022 
1023           case NAME:
1024           case OREG:
1025                     if (features(FEATURE_BIGENDIAN))
1026                               printf("%d", (int)p->n_lval);
1027                     else
1028                               printf("%d", (int)(p->n_lval + 4));
1029                     printf("(%s)", rnames[regno(p)]);
1030                     break;
1031 
1032           case ICON:
1033                     printf(CONFMT, p->n_lval >> 32);
1034                     break;
1035 
1036           default:
1037                     comperr("upput bad op %d size %d", p->n_op, size);
1038           }
1039 }
1040 
1041 void
adrput(FILE * io,NODE * p)1042 adrput(FILE *io, NODE *p)
1043 {
1044           /* output an address, with offsets, from p */
1045 
1046           if (p->n_op == FLD)
1047                     p = p->n_left;
1048 
1049           switch (p->n_op) {
1050 
1051           case NAME:
1052                     if (p->n_name[0] != '\0') {
1053                               fputs(p->n_name, io);
1054                               if (p->n_lval != 0)
1055                                         fprintf(io, "+" CONFMT, p->n_lval);
1056                     } else
1057                               fprintf(io, CONFMT, p->n_lval);
1058                     return;
1059 
1060           case OREG:
1061                     if (DEUNSIGN(p->n_type) == LONGLONG &&
1062                         features(FEATURE_BIGENDIAN))
1063                               fprintf(io, "%d", (int)(p->n_lval + 4));
1064                     else
1065                               fprintf(io, "%d", (int)p->n_lval);
1066                     fprintf(io, "(%s)", rnames[regno(p)]);
1067                     return;
1068 
1069           case ICON:
1070                     /* addressable value of the constant */
1071                     conput(io, p);
1072                     return;
1073 
1074           case REG:
1075                     if (GCLASS(regno(p)) == CLASSB)
1076                               reg64name(regno(p), LOWREG);
1077                     else
1078                               fprintf(io, "%s", rnames[regno(p)]);
1079 #if 0
1080                     switch (p->n_type) {
1081                     case DOUBLE:
1082                     case LDOUBLE:
1083                               if (features(FEATURE_HARDFLOAT)) {
1084                                         fprintf(io, "%s", rnames[regno(p)]);
1085                                         break;
1086                               }
1087                               /* FALL-THROUGH */
1088                     case LONGLONG:
1089                     case ULONGLONG:
1090                               reg64name(regno(p), LOWREG);
1091                               break;
1092                     default:
1093                               fprintf(io, "%s", rnames[regno(p)]);
1094                     }
1095 #endif
1096                     return;
1097 
1098           default:
1099                     comperr("illegal address, op %d, node %p", p->n_op, p);
1100                     return;
1101 
1102           }
1103 }
1104 
1105 /*
1106  * these mnemonics match the order of the preprocessor decls
1107  * EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT
1108  */
1109 
1110 static char *
1111 ccbranches[] = {
1112           "beq",              /* branch if equal */
1113           "bne",              /* branch if not-equal */
1114           "ble",              /* branch if less-than-or-equal */
1115           "blt",              /* branch if less-than */
1116           "bge",              /* branch if greater-than-or-equal */
1117           "bgt",              /* branch if greater-than */
1118           /* what should these be ? */
1119           "ble",              /* branch if less-than-or-equal */
1120           "blt",              /* branch if less-than */
1121           "bge",              /* branch if greater-than-or-equal */
1122           "bgt",              /* branch if greater-than */
1123 
1124 };
1125 
1126 
1127 /*   printf conditional and unconditional branches */
1128 void
cbgen(int o,int lab)1129 cbgen(int o, int lab)
1130 {
1131           if (o < EQ || o > UGT)
1132                     comperr("bad conditional branch: %s", opst[o]);
1133           printf("\t%s " LABFMT "\n", ccbranches[o-EQ], lab);
1134 }
1135 
1136 static int
argsize(NODE * p)1137 argsize(NODE *p)
1138 {
1139           TWORD t = p->n_type;
1140 
1141           if (t < LONGLONG || t == FLOAT || t > BTMASK)
1142                     return 4;
1143           if (t == LONGLONG || t == ULONGLONG)
1144                     return 8;
1145           if (t == DOUBLE || t == LDOUBLE)
1146                     return 8;
1147           if (t == STRTY || t == UNIONTY)
1148                     return attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
1149           comperr("argsize");
1150           return 0;
1151 }
1152 
1153 static int
calc_args_size(NODE * p)1154 calc_args_size(NODE *p)
1155 {
1156           int n = 0;
1157 
1158         if (p->n_op == CM) {
1159                 n += calc_args_size(p->n_left);
1160                 n += calc_args_size(p->n_right);
1161                 return n;
1162         }
1163 
1164         n += argsize(p);
1165 
1166         return n;
1167 }
1168 
1169 
1170 static void
fixcalls(NODE * p,void * arg)1171 fixcalls(NODE *p, void *arg)
1172 {
1173           int n = 0;
1174 
1175           switch (p->n_op) {
1176           case STCALL:
1177           case CALL:
1178                     n = calc_args_size(p->n_right);
1179                     if (n > p2maxstacksize)
1180                               p2maxstacksize = n;
1181                     /* FALLTHROUGH */
1182           case USTCALL:
1183           case UCALL:
1184                     ++p2calls;
1185                     break;
1186           case TEMP:
1187                     p2temps += argsize(p);
1188                     break;
1189           }
1190 }
1191 
1192 /*
1193  * Must store floats in memory if there are two function calls involved.
1194  */
1195 static int
storefloat(struct interpass * ip,NODE * p)1196 storefloat(struct interpass *ip, NODE *p)
1197 {
1198           int l, r;
1199 
1200           switch (optype(p->n_op)) {
1201           case BITYPE:
1202                     l = storefloat(ip, p->n_left);
1203                     r = storefloat(ip, p->n_right);
1204                     if (p->n_op == CM)
1205                               return 0; /* arguments, don't care */
1206                     if (callop(p->n_op))
1207                               return 1; /* found one */
1208 #define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
1209           (p)->n_type == LDOUBLE)
1210                     if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
1211                               /* must store one. store left */
1212                               struct interpass *nip;
1213                               TWORD t = p->n_left->n_type;
1214                               NODE *ll;
1215                               int off;
1216 
1217                     off = (freetemp(szty(t)));
1218                     ll = mklnode(OREG, off, SPREG, t);
1219                               nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
1220                               p->n_left = mklnode(OREG, off, SPREG, t);
1221                     DLIST_INSERT_BEFORE(ip, nip, qelem);
1222                     }
1223                     return l|r;
1224 
1225           case UTYPE:
1226                     l = storefloat(ip, p->n_left);
1227                     if (callop(p->n_op))
1228                               l = 1;
1229                     return l;
1230           default:
1231                     return 0;
1232           }
1233 }
1234 
1235 void
myreader(struct interpass * ipole)1236 myreader(struct interpass *ipole)
1237 {
1238           struct interpass *ip;
1239 
1240           p2calls = 0;
1241           p2temps = 0;
1242           p2maxstacksize = 0;
1243 
1244           DLIST_FOREACH(ip, ipole, qelem) {
1245                     if (ip->type != IP_NODE)
1246                               continue;
1247                     walkf(ip->ip_node, fixcalls, 0);
1248                     storefloat(ip, ip->ip_node);
1249           }
1250 
1251           if (p2maxstacksize < NARGREGS*SZINT/SZCHAR)
1252                     p2maxstacksize = NARGREGS*SZINT/SZCHAR;
1253 
1254           p2framesize = ARGINIT/SZCHAR;           /* stack ptr / return addr */
1255           p2framesize += 8;                       /* for R31 and R30 */
1256           p2framesize += p2maxautooff;            /* autos */
1257           p2framesize += p2temps;                           /* TEMPs that aren't autos */
1258           if (p2calls != 0)
1259                     p2framesize += p2maxstacksize;          /* arguments to functions */
1260           p2framesize += (ALSTACK/SZCHAR - 1);    /* round to 16-byte boundary */
1261           p2framesize &= ~(ALSTACK/SZCHAR - 1);
1262 
1263 #if 0
1264           printf("!!! MYREADER\n");
1265           printf("!!! p2maxautooff = %d\n", p2maxautooff);
1266           printf("!!! p2autooff = %d\n", p2autooff);
1267           printf("!!! p2temps = %d\n", p2temps);
1268           printf("!!! p2calls = %d\n", p2calls);
1269           printf("!!! p2maxstacksize = %d\n", p2maxstacksize);
1270 #endif
1271 
1272           if (x2debug)
1273                     printip(ipole);
1274 }
1275 
1276 /*
1277  * Remove some PCONVs after OREGs are created.
1278  */
1279 static void
pconv2(NODE * p,void * arg)1280 pconv2(NODE *p, void *arg)
1281 {
1282           NODE *q;
1283 
1284           if (p->n_op == PLUS) {
1285                     if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
1286                               if (p->n_right->n_op != ICON)
1287                                         return;
1288                               if (p->n_left->n_op != PCONV)
1289                                         return;
1290                               if (p->n_left->n_left->n_op != OREG)
1291                                         return;
1292                               q = p->n_left->n_left;
1293                               nfree(p->n_left);
1294                               p->n_left = q;
1295                               /*
1296                                * This will be converted to another OREG later.
1297                                */
1298                     }
1299           }
1300 }
1301 
1302 void
mycanon(NODE * p)1303 mycanon(NODE *p)
1304 {
1305           walkf(p, pconv2, 0);
1306 }
1307 
1308 void
myoptim(struct interpass * ip)1309 myoptim(struct interpass *ip)
1310 {
1311 #ifdef PCC_DEBUG
1312           if (x2debug) {
1313                     printf("myoptim\n");
1314           }
1315 #endif
1316 }
1317 
1318 /*
1319  * Move data between registers.  While basic registers aren't a problem,
1320  * we have to handle the special case of overlapping composite registers.
1321  * It might just be easier to modify the register allocator so that
1322  * moves between overlapping registers isn't possible.
1323  */
1324 void
rmove(int s,int d,TWORD t)1325 rmove(int s, int d, TWORD t)
1326 {
1327           switch (t) {
1328           case LDOUBLE:
1329           case DOUBLE:
1330                     if (features(FEATURE_HARDFLOAT)) {
1331                               printf("\tfmr %s,%s" COM "rmove\n",
1332                                   rnames[d], rnames[s]);
1333                               break;
1334                     }
1335                     /* FALL-THROUGH */
1336           case LONGLONG:
1337           case ULONGLONG:
1338                     if (s == d+1) {
1339                               /* dh = sl, copy low word first */
1340                               printf("\tmr ");
1341                               reg64name(d, LOWREG);
1342                               printf(",");
1343                               reg64name(s, LOWREG);
1344                               printf("\n");
1345                               printf("\tmr ");
1346                               reg64name(d, HIREG);
1347                               printf(",");
1348                               reg64name(s, HIREG);
1349                               printf("\n");
1350                     } else {
1351                               /* copy high word first */
1352                               printf("\tmr ");
1353                               reg64name(d, HIREG);
1354                               printf(",");
1355                               reg64name(s, HIREG);
1356                               printf("\n");
1357                               printf("\tmr ");
1358                               reg64name(d, LOWREG);
1359                               printf(",");
1360                               reg64name(s, LOWREG);
1361                               printf("\n");
1362                     }
1363                     break;
1364           case FLOAT:
1365                     if (features(FEATURE_HARDFLOAT)) {
1366                               printf("\tfmr %s,%s" COM "rmove\n",
1367                                   rnames[d], rnames[s]);
1368                               break;
1369                     }
1370                     /* FALL-THROUGH */
1371           default:
1372                     printf("\tmr %s,%s" COM "rmove\n", rnames[d], rnames[s]);
1373           }
1374 }
1375 
1376 /*
1377  * For class c, find worst-case displacement of the number of
1378  * registers in the array r[] indexed by class.
1379  *
1380  * On PowerPC, we have:
1381  *
1382  * 32 32-bit registers (2 reserved)
1383  * 16 64-bit pseudo registers
1384  * 32 floating-point registers
1385  */
1386 int
COLORMAP(int c,int * r)1387 COLORMAP(int c, int *r)
1388 {
1389           int num = 0;
1390 
1391         switch (c) {
1392         case CLASSA:
1393                 num += r[CLASSA];
1394                 num += 2*r[CLASSB];
1395                 return num < 30;
1396         case CLASSB:
1397                 num += 2*r[CLASSB];
1398                 num += r[CLASSA];
1399                 return num < 16;
1400           case CLASSC:
1401                     return num < 32;
1402         case CLASSD:
1403                 return r[CLASSD] < DREGCNT;
1404         }
1405         return 0; /* XXX gcc */
1406 }
1407 
1408 /*
1409  * Return a class suitable for a specific type.
1410  */
1411 int
gclass(TWORD t)1412 gclass(TWORD t)
1413 {
1414           if (t == LONGLONG || t == ULONGLONG)
1415                     return CLASSB;
1416           if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
1417                     if (features(FEATURE_HARDFLOAT))
1418                               return CLASSC;
1419                     if (t == FLOAT)
1420                               return CLASSA;
1421                     else
1422                               return CLASSB;
1423           }
1424           return CLASSA;
1425 }
1426 
1427 int
retreg(int t)1428 retreg(int t)
1429 {
1430           int c = gclass(t);
1431           if (c == CLASSB)
1432                     return R3R4;
1433           else if (c == CLASSC)
1434                     return F1;
1435           return R3;
1436 }
1437 
1438 /*
1439  * Calculate argument sizes.
1440  */
1441 void
lastcall(NODE * p)1442 lastcall(NODE *p)
1443 {
1444           NODE *op = p;
1445           int size = 0;
1446 
1447 #ifdef PCC_DEBUG
1448           if (x2debug)
1449                     printf("lastcall:\n");
1450 #endif
1451 
1452           p->n_qual = 0;
1453           if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1454                     return;
1455 
1456           for (p = p->n_right; p->n_op == CM; p = p->n_left)
1457                     size += argsize(p->n_right);
1458           size += argsize(p);
1459           op->n_qual = size; /* XXX */
1460 }
1461 
1462 /*
1463  * Special shapes.
1464  */
1465 int
special(NODE * p,int shape)1466 special(NODE *p, int shape)
1467 {
1468           int o = p->n_op;
1469 
1470           switch (shape) {
1471           case SFUNCALL:
1472                     if (o == STCALL || o == USTCALL)
1473                               return SRREG;
1474                     break;
1475           case SPCON:
1476                     if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0x7fff) == 0)
1477                               return SRDIR;
1478                     break;
1479           }
1480           return SRNOPE;
1481 }
1482 
1483 static int fset = FEATURE_BIGENDIAN | FEATURE_HARDFLOAT;
1484 
1485 /*
1486  * Target-dependent command-line options.
1487  */
1488 void
mflags(char * str)1489 mflags(char *str)
1490 {
1491           if (strcasecmp(str, "big-endian") == 0) {
1492                     fset |= FEATURE_BIGENDIAN;
1493           } else if (strcasecmp(str, "little-endian") == 0) {
1494                     fset &= ~FEATURE_BIGENDIAN;
1495           } else if (strcasecmp(str, "soft-float") == 0) {
1496                     fset &= ~FEATURE_HARDFLOAT;
1497           } else if (strcasecmp(str, "hard-float") == 0) {
1498                     fset |= FEATURE_HARDFLOAT;
1499           } else {
1500                     fprintf(stderr, "unknown m option '%s'\n", str);
1501                     exit(1);
1502           }
1503 }
1504 
1505 int
features(int mask)1506 features(int mask)
1507 {
1508           return ((fset & mask) == mask);
1509 }
1510 /*
1511  * Do something target-dependent for xasm arguments.
1512  * Supposed to find target-specific constraints and rewrite them.
1513  */
1514 int
myxasm(struct interpass * ip,NODE * p)1515 myxasm(struct interpass *ip, NODE *p)
1516 {
1517           return 0;
1518 }
1519