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