* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / m16c / local2.c
bloba47a7720e729b65395d4c5c4f597c32156a50246
1 /* $Id: local2.c,v 1.40 2008/11/22 16:12:24 ragge Exp $ */
2 /*
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
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
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.
30 # include "pass2.h"
31 # include <ctype.h>
33 void acon(NODE *p);
34 int argsize(NODE *p);
35 void genargs(NODE *p);
37 static int ftlab1, ftlab2;
39 void
40 deflab(int label)
42 printf(LABFMT ":\n", label);
45 static TWORD ftype;
46 static int addto;
48 void
49 prologue(struct interpass_prolog *ipp)
51 ftype = ipp->ipp_type;
53 #if 0
54 if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR)
55 comperr("fix prologue register savings", ipp->ipp_regs);
56 #endif
58 printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n");
59 if (ipp->ipp_vis)
60 printf(" PUBLIC %s\n", ipp->ipp_name);
61 printf("%s:\n", ipp->ipp_name);
63 #if 0
64 if (xsaveip) {
65 /* Optimizer running, save space on stack */
66 addto = (p2maxautooff - AUTOINIT)/SZCHAR;
67 printf(" enter #%d\n", addto);
68 } else {
69 #endif
71 /* non-optimized code, jump to epilogue for code generation */
72 ftlab1 = getlab2();
73 ftlab2 = getlab2();
74 printf(" jmp.w " LABFMT "\n", ftlab1);
75 deflab(ftlab2);
79 * End of block.
81 void
82 eoftn(struct interpass_prolog *ipp)
84 #if 0
85 if (ipp->ipp_regs != MINRVAR)
86 comperr("fix eoftn register savings %x", ipp->ipp_regs);
87 #endif
89 // if (xsaveip == 0)
90 addto = (p2maxautooff - AUTOINIT)/SZCHAR;
92 /* return from function code */
93 //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary?
95 /* If retval is a pointer and not a function pointer, put in A0 */
96 if (ISPTR(DECREF(ipp->ipp_type)) &&
97 !ISFTN(DECREF(DECREF(ipp->ipp_type))))
98 printf(" mov.w r0,a0\n");
100 /* struct return needs special treatment */
101 if (ftype == STRTY || ftype == UNIONTY) {
102 comperr("fix struct return in eoftn");
103 } else
104 printf(" exitd\n");
106 /* Prolog code */
107 // if (xsaveip == 0) {
108 deflab(ftlab1);
109 printf(" enter #%d\n", addto);
110 printf(" jmp.w " LABFMT "\n", ftlab2);
115 * add/sub/...
117 * Param given:
119 void
120 hopcode(int f, int o)
122 char *str;
124 switch (o) {
125 case PLUS:
126 str = "add";
127 break;
128 case MINUS:
129 str = "sub";
130 break;
131 case AND:
132 str = "and";
133 break;
134 case OR:
135 str = "or";
136 break;
137 case ER:
138 str = "xor";
139 break;
140 default:
141 comperr("hopcode2: %d", o);
142 str = 0; /* XXX gcc */
144 printf("%s.%c", str, f);
147 char *
148 rnames[] = { /* keyed to register number tokens */
149 "r0", "r2", "r1", "r3", "a0", "a1", "fb", "sp", "r0h", "r0l",
150 "r1h", "r1l",
154 * Return the size (in bytes) of some types.
157 tlen(p) NODE *p;
159 switch(p->n_type) {
160 case CHAR:
161 case UCHAR:
162 return(1);
164 case INT:
165 case UNSIGNED:
166 case FLOAT:
167 return 2;
169 case DOUBLE:
170 case LONG:
171 case ULONG:
172 return 4;
174 default:
175 if (!ISPTR(p->n_type))
176 comperr("tlen type %d not pointer");
177 return SZPOINT(p->n_type)/SZCHAR;
182 * Emit code to compare two longlong numbers.
184 static void
185 twollcomp(NODE *p)
187 int o = p->n_op;
188 int s = getlab2();
189 int e = p->n_label;
190 int cb1, cb2;
192 if (o >= ULE)
193 o -= (ULE-LE);
194 switch (o) {
195 case NE:
196 cb1 = 0;
197 cb2 = NE;
198 break;
199 case EQ:
200 cb1 = NE;
201 cb2 = 0;
202 break;
203 case LE:
204 case LT:
205 cb1 = GT;
206 cb2 = LT;
207 break;
208 case GE:
209 case GT:
210 cb1 = LT;
211 cb2 = GT;
212 break;
214 default:
215 cb1 = cb2 = 0; /* XXX gcc */
217 if (p->n_op >= ULE)
218 cb1 += 4, cb2 += 4;
219 expand(p, 0, " cmp.w UR,UL\n");
220 if (cb1) cbgen(cb1, s);
221 if (cb2) cbgen(cb2, e);
222 expand(p, 0, " cmp.w AR,AL\n");
223 cbgen(p->n_op, e);
224 deflab(s);
228 void
229 zzzcode(NODE *p, int c)
231 NODE *l;
233 switch (c) {
234 case 'A': /* print negative shift constant */
235 p = getlr(p, 'R');
236 if (p->n_op != ICON)
237 comperr("ZA bad use");
238 p->n_lval = -p->n_lval;
239 adrput(stdout, p);
240 p->n_lval = -p->n_lval;
241 break;
243 case 'B':
244 if (p->n_rval)
245 printf(" add.b #%d,%s\n",
246 p->n_rval, rnames[STKREG]);
247 break;
249 case 'C': /* Print label address */
250 p = p->n_left;
251 if (p->n_lval)
252 printf(LABFMT, (int)p->n_lval);
253 else
254 printf("%s", p->n_name);
255 break;
257 case 'D': /* copy function pointers */
258 l = p->n_left;
259 printf("\tmov.w #HWRD(%s),%s\n\tmov.w #LWRD(%s),%s\n",
260 p->n_right->n_name, rnames[l->n_rval+1],
261 p->n_right->n_name, rnames[l->n_rval]);
262 break;
264 case 'E': /* double-reg printout */
265 /* XXX - always r0r2 here */
266 printf("%s%s", rnames[R0], rnames[R2]);
267 break;
269 case 'F': /* long comparisions */
270 twollcomp(p);
271 break;
273 case 'G':
274 printf("R0R2");
275 break;
277 case 'H': /* push 32-bit address (for functions) */
278 printf("\tpush.w #HWRD(%s)\n\tpush.w #LWRD(%s)\n",
279 p->n_left->n_name, p->n_left->n_name);
280 break;
282 case 'I': /* push 32-bit address (for functions) */
283 l = p->n_left;
284 printf("\tpush.w %d[%s]\n\tpush.w %d[%s]\n",
285 (int)l->n_lval, rnames[l->n_rval],
286 (int)l->n_lval+2, rnames[l->n_rval]);
287 break;
289 default:
290 comperr("bad zzzcode %c", c);
294 /*ARGSUSED*/
296 rewfld(NODE *p)
298 return(1);
301 int canaddr(NODE *);
303 canaddr(NODE *p)
305 int o = p->n_op;
307 if (o==NAME || o==REG || o==ICON || o==OREG ||
308 (o==UMUL && shumul(p->n_left, SOREG) == SRDIR))
309 return(1);
310 return(0);
314 fldexpand(NODE *p, int cookie, char **cp)
316 return 0;
320 * Does the bitfield shape match?
323 flshape(NODE *p)
325 int o = p->n_op;
327 if (o == OREG || o == REG || o == NAME)
328 return SRDIR; /* Direct match */
329 if (o == UMUL && shumul(p->n_left, SOREG))
330 return SROREG; /* Convert into oreg */
331 return SRREG; /* put it into a register */
334 /* INTEMP shapes must not contain any temporary registers */
335 /* XXX should this go away now? */
337 shtemp(NODE *p)
339 return 0;
342 void
343 adrcon(CONSZ val)
345 printf("$" CONFMT, val);
348 void
349 conput(FILE *fp, NODE *p)
351 int val = p->n_lval;
353 switch (p->n_op) {
354 case ICON:
355 if (p->n_name[0] != '\0') {
356 fprintf(fp, "%s", p->n_name);
357 if (val)
358 fprintf(fp, "+%d", val);
359 } else
360 fprintf(fp, "%d", val);
361 return;
363 default:
364 comperr("illegal conput");
368 /*ARGSUSED*/
369 void
370 insput(NODE *p)
372 comperr("insput");
376 * Write out the upper address, like the upper register of a 2-register
377 * reference, or the next memory location.
379 void
380 upput(NODE *p, int size)
383 size /= SZINT;
384 switch (p->n_op) {
385 case REG:
386 fputs(rnames[p->n_rval + 1], stdout);
387 break;
389 case NAME:
390 case OREG:
391 p->n_lval += size;
392 adrput(stdout, p);
393 p->n_lval -= size;
394 break;
395 case ICON:
396 fprintf(stdout, "#" CONFMT, p->n_lval >> 16);
397 break;
398 default:
399 comperr("upput bad op %d size %d", p->n_op, size);
403 void
404 adrput(FILE *io, NODE *p)
406 /* output an address, with offsets, from p */
408 if (p->n_op == FLD)
409 p = p->n_left;
411 switch (p->n_op) {
413 case NAME:
414 if (p->n_name[0] != '\0')
415 fputs(p->n_name, io);
416 if (p->n_lval != 0)
417 fprintf(io, "+" CONFMT, p->n_lval);
418 return;
420 case OREG:
421 if (p->n_lval)
422 fprintf(io, "%d", (int)p->n_lval);
423 fprintf(io, "[%s]", rnames[p->n_rval]);
424 return;
425 case ICON:
426 /* addressable value of the constant */
427 fputc('#', io);
428 conput(io, p);
429 return;
431 case REG:
432 /*if (DEUNSIGN(p->n_type) == CHAR) {
433 fprintf(io, "R%c%c", p->n_rval < 2 ? '0' : '1',
434 (p->n_rval & 1) ? 'H' : 'L');
435 } else*/
436 fprintf(io, "%s", rnames[p->n_rval]);
437 return;
439 default:
440 comperr("illegal address, op %d, node %p", p->n_op, p);
441 return;
446 static char *
447 ccbranches[] = {
448 "jeq", /* jumpe */
449 "jne", /* jumpn */
450 "jle", /* jumple */
451 "jlt", /* jumpl */
452 "jge", /* jumpge */
453 "jgt", /* jumpg */
454 "jleu", /* jumple (jlequ) */
455 "jltu", /* jumpl (jlssu) */
456 "jgeu", /* jumpge (jgequ) */
457 "jgtu", /* jumpg (jgtru) */
461 /* printf conditional and unconditional branches */
462 void
463 cbgen(int o, int lab)
465 if (o < EQ || o > UGT)
466 comperr("bad conditional branch: %s", opst[o]);
467 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
470 void
471 mycanon(NODE *p)
475 void
476 myoptim(struct interpass *ip)
480 #if 0
481 void
482 mygenregs(NODE *p)
485 if (p->n_op == MINUS && p->n_type == DOUBLE &&
486 (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) {
487 p->n_su |= DORIGHT;
489 /* Must walk down correct node first for logops to work */
490 if (p->n_op != CBRANCH)
491 return;
492 p = p->n_left;
493 if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG))
494 return;
495 p->n_su &= ~DORIGHT;
498 #endif
500 struct hardops hardops[] = {
501 { PLUS, FLOAT, "?F_ADD_L04" },
502 { MUL, LONG, "?L_MUL_L03" },
503 { MUL, ULONG, "?L_MUL_L03" },
504 { DIV, LONG, "?SL_DIV_L03" },
505 { DIV, ULONG, "?UL_DIV_L03" },
506 { MOD, LONG, "?SL_MOD_L03" },
507 { MOD, ULONG, "?UL_MOD_L03" },
508 { RS, LONGLONG, "__ashrdi3" },
509 { RS, ULONGLONG, "__lshrdi3" },
510 { LS, LONGLONG, "__ashldi3" },
511 { LS, ULONGLONG, "__ashldi3" },
512 { 0 },
516 special(NODE *p, int shape)
518 switch (shape) {
519 case SFTN:
520 if (ISPTR(p->n_type) && ISFTN(DECREF(p->n_type))) {
521 if (p->n_op == NAME || p->n_op == OREG)
522 return SRDIR;
523 else
524 return SRREG;
526 break;
528 return SRNOPE;
531 void
532 myreader(NODE *p)
534 NODE *q, *r, *s, *right;
536 if (optype(p->n_op) == LTYPE)
537 return;
538 if (optype(p->n_op) != UTYPE)
539 myreader(p->n_right);
540 myreader(p->n_left);
542 switch (p->n_op) {
543 case PLUS:
544 case MINUS:
545 if (p->n_type != LONG && p->n_type != ULONG)
546 break;
547 if (p->n_right->n_op == NAME || p->n_right->n_op == OREG)
548 break;
549 /* Must convert right into OREG */
550 right = p->n_right;
551 q = mklnode(OREG, BITOOR(freetemp(szty(right->n_type))),
552 FPREG, right->n_type);
553 s = mkbinode(ASSIGN, q, right, right->n_type);
554 r = talloc();
555 *r = *q;
556 p->n_right = r;
557 pass2_compile(ipnode(s));
558 break;
563 void
564 rmove(int s, int d, TWORD t)
566 switch (t) {
567 case CHAR:
568 case UCHAR:
569 printf(" mov.b %s,%s\n", rnames[s], rnames[d]);
570 break;
571 default:
572 printf(" mov.w %s,%s\n", rnames[s], rnames[d]);
577 * For class c, find worst-case displacement of the number of
578 * registers in the array r[] indexed by class.
581 COLORMAP(int c, int *r)
583 int num;
585 switch (c) {
586 case CLASSA:
587 num = r[CLASSA];
588 num += r[CLASSC];
589 return num < 4;
590 case CLASSB:
591 num = r[CLASSB];
592 return num < 2;
593 case CLASSC:
594 num = 2*r[CLASSA];
595 num += r[CLASSC];
596 return num < 4;
598 return 0; /* XXX gcc */
602 * Return a class suitable for a specific type.
605 gclass(TWORD t)
607 if (t == CHAR || t == UCHAR)
608 return CLASSC;
610 if(ISPTR(t))
611 return CLASSB;
613 return CLASSA;
616 static int sizen;
618 /* XXX: Fix this. */
619 static int
620 argsiz(NODE *p)
622 TWORD t = p->n_type;
624 if (t < LONGLONG || t > MAXTYPES)
625 return 4;
626 if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
627 return 8;
628 if (t == LDOUBLE)
629 return 12;
630 if (t == STRTY)
631 return p->n_stsize;
632 comperr("argsiz");
633 return 0;
637 * Calculate argument sizes.
638 * XXX: Fix this.
640 void
641 lastcall(NODE *p)
643 sizen = 0;
644 for (p = p->n_right; p->n_op == CM; p = p->n_left)
645 sizen += argsiz(p->n_right);
646 sizen += argsiz(p);
650 * Target-dependent command-line options.
652 void
653 mflags(char *str)
657 * Do something target-dependent for xasm arguments.
658 * Supposed to find target-specific constraints and rewrite them.
661 myxasm(struct interpass *ip, NODE *p)
663 return 0;