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