source: mainline/uspace/app/pcc/arch/powerpc/local2.c@ 5974661

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5974661 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

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