xref: /netbsd-src/external/bsd/pcc/dist/pcc/arch/powerpc/local2.c (revision 411dcbec990c8aa9c57d3bd2f4bcacadec0b1ab5)
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