xref: /netbsd-src/external/bsd/pcc/dist/pcc/arch/mips/local2.c (revision 411dcbec990c8aa9c57d3bd2f4bcacadec0b1ab5)
1 /*	Id: local2.c,v 1.31 2016/01/06 16:11:24 ragge Exp 	 */
2 /*	$NetBSD: local2.c,v 1.1.1.5 2016/02/09 20:28:21 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 /*
31  * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
32  * Simon Olsson (simols-1@student.ltu.se) 2005.
33  */
34 
35 #include <ctype.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <assert.h>
39 
40 #include "pass1.h"
41 #include "pass2.h"
42 
43 #ifdef TARGET_BIG_ENDIAN
44 int bigendian = 1;
45 #else
46 int bigendian = 0;
47 #endif
48 
49 int nargregs = MIPS_O32_NARGREGS;
50 
51 static int argsiz(NODE *p);
52 
53 void
deflab(int label)54 deflab(int label)
55 {
56 	printf(LABFMT ":\n", label);
57 }
58 
59 static int regoff[32];
60 static TWORD ftype;
61 
62 /*
63  * calculate stack size and offsets
64  */
65 static int
offcalc(struct interpass_prolog * ipp)66 offcalc(struct interpass_prolog * ipp)
67 {
68 	int i, j, addto;
69 
70 	addto = p2maxautooff;
71 
72 	for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) {
73 		if (i & 1) {
74 			addto += SZINT / SZCHAR;
75 			regoff[j] = addto;
76 		}
77 	}
78 
79         /* round to 8-byte boundary */
80         addto += 7;
81         addto &= ~7;
82 
83 	return addto;
84 }
85 
86 /*
87  * Print out the prolog assembler.
88  */
89 void
prologue(struct interpass_prolog * ipp)90 prologue(struct interpass_prolog * ipp)
91 {
92 	int addto;
93 	int i, j;
94 
95 	ftype = ipp->ipp_type;
96 	printf("\t.align 2\n");
97 	if (ipp->ipp_vis)
98 		printf("\t.globl %s\n", ipp->ipp_name);
99 	printf("\t.ent %s\n", ipp->ipp_name);
100 	printf("%s:\n", ipp->ipp_name);
101 
102 	addto = offcalc(ipp);
103 
104 	/* emit PIC only if -fpic or -fPIC set */
105 	if (kflag > 0) {
106 		printf("\t.frame %s,%d,%s\n",
107 		    rnames[FP], ARGINIT/SZCHAR, rnames[RA]);
108 		printf("\t.set noreorder\n");
109 		printf("\t.cpload $25\t# pseudo-op to load GOT ptr into $25\n");
110 		printf("\t.set reorder\n");
111 	}
112 
113 	printf("\t.frame %s,%d,%s\n", rnames[FP], ARGINIT/SZCHAR, rnames[RA]);
114 	printf("\t.set noreorder\n");
115 	printf("\t.cpload $25\t# pseudo-op to load GOT ptr into $25\n");
116 	printf("\t.set reorder\n");
117 
118 	printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], ARGINIT/SZCHAR);
119 	/* emit PIC only if -fpic or -fPIC set */
120 	if (kflag > 0)
121 		printf("\t.cprestore 8\t# pseudo-op to store GOT ptr at 8(sp)\n");
122 
123 	printf("\tsw %s,4(%s)\n", rnames[RA], rnames[SP]);
124 	printf("\tsw %s,(%s)\n", rnames[FP], rnames[SP]);
125 	printf("\tmove %s,%s\n", rnames[FP], rnames[SP]);
126 
127 #ifdef notyet
128 	/* profiling */
129 	if (pflag) {
130 		printf("\t.set noat\n");
131 		printf("\tmove %s,%s\t# save current return address\n",
132 		    rnames[AT], rnames[RA]);
133 		printf("\tsubu %s,%s,8\t# _mcount pops 2 words from stack\n",
134 		    rnames[SP], rnames[SP]);
135 		printf("\tjal %s\n", exname("_mcount"));
136 		printf("\tnop\n");
137 		printf("\t.set at\n");
138 	}
139 #endif
140 
141 	if (addto)
142 		printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], addto);
143 
144 	for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++)
145 		if (i & 1)
146 			printf("\tsw %s,-%d(%s) # save permanent\n",
147 				rnames[j], regoff[j], rnames[FP]);
148 
149 }
150 
151 void
eoftn(struct interpass_prolog * ipp)152 eoftn(struct interpass_prolog * ipp)
153 {
154 	int i, j;
155 
156 	(void) offcalc(ipp);
157 
158 	if (ipp->ipp_ip.ip_lbl == 0)
159 		return;		/* no code needs to be generated */
160 
161 	/* return from function code */
162 	for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) {
163 		if (i & 1)
164 			printf("\tlw %s,-%d(%s)\n\tnop\n",
165 				rnames[j], regoff[j], rnames[FP]);
166 	}
167 
168 	printf("\taddiu %s,%s,%d\n", rnames[SP], rnames[FP], ARGINIT/SZCHAR);
169 	printf("\tlw %s,%d(%s)\n", rnames[RA], 4-ARGINIT/SZCHAR,  rnames[SP]);
170 	printf("\tlw %s,%d(%s)\n", rnames[FP], 0-ARGINIT/SZCHAR,  rnames[SP]);
171 
172 	printf("\tjr %s\n", rnames[RA]);
173 	printf("\tnop\n");
174 
175 #ifdef USE_GAS
176 	printf("\t.end %s\n", ipp->ipp_name);
177 	printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name);
178 #endif
179 }
180 
181 /*
182  * add/sub/...
183  *
184  * Param given:
185  */
186 void
hopcode(int f,int o)187 hopcode(int f, int o)
188 {
189 	char *str;
190 
191 	switch (o) {
192 	case EQ:
193 		str = "beqz";	/* pseudo-op */
194 		break;
195 	case NE:
196 		str = "bnez";	/* pseudo-op */
197 		break;
198 	case ULE:
199 	case LE:
200 		str = "blez";
201 		break;
202 	case ULT:
203 	case LT:
204 		str = "bltz";
205 		break;
206 	case UGE:
207 	case GE:
208 		str = "bgez";
209 		break;
210 	case UGT:
211 	case GT:
212 		str = "bgtz";
213 		break;
214 	case PLUS:
215 		str = "add";
216 		break;
217 	case MINUS:
218 		str = "sub";
219 		break;
220 	case AND:
221 		str = "and";
222 		break;
223 	case OR:
224 		str = "or";
225 		break;
226 	case ER:
227 		str = "xor";
228 		break;
229 	default:
230 		comperr("hopcode2: %d", o);
231 		str = 0;	/* XXX gcc */
232 	}
233 
234 	printf("%s%c", str, f);
235 }
236 
237 char *
238 rnames[] = {
239 #ifdef USE_GAS
240 	/* gnu assembler */
241 	"$zero", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
242 	"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
243 	"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
244 	"$24", "$25",
245 	"$kt0", "$kt1", "$gp", "$sp", "$fp", "$ra",
246 	"$2!!$3!!",
247 	"$4!!$5!!", "$5!!$6!!", "$6!!$7!!", "$7!!$8!!",
248 	"$8!!$9!!", "$9!!$10!", "$10!$11!", "$11!$12!",
249 	"$12!$13!", "$13!$14!", "$14!$15!", "$15!$24!", "$24!$25!",
250 	"$16!$17!", "$17!$18!", "$18!$19!", "$19!$20!",
251 	"$20!$21!", "$21!$22!", "$22!$23!",
252 #else
253 	/* mips assembler */
254 	 "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
255 	"$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
256 	"$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
257 	"$t8", "$t9",
258 	"$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
259 	"$v0!$v1!",
260 	"$a0!$a1!", "$a1!$a2!", "$a2!$a3!", "$a3!$t0!",
261 	"$t0!$t1!", "$t1!$t2!", "$t2!$t3!", "$t3!$t4!",
262 	"$t4!$t5!", "$t5!$t6!", "$t6!$t7!", "$t7!$t8!", "$t8!$t9!",
263 	"$s0!$s1!", "$s1!$s2!", "$s2!$s3!", "$s3!$s4!",
264 	"$s4!$s5!", "$s5!$s6!", "$s6!$s7!",
265 #endif
266 	"$f0!$f1!", "$f2!$f3!", "$f4!$f5!", "$f6!$f7!",
267 	"$f8!$f9!", "$f10$f11", "$f12$f13", "$f14$f15",
268 	"$f16$f17", "$f18$f19", "$f20$f21", "$f22$f23",
269 	"$f24$f25", "$f26$f27", "$f28$f29", "$f30$f31",
270 };
271 
272 char *
273 rnames_n32[] = {
274 	/* mips assembler */
275 	"$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
276 	"$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2", "$t3",
277 	"$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
278 	"$t8", "$t9",
279 	"$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
280 	"$v0!$v1!",
281 	"$a0!$a1!", "$a1!$a2!", "$a2!$a3!", "$a3!$a4!",
282 	"$a4!$a5!", "$a5!$a6!", "$a6!$a7!", "$a7!$t0!",
283 	"$t0!$t1!", "$t1!$t2!", "$t2!$t3!", "$t3!$t8!", "$t8!$t9!",
284 	"$s0!$s1!", "$s1!$s2!", "$s2!$s3!", "$s3!$s4!",
285 	"$s4!$s5!", "$s5!$s6!", "$s6!$s7!",
286 	"$f0!$f1!", "$f2!$f3!", "$f4!$f5!", "$f6!$f7!",
287 	"$f8!$f9!", "$f10$f11", "$f12$f13", "$f14$f15",
288 	"$f16$f17", "$f18$f19", "$f20$f21", "$f22$f23",
289 	"$f24$f25", "$f26$f27", "$f28$f29", "$f30$f31",
290 };
291 
292 int
tlen(NODE * p)293 tlen(NODE *p)
294 {
295 	switch (p->n_type) {
296 	case CHAR:
297 	case UCHAR:
298 		return (1);
299 
300 	case SHORT:
301 	case USHORT:
302 		return (SZSHORT / SZCHAR);
303 
304 	case DOUBLE:
305 		return (SZDOUBLE / SZCHAR);
306 
307 	case INT:
308 	case UNSIGNED:
309 	case LONG:
310 	case ULONG:
311 		return (SZINT / SZCHAR);
312 
313 	case LONGLONG:
314 	case ULONGLONG:
315 		return SZLONGLONG / SZCHAR;
316 
317 	default:
318 		if (!ISPTR(p->n_type))
319 			comperr("tlen type %d not pointer");
320 		return SZPOINT(p->n_type) / SZCHAR;
321 	}
322 }
323 
324 
325 /*
326  * Push a structure on stack as argument.
327  */
328 static void
starg(NODE * p)329 starg(NODE *p)
330 {
331 	int sz = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
332 	//assert(p->n_rval == A1);
333 	printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], sz);
334 	/* A0 = dest, A1 = src, A2 = len */
335 	printf("\tmove %s,%s\n", rnames[A0], rnames[SP]);
336 	printf("\tli %s,%d\t# structure size\n", rnames[A2], sz);
337 	printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]);
338 	printf("\tjal %s\t# structure copy\n", exname("memcpy"));
339 	printf("\tnop\n");
340 	printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]);
341 }
342 
343 /*
344  * Structure assignment.
345  */
346 static void
stasg(NODE * p)347 stasg(NODE *p)
348 {
349 	assert(p->n_right->n_rval == A1);
350 	/* A0 = dest, A1 = src, A2 = len */
351 	printf("\tli %s,%d\t# structure size\n", rnames[A2],
352 	    attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0));
353 	if (p->n_left->n_op == OREG) {
354 		printf("\taddiu %s,%s," CONFMT "\t# dest address\n",
355 		    rnames[A0], rnames[p->n_left->n_rval],
356 		    getlval(p->n_left));
357 	} else if (p->n_left->n_op == NAME) {
358 		printf("\tla %s,", rnames[A0]);
359 		adrput(stdout, p->n_left);
360 		printf("\n");
361 	}
362 	printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]);
363 	printf("\tjal %s\t# structure copy\n", exname("memcpy"));
364 	printf("\tnop\n");
365 	printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]);
366 }
367 
368 static void
shiftop(NODE * p)369 shiftop(NODE *p)
370 {
371 	NODE *r = p->n_right;
372 	TWORD ty = p->n_type;
373 
374 	if (p->n_op == LS && r->n_op == ICON && getlval(r) < 32) {
375 		expand(p, INBREG, "\tsrl A1,AL,");
376 		printf(CONFMT "\t# 64-bit left-shift\n", 32 - getlval(r));
377 		expand(p, INBREG, "\tsll U1,UL,AR\n");
378 		expand(p, INBREG, "\tor U1,U1,A1\n");
379 		expand(p, INBREG, "\tsll A1,AL,AR\n");
380 	} else if (p->n_op == LS && r->n_op == ICON && getlval(r) < 64) {
381 		expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n");
382 		expand(p, INBREG, "\tsll U1,AL,");
383 		printf(CONFMT "\n", getlval(r) - 32);
384 	} else if (p->n_op == LS && r->n_op == ICON) {
385 		expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n");
386 		expand(p, INBREG, "\tli U1,0\n");
387 	} else if (p->n_op == RS && r->n_op == ICON && getlval(r) < 32) {
388 		expand(p, INBREG, "\tsll U1,UL,");
389 		printf(CONFMT "\t# 64-bit right-shift\n", 32 - getlval(r));
390 		expand(p, INBREG, "\tsrl A1,AL,AR\n");
391 		expand(p, INBREG, "\tor A1,A1,U1\n");
392 		if (ty == LONGLONG)
393 			expand(p, INBREG, "\tsra U1,UL,AR\n");
394 		else
395 			expand(p, INBREG, "\tsrl U1,UL,AR\n");
396 	} else if (p->n_op == RS && r->n_op == ICON && getlval(r) < 64) {
397 		if (ty == LONGLONG) {
398 			expand(p, INBREG, "\tsra U1,UL,31\t# 64-bit right-shift\n");
399 			expand(p, INBREG, "\tsra A1,UL,");
400 		}else {
401 			expand(p, INBREG, "\tli U1,0\t# 64-bit right-shift\n");
402 			expand(p, INBREG, "\tsrl A1,UL,");
403 		}
404 		printf(CONFMT "\n", getlval(r) - 32);
405 	} else if (p->n_op == LS && r->n_op == ICON) {
406 		expand(p, INBREG, "\tli A1,0\t# 64-bit right-shift\n");
407 		expand(p, INBREG, "\tli U1,0\n");
408 	} else {
409 		comperr("shiftop");
410 	}
411 }
412 
413 /*
414  * http://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Soft-float-library-routines
415  */
416 static void
fpemulop(NODE * p)417 fpemulop(NODE *p)
418 {
419 	NODE *l = p->n_left;
420 	char *ch = NULL;
421 
422 	if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3";
423 	else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3";
424 	else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3";
425 
426 	else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3";
427 	else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3";
428 	else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3";
429 
430 	else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3";
431 	else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3";
432 	else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3";
433 
434 	else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3";
435 	else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3";
436 	else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3";
437 
438 	else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2";
439 	else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2";
440 	else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2";
441 
442 	else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2";
443 	else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2";
444 	else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2";
445 
446 	else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2";
447 	else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2";
448 	else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2";
449 
450 	else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2";
451 	else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2";
452 	else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2";
453 
454 	else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2";
455 	else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2";
456 	else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2";
457 
458 	else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2";
459 	else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2";
460 	else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2";
461 
462 	else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2";
463 	else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2";
464 	else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2";
465 
466 	else if (p->n_op == SCONV && p->n_type == FLOAT) {
467 		if (l->n_type == DOUBLE) ch = "truncdfsf2";
468 		else if (l->n_type == LDOUBLE) ch = "trunctfsf2";
469 		else if (l->n_type == ULONGLONG) ch = "floatdisf"; /**/
470 		else if (l->n_type == LONGLONG) ch = "floatdisf";
471 		else if (l->n_type == LONG) ch = "floatsisf";
472 		else if (l->n_type == ULONG) ch = "floatunsisf";
473 		else if (l->n_type == INT) ch = "floatsisf";
474 		else if (l->n_type == UNSIGNED) ch = "floatunsisf";
475 	} else if (p->n_op == SCONV && p->n_type == DOUBLE) {
476 		if (l->n_type == FLOAT) ch = "extendsfdf2";
477 		else if (l->n_type == LDOUBLE) ch = "trunctfdf2";
478 		else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
479 		else if (l->n_type == LONGLONG) ch = "floatdidf";
480 		else if (l->n_type == LONG) ch = "floatsidf";
481 		else if (l->n_type == ULONG) ch = "floatunsidf";
482 		else if (l->n_type == INT) ch = "floatsidf";
483 		else if (l->n_type == UNSIGNED) ch = "floatunsidf";
484 	} else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
485 		if (l->n_type == FLOAT) ch = "extendsftf2";
486 		else if (l->n_type == DOUBLE) ch = "extenddfdf2";
487 		else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
488 		else if (l->n_type == LONGLONG) ch = "floatdidf";
489 		else if (l->n_type == LONG) ch = "floatsidf";
490 		else if (l->n_type == ULONG) ch = "floatunssidf";
491 		else if (l->n_type == INT) ch = "floatsidf";
492 		else if (l->n_type == UNSIGNED) ch = "floatunsidf";
493 	} else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
494 		if (l->n_type == FLOAT) ch = "fixunssfdi";
495 		else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
496 		else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
497 	} else if (p->n_op == SCONV && p->n_type == LONGLONG) {
498 		if (l->n_type == FLOAT) ch = "fixsfdi";
499 		else if (l->n_type == DOUBLE) ch = "fixdfdi";
500 		else if (l->n_type == LDOUBLE) ch = "fixdfdi";
501 	} else if (p->n_op == SCONV && p->n_type == LONG) {
502 		if (l->n_type == FLOAT) ch = "fixsfsi";
503 		else if (l->n_type == DOUBLE) ch = "fixdfsi";
504 		else if (l->n_type == LDOUBLE) ch = "fixdfsi";
505 	} else if (p->n_op == SCONV && p->n_type == ULONG) {
506 		if (l->n_type == FLOAT) ch = "fixunssfsi";
507 		else if (l->n_type == DOUBLE) ch = "fixunsdfsi";
508 		else if (l->n_type == LDOUBLE) ch = "fixunsdfsi";
509 	} else if (p->n_op == SCONV && p->n_type == INT) {
510 		if (l->n_type == FLOAT) ch = "fixsfsi";
511 		else if (l->n_type == DOUBLE) ch = "fixdfsi";
512 		else if (l->n_type == LDOUBLE) ch = "fixdfsi";
513 	} else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
514 		if (l->n_type == FLOAT) ch = "fixunssfsi";
515 		else if (l->n_type == DOUBLE) ch = "fixunsdfsi";
516 		else if (l->n_type == LDOUBLE) ch = "fixunsdfsi";
517 	}
518 
519 	if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op);
520 
521 	if (p->n_op == SCONV) {
522 		if (l->n_type == FLOAT) {
523 			printf("\tmfc1 %s,", rnames[A0]);
524 			adrput(stdout, l);
525 			printf("\n\tnop\n");
526 		}  else if (l->n_type == DOUBLE || l->n_type == LDOUBLE) {
527 			printf("\tmfc1 %s,", rnames[A1]);
528 			upput(l, 0);
529 			printf("\n\tnop\n");
530 			printf("\tmfc1 %s,", rnames[A0]);
531 			adrput(stdout, l);
532 			printf("\n\tnop\n");
533 		}
534 	} else {
535 		comperr("ZF: incomplete softfloat - put args in registers");
536 	}
537 
538 	printf("\tjal __%s\t# softfloat operation\n", exname(ch));
539 	printf("\tnop\n");
540 
541 	if (p->n_op >= EQ && p->n_op <= GT)
542 		printf("\tcmp %s,0\n", rnames[V0]);
543 }
544 
545 /*
546  * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
547  */
548 static void
emulop(NODE * p)549 emulop(NODE *p)
550 {
551 	char *ch = NULL;
552 
553 	if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3";
554 	else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG ||
555 	    DEUNSIGN(p->n_type) == INT))
556 		ch = "ashlsi3";
557 
558 	else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3";
559 	else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT))
560 		ch = "lshrsi3";
561 
562 	else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3";
563 	else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT))
564 		ch = "ashrsi3";
565 
566 	else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3";
567 	else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT))
568 		ch = "divsi3";
569 
570 	else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3";
571 	else if (p->n_op == DIV && (p->n_type == ULONG ||
572 	    p->n_type == UNSIGNED))
573 		ch = "udivsi3";
574 
575 	else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3";
576 	else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT))
577 		ch = "modsi3";
578 
579 	else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3";
580 	else if (p->n_op == MOD && (p->n_type == ULONG ||
581 	    p->n_type == UNSIGNED))
582 		ch = "umodsi3";
583 
584 	else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3";
585 	else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT))
586 		ch = "mulsi3";
587 
588 	else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2";
589 	else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2";
590 
591 	else ch = 0, comperr("ZE");
592 	printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]);
593 	printf("\tjal __%s\t# emulated operation\n", exname(ch));
594 	printf("\tnop\n");
595 	printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]);
596 }
597 
598 /*
599  * Emit code to compare two longlong numbers.
600  */
601 static void
twollcomp(NODE * p)602 twollcomp(NODE *p)
603 {
604 	int o = p->n_op;
605 	int s = getlab2();
606 	int e = p->n_label;
607 	int cb1, cb2;
608 
609 	if (o >= ULE)
610 		o -= (ULE-LE);
611 	switch (o) {
612 	case NE:
613 		cb1 = 0;
614 		cb2 = NE;
615 		break;
616 	case EQ:
617 		cb1 = NE;
618 		cb2 = 0;
619 		break;
620 	case LE:
621 	case LT:
622 		cb1 = GT;
623 		cb2 = LT;
624 		break;
625 	case GE:
626 	case GT:
627 		cb1 = LT;
628 		cb2 = GT;
629 		break;
630 
631 	default:
632 		cb1 = cb2 = 0; /* XXX gcc */
633 	}
634 	if (p->n_op >= ULE)
635 		cb1 += 4, cb2 += 4;
636 	expand(p, 0, "\tsub A1,UL,UR\t# compare 64-bit values (upper)\n");
637 	if (cb1) {
638 		printf("\t");
639 		hopcode(' ', cb1);
640 		expand(p, 0, "A1");
641 		printf("," LABFMT "\n", s);
642 		printf("\tnop\n");
643 	}
644 	if (cb2) {
645 		printf("\t");
646 		hopcode(' ', cb2);
647 		expand(p, 0, "A1");
648 		printf("," LABFMT "\n", e);
649 		printf("\tnop\n");
650 	}
651 	expand(p, 0, "\tsub A1,AL,AR\t# (and lower)\n");
652 	printf("\t");
653 	hopcode(' ', o);
654 	expand(p, 0, "A1");
655 	printf("," LABFMT "\n", e);
656 	printf("\tnop\n");
657 	deflab(s);
658 }
659 
660 static void
fpcmpops(NODE * p)661 fpcmpops(NODE *p)
662 {
663 	NODE *l = p->n_left;
664 
665 	switch (p->n_op) {
666 	case EQ:
667 		if (l->n_type == FLOAT)
668 			expand(p, 0, "\tc.eq.s AL,AR\n");
669 		else
670 			expand(p, 0, "\tc.eq.d AL,AR\n");
671 		expand(p, 0, "\tnop\n\tbc1t LC\n");
672 		break;
673 	case NE:
674 		if (l->n_type == FLOAT)
675 			expand(p, 0, "\tc.eq.s AL,AR\n");
676 		else
677 			expand(p, 0, "\tc.eq.d AL,AR\n");
678 		expand(p, 0, "\tnop\n\tbc1f LC\n");
679 		break;
680 	case LT:
681 		if (l->n_type == FLOAT)
682 			expand(p, 0, "\tc.lt.s AL,AR\n");
683 		else
684 			expand(p, 0, "\tc.lt.d AL,AR\n");
685 		expand(p, 0, "\tnop\n\tbc1t LC\n");
686 		break;
687 	case GE:
688 		if (l->n_type == FLOAT)
689 			expand(p, 0, "\tc.lt.s AL,AR\n");
690 		else
691 			expand(p, 0, "\tc.lt.d AL,AR\n");
692 		expand(p, 0, "\tnop\n\tbc1f LC\n");
693 		break;
694 	case LE:
695 		if (l->n_type == FLOAT)
696 			expand(p, 0, "\tc.le.s AL,AR\n");
697 		else
698 			expand(p, 0, "\tc.le.d AL,AR\n");
699 		expand(p, 0, "\tnop\n\tbc1t LC\n");
700 		break;
701 	case GT:
702 		if (l->n_type == FLOAT)
703 			expand(p, 0, "\tc.le.s AL,AR\n");
704 		else
705 			expand(p, 0, "\tc.le.d AL,AR\n");
706 		expand(p, 0, "\tnop\n\tbc1f LC\n");
707 		break;
708 	}
709 	printf("\tnop\n\tnop\n");
710 }
711 
712 void
zzzcode(NODE * p,int c)713 zzzcode(NODE * p, int c)
714 {
715 	int sz;
716 
717 	switch (c) {
718 
719 	case 'C':	/* remove arguments from stack after subroutine call */
720 		sz = p->n_qual > 16 ? p->n_qual : 16;
721 		printf("\taddiu %s,%s,%d\n", rnames[SP], rnames[SP], sz);
722 		break;
723 
724 	case 'D':	/* long long comparison */
725 		twollcomp(p);
726 		break;
727 
728 	case 'E':	/* emit emulated ops */
729 		emulop(p);
730 		break;
731 
732 	case 'F':	/* emit emulate floating point ops */
733 		fpemulop(p);
734 		break;
735 
736 	case 'G':	/* emit hardware floating-point compare op */
737 		fpcmpops(p);
738 		break;
739 
740 	case 'H':	/* structure argument */
741 		starg(p);
742 		break;
743 
744 	case 'I':		/* high part of init constant */
745 		if (p->n_name[0] != '\0')
746 			comperr("named highword");
747 		printf(CONFMT, (getlval(p) >> 32) & 0xffffffff);
748 		break;
749 
750         case 'O': /* 64-bit left and right shift operators */
751 		shiftop(p);
752 		break;
753 
754 	case 'Q':		/* emit struct assign */
755 		stasg(p);
756 		break;
757 
758 	default:
759 		comperr("zzzcode %c", c);
760 	}
761 }
762 
763 /* ARGSUSED */
764 int
rewfld(NODE * p)765 rewfld(NODE * p)
766 {
767 	return (1);
768 }
769 
770 int
fldexpand(NODE * p,int cookie,char ** cp)771 fldexpand(NODE *p, int cookie, char **cp)
772 {
773         CONSZ val;
774 
775         if (p->n_op == ASSIGN)
776                 p = p->n_left;
777         switch (**cp) {
778         case 'S':
779                 printf("%d", UPKFSZ(p->n_rval));
780                 break;
781         case 'H':
782                 printf("%d", UPKFOFF(p->n_rval));
783                 break;
784         case 'M':
785         case 'N':
786                 val = (CONSZ)1 << UPKFSZ(p->n_rval);
787                 --val;
788                 val <<= UPKFOFF(p->n_rval);
789                 printf("0x%llx", (**cp == 'M' ? val : ~val)  & 0xffffffff);
790                 break;
791         default:
792                 comperr("fldexpand");
793         }
794         return 1;
795 }
796 
797 /*
798  * Does the bitfield shape match?
799  */
800 int
flshape(NODE * p)801 flshape(NODE * p)
802 {
803 	int o = p->n_op;
804 
805 	if (o == OREG || o == REG || o == NAME)
806 		return SRDIR;	/* Direct match */
807 	if (o == UMUL && shumul(p->n_left, SOREG))
808 		return SROREG;	/* Convert into oreg */
809 	return SRREG;		/* put it into a register */
810 }
811 
812 /* INTEMP shapes must not contain any temporary registers */
813 /* XXX should this go away now? */
814 int
shtemp(NODE * p)815 shtemp(NODE * p)
816 {
817 	return 0;
818 #if 0
819 	int r;
820 
821 	if (p->n_op == STARG)
822 		p = p->n_left;
823 
824 	switch (p->n_op) {
825 	case REG:
826 		return (!istreg(p->n_rval));
827 
828 	case OREG:
829 		r = p->n_rval;
830 		if (R2TEST(r)) {
831 			if (istreg(R2UPK1(r)))
832 				return (0);
833 			r = R2UPK2(r);
834 		}
835 		return (!istreg(r));
836 
837 	case UMUL:
838 		p = p->n_left;
839 		return (p->n_op != UMUL && shtemp(p));
840 	}
841 
842 	if (optype(p->n_op) != LTYPE)
843 		return (0);
844 	return (1);
845 #endif
846 }
847 
848 void
adrcon(CONSZ val)849 adrcon(CONSZ val)
850 {
851 	printf(CONFMT, val);
852 }
853 
854 void
conput(FILE * fp,NODE * p)855 conput(FILE *fp, NODE *p)
856 {
857 	int val = getlval(p);
858 
859 	switch (p->n_op) {
860 	case ICON:
861 		if (p->n_name[0] != '\0') {
862 			fprintf(fp, "%s", p->n_name);
863 			if (getlval(p))
864 				fprintf(fp, "+%d", val);
865 		} else
866 			fprintf(fp, "%d", val);
867 		return;
868 
869 	default:
870 		comperr("illegal conput");
871 	}
872 }
873 
874 /* ARGSUSED */
875 void
insput(NODE * p)876 insput(NODE * p)
877 {
878 	comperr("insput");
879 }
880 
881 /*
882  * Print lower or upper name of 64-bit register.
883  */
884 static void
print_reg64name(FILE * fp,int rval,int hi)885 print_reg64name(FILE *fp, int rval, int hi)
886 {
887         int off = 4 * (hi != 0);
888 	char *regname = rnames[rval];
889 
890         fprintf(fp, "%c%c",
891                  regname[off],
892                  regname[off + 1]);
893         if (regname[off + 2] != '!')
894                 fputc(regname[off + 2], fp);
895         if (regname[off + 3] != '!')
896                 fputc(regname[off + 3], fp);
897 }
898 
899 /*
900  * Write out the upper address, like the upper register of a 2-register
901  * reference, or the next memory location.
902  */
903 void
upput(NODE * p,int size)904 upput(NODE * p, int size)
905 {
906 
907 	size /= SZCHAR;
908 	switch (p->n_op) {
909 	case REG:
910 		if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
911 			print_reg64name(stdout, p->n_rval, 1);
912 		else
913 			printf("%s", rnames[p->n_rval]);
914 		break;
915 
916 	case NAME:
917 	case OREG:
918 		setlval(p, getlval(p) + size);
919 		adrput(stdout, p);
920 		setlval(p, getlval(p) - size);
921 		break;
922 	case ICON:
923 		printf(CONFMT, getlval(p) >> 32);
924 		break;
925 	default:
926 		comperr("upput bad op %d size %d", p->n_op, size);
927 	}
928 }
929 
930 void
adrput(FILE * io,NODE * p)931 adrput(FILE * io, NODE * p)
932 {
933 	/* output an address, with offsets, from p */
934 
935 	if (p->n_op == FLD)
936 		p = p->n_left;
937 
938 	switch (p->n_op) {
939 
940 	case NAME:
941 		if (p->n_name[0] != '\0')
942 			fputs(p->n_name, io);
943 		if (getlval(p) != 0)
944 			fprintf(io, "+" CONFMT, getlval(p));
945 		return;
946 
947 	case OREG:
948 		if (getlval(p))
949 			fprintf(io, "%d", (int) getlval(p));
950 		fprintf(io, "(%s)", rnames[p->n_rval]);
951 		return;
952 
953 	case ICON:
954 		/* addressable value of the constant */
955 		conput(io, p);
956 		return;
957 
958 	case REG:
959 		if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
960 			print_reg64name(io, p->n_rval, 0);
961 		else
962 			fputs(rnames[p->n_rval], io);
963 		return;
964 
965 	default:
966 		comperr("illegal address, op %d, node %p", p->n_op, p);
967 		return;
968 
969 	}
970 }
971 
972 /* printf conditional and unconditional branches */
973 void
cbgen(int o,int lab)974 cbgen(int o, int lab)
975 {
976 }
977 
978 void
myreader(struct interpass * ipole)979 myreader(struct interpass * ipole)
980 {
981 }
982 
983 #if 0
984 /*
985  *  Calculate the stack size for arguments
986  */
987 static int stacksize;
988 
989 static void
990 calcstacksize(NODE *p, void *arg)
991 {
992 	int sz;
993 
994 	printf("op=%d\n", p->n_op);
995 
996 	if (p->n_op != CALL && p->n_op != STCALL)
997 		return;
998 
999 	sz = argsiz(p->n_right);
1000 	if (sz > stacksize)
1001 		stacksize = sz;
1002 
1003 #ifdef PCC_DEBUG
1004 	if (x2debug)
1005 		printf("stacksize: %d\n", stacksize);
1006 #endif
1007 }
1008 #endif
1009 
1010 /*
1011  * If we're big endian, then all OREG loads of a type
1012  * larger than the destination, must have the
1013  * offset changed to point to the correct bytes in memory.
1014  */
1015 static void
offchg(NODE * p,void * arg)1016 offchg(NODE *p, void *arg)
1017 {
1018 	NODE *l;
1019 
1020 	if (p->n_op != SCONV)
1021 		return;
1022 
1023 	l = p->n_left;
1024 
1025 	if (l->n_op != OREG)
1026 		return;
1027 
1028 	switch (l->n_type) {
1029 	case SHORT:
1030 	case USHORT:
1031 		if (DEUNSIGN(p->n_type) == CHAR)
1032 			setlval(l, getlval(l) + 1);
1033 		break;
1034 	case LONG:
1035 	case ULONG:
1036 	case INT:
1037 	case UNSIGNED:
1038 		if (DEUNSIGN(p->n_type) == CHAR)
1039 			setlval(l, getlval(l + 3));
1040 		else if (DEUNSIGN(p->n_type) == SHORT)
1041 			setlval(l, getlval(l + 2));
1042 		break;
1043 	case LONGLONG:
1044 	case ULONGLONG:
1045 		if (DEUNSIGN(p->n_type) == CHAR)
1046 			setlval(l, getlval(l + 7));
1047 		else if (DEUNSIGN(p->n_type) == SHORT)
1048 			setlval(l, getlval(l + 6));
1049 		else if (DEUNSIGN(p->n_type) == INT ||
1050 		    DEUNSIGN(p->n_type) == LONG)
1051 			setlval(l, getlval(l + 4));
1052 		break;
1053 	default:
1054 		comperr("offchg: unknown type");
1055 		break;
1056 	}
1057 }
1058 
1059 /*
1060  * Remove some PCONVs after OREGs are created.
1061  */
1062 static void
pconv2(NODE * p,void * arg)1063 pconv2(NODE * p, void *arg)
1064 {
1065 	NODE *q;
1066 
1067 	if (p->n_op == PLUS) {
1068 		if (p->n_type == (PTR | SHORT) || p->n_type == (PTR | USHORT)) {
1069 			if (p->n_right->n_op != ICON)
1070 				return;
1071 			if (p->n_left->n_op != PCONV)
1072 				return;
1073 			if (p->n_left->n_left->n_op != OREG)
1074 				return;
1075 			q = p->n_left->n_left;
1076 			nfree(p->n_left);
1077 			p->n_left = q;
1078 			/*
1079 		         * This will be converted to another OREG later.
1080 		         */
1081 		}
1082 	}
1083 }
1084 
1085 void
mycanon(NODE * p)1086 mycanon(NODE * p)
1087 {
1088 	walkf(p, pconv2, 0);
1089 }
1090 
1091 void
myoptim(struct interpass * ipole)1092 myoptim(struct interpass * ipole)
1093 {
1094 	struct interpass *ip;
1095 
1096 #ifdef PCC_DEBUG
1097 	if (x2debug)
1098 		printf("myoptim:\n");
1099 #endif
1100 
1101 #if 0
1102 	stacksize = 0;
1103 #endif
1104 
1105 	DLIST_FOREACH(ip, ipole, qelem) {
1106 		if (ip->type != IP_NODE)
1107 			continue;
1108 		if (bigendian)
1109 			walkf(ip->ip_node, offchg, 0);
1110 #if 0
1111 		walkf(ip->ip_node, calcstacksize, 0);
1112 #endif
1113 	}
1114 }
1115 
1116 /*
1117  * Move data between registers.  While basic registers aren't a problem,
1118  * we have to handle the special case of overlapping composite registers.
1119  */
1120 void
rmove(int s,int d,TWORD t)1121 rmove(int s, int d, TWORD t)
1122 {
1123         switch (t) {
1124         case LONGLONG:
1125         case ULONGLONG:
1126                 if (s == d+1) {
1127                         /* dh = sl, copy low word first */
1128                         printf("\tmove ");
1129 			print_reg64name(stdout, d, 0);
1130 			printf(",");
1131 			print_reg64name(stdout, s, 0);
1132 			printf("\t# 64-bit rmove\n");
1133                         printf("\tmove ");
1134 			print_reg64name(stdout, d, 1);
1135 			printf(",");
1136 			print_reg64name(stdout, s, 1);
1137 			printf("\n");
1138                 } else {
1139                         /* copy high word first */
1140                         printf("\tmove ");
1141 			print_reg64name(stdout, d, 1);
1142 			printf(",");
1143 			print_reg64name(stdout, s, 1);
1144 			printf(" # 64-bit rmove\n");
1145                         printf("\tmove ");
1146 			print_reg64name(stdout, d, 0);
1147 			printf(",");
1148 			print_reg64name(stdout, s, 0);
1149 			printf("\n");
1150                 }
1151                 break;
1152 	case FLOAT:
1153 	case DOUBLE:
1154         case LDOUBLE:
1155 		if (t == FLOAT)
1156 			printf("\tmov.s ");
1157 		else
1158 			printf("\tmov.d ");
1159 		print_reg64name(stdout, d, 0);
1160 		printf(",");
1161 		print_reg64name(stdout, s, 0);
1162 		printf("\t# float/double rmove\n");
1163                 break;
1164         default:
1165                 printf("\tmove %s,%s\t# default rmove\n", rnames[d], rnames[s]);
1166         }
1167 }
1168 
1169 
1170 /*
1171  * For class c, find worst-case displacement of the number of
1172  * registers in the array r[] indexed by class.
1173  *
1174  * On MIPS, we have:
1175  *
1176  * 32 32-bit registers (8 reserved)
1177  * 26 64-bit pseudo registers (1 unavailable)
1178  * 16 floating-point register pairs
1179  */
1180 int
COLORMAP(int c,int * r)1181 COLORMAP(int c, int *r)
1182 {
1183 	int num = 0;
1184 
1185         switch (c) {
1186         case CLASSA:
1187                 num += r[CLASSA];
1188                 num += 2*r[CLASSB];
1189                 return num < 24;
1190         case CLASSB:
1191                 num += 2*r[CLASSB];
1192                 num += r[CLASSA];
1193                 return num < 25;
1194 	case CLASSC:
1195 		num += r[CLASSC];
1196 		return num < 6;
1197         }
1198 	comperr("COLORMAP");
1199         return 0; /* XXX gcc */
1200 }
1201 
1202 /*
1203  * Return a class suitable for a specific type.
1204  */
1205 int
gclass(TWORD t)1206 gclass(TWORD t)
1207 {
1208 	if (t == LONGLONG || t == ULONGLONG)
1209 		return CLASSB;
1210 	if (t >= FLOAT && t <= LDOUBLE)
1211 		return CLASSC;
1212 	return CLASSA;
1213 }
1214 
1215 /*
1216  * Calculate argument sizes.
1217  */
1218 void
lastcall(NODE * p)1219 lastcall(NODE *p)
1220 {
1221 	int sz;
1222 
1223 #ifdef PCC_DEBUG
1224 	if (x2debug)
1225 		printf("lastcall:\n");
1226 #endif
1227 
1228 	p->n_qual = 0;
1229 	if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
1230 		return;
1231 
1232 	sz = argsiz(p->n_right);
1233 
1234 	if ((sz > 4*nargregs) && (sz & 7) != 0) {
1235 		printf("\tsubu %s,%s,4\t# align stack\n",
1236 		    rnames[SP], rnames[SP]);
1237 		sz += 4;
1238 		assert((sz & 7) == 0);
1239 	}
1240 
1241 	p->n_qual = sz; /* XXX */
1242 }
1243 
1244 static int
argsiz(NODE * p)1245 argsiz(NODE *p)
1246 {
1247 	TWORD t;
1248 	int size = 0;
1249 	int sz = 0;
1250 
1251 	if (p->n_op == CM) {
1252 		size = argsiz(p->n_left);
1253 		p = p->n_right;
1254 	}
1255 
1256 	t = p->n_type;
1257 	if (t < LONGLONG || t > BTMASK)
1258 		sz = 4;
1259 	else if (DEUNSIGN(t) == LONGLONG)
1260 		sz = 8;
1261 	else if (t == DOUBLE || t == LDOUBLE)
1262 		sz = 8;
1263 	else if (t == FLOAT)
1264 		sz = 4;
1265 	else if (t == STRTY || t == UNIONTY)
1266 		sz = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
1267 
1268 	if (p->n_type == STRTY || p->n_type == UNIONTY) {
1269 		return (size + sz);
1270 	}
1271 
1272 	/* alignment */
1273 	if (sz == 8 && (size & 7) != 0)
1274 		sz += 4;
1275 
1276 //	printf("size=%d, sz=%d -> %d\n", size, sz, size + sz);
1277 	return (size + sz);
1278 }
1279 
1280 /*
1281  * Special shapes.
1282  */
1283 int
special(NODE * p,int shape)1284 special(NODE *p, int shape)
1285 {
1286 	int o = p->n_op;
1287 
1288 	if (o != ICON || p->n_name[0] != 0)
1289 		return SRNOPE;
1290 
1291 	switch(shape) {
1292 	case SPCON:
1293 		if ((getlval(p) & ~0xffff) == 0)
1294 			return SRDIR;
1295 		break;
1296 	}
1297 
1298 	return SRNOPE;
1299 }
1300 
1301 /*
1302  * Target-dependent command-line options.
1303  */
1304 void
mflags(char * str)1305 mflags(char *str)
1306 {
1307 	if (strcasecmp(str, "big-endian") == 0) {
1308 		bigendian = 1;
1309 	} else if (strcasecmp(str, "little-endian") == 0) {
1310 		bigendian = 0;
1311 	} else {
1312 		fprintf(stderr, "unknown m option '%s'\n", str);
1313 		exit(1);
1314 	}
1315 
1316 #if 0
1317 	 else if (strcasecmp(str, "ips2")) {
1318 	} else if (strcasecmp(str, "ips2")) {
1319 	} else if (strcasecmp(str, "ips3")) {
1320 	} else if (strcasecmp(str, "ips4")) {
1321 	} else if (strcasecmp(str, "hard-float")) {
1322 	} else if (strcasecmp(str, "soft-float")) {
1323 	} else if (strcasecmp(str, "abi=32")) {
1324 		nargregs = MIPS_O32_NARGREGS;
1325 	} else if (strcasecmp(str, "abi=n32")) {
1326 		nargregs = MIPS_N32_NARGREGS;
1327 	} else if (strcasecmp(str, "abi=64")) {
1328 		nargregs = MIPS_N32_NARGREGS;
1329 	}
1330 #endif
1331 }
1332 /*
1333  * Do something target-dependent for xasm arguments.
1334  * Supposed to find target-specific constraints and rewrite them.
1335  */
1336 int
myxasm(struct interpass * ip,NODE * p)1337 myxasm(struct interpass *ip, NODE *p)
1338 {
1339 	return 0;
1340 }
1341