Home | History | Annotate | Line # | Download | only in m16c
      1 /*	Id: order.c,v 1.22 2014/06/01 11:35:02 ragge Exp 	*/
      2 /*	$NetBSD: order.c,v 1.1.1.4 2014/07/24 19:17:52 plunky Exp $	*/
      3 /*
      4  * Copyright (c) 2003 Anders Magnusson (ragge (at) 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 # include "pass2.h"
     32 # include <strings.h>
     33 
     34 int canaddr(NODE *);
     35 
     36 /*
     37  * should the assignment op p be stored,
     38  * given that it lies as the right operand of o
     39  * (or the left, if o==UNARY MUL)
     40  */
     41 /*
     42 void
     43 stoasg(NODE *p, int o)
     44 {
     45 	if (x2debug)
     46 		printf("stoasg(%p, %o)\n", p, o);
     47 }
     48 */
     49 /* should we delay the INCR or DECR operation p */
     50 int
     51 deltest(NODE *p)
     52 {
     53 	return 0;
     54 }
     55 
     56 /*
     57  * Check if p can be autoincremented.
     58  * XXX - nothing can be autoincremented for now.
     59  */
     60 int
     61 autoincr(NODE *p)
     62 {
     63 	return 0;
     64 }
     65 
     66 /* is it legal to make an OREG or NAME entry which has an
     67  * offset of off, (from a register of r), if the
     68  * resulting thing had type t */
     69 int
     70 notoff(TWORD t, int r, CONSZ off, char *cp)
     71 {
     72 	return(0);  /* YES */
     73 }
     74 
     75 /*
     76  * Turn a UMUL-referenced node into OREG.
     77  */
     78 int
     79 offstar(NODE *p, int shape)
     80 {
     81 	if (x2debug)
     82 		printf("offstar(%p)\n", p);
     83 
     84 	if( p->n_op == PLUS || p->n_op == MINUS ){
     85 		if( p->n_right->n_op == ICON ){
     86 			geninsn(p->n_left, INBREG);
     87 			p->n_su = -1;
     88 			return 1;
     89 		}
     90 	}
     91 	geninsn(p, INBREG);
     92 	return 0;
     93 }
     94 
     95 /*
     96  * Shape matches for UMUL.  Cooperates with offstar().
     97  */
     98 int
     99 shumul(NODE *p, int shape)
    100 {
    101 //	NODE *l = p->n_left;
    102 
    103 #ifdef PCC_DEBUG
    104 	if (x2debug) {
    105 		printf("shumul(%p)\n", p);
    106 		fwalk(p, e2print, 0);
    107 	}
    108 #endif
    109 	/* XXX - fix */
    110 
    111 	/* Can only generate OREG of BREGs (or FB) */
    112 	if (p->n_op == REG && (isbreg(p->n_rval) || p->n_rval == FB))
    113 		return SROREG;
    114 #if 0
    115 	if ((p->n_op == PLUS || p->n_op == MINUS) &&
    116 	    (l->n_op == REG && (isbreg(l->n_rval) || l->n_rval == FB)) &&
    117 	    p->n_right->n_op == ICON)
    118 		return SOREG;
    119 	return 0;
    120 #else
    121 	return SROREG;
    122 #endif
    123 }
    124 
    125 /*
    126  * Rewrite increment/decrement operation.
    127  */
    128 int
    129 setincr(NODE *p)
    130 {
    131 	if (x2debug)
    132 		printf("setincr(%p)\n", p);
    133 
    134 	return(0);
    135 }
    136 
    137 /*
    138  * Rewrite operations on binary operators (like +, -, etc...).
    139  * Called as a result of table lookup.
    140  */
    141 int
    142 setbin(NODE *p)
    143 {
    144 
    145 	if (x2debug)
    146 		printf("setbin(%p)\n", p);
    147 	return 0;
    148 
    149 }
    150 
    151 /* setup for assignment operator */
    152 int
    153 setasg(NODE *p, int cookie)
    154 {
    155 	if (x2debug)
    156 		printf("setasg(%p)\n", p);
    157 	return(0);
    158 }
    159 
    160 /* setup for unary operator */
    161 int
    162 setuni(NODE *p, int cookie)
    163 {
    164 	return 0;
    165 }
    166 
    167 #if 0
    168 /*
    169  * register allocation for instructions with special preferences.
    170  */
    171 regcode
    172 regalloc(NODE *p, struct optab *q, int wantreg)
    173 {
    174 	regcode regc;
    175 
    176 	if (q->op == DIV || q->op == MOD) {
    177 		/*
    178 		 * 16-bit div.
    179 		 */
    180 		if (regblk[R0] & 1 || regblk[R2] & 1)
    181 			comperr("regalloc: needed regs inuse, node %p", p);
    182 		if (p->n_su & DORIGHT) {
    183 			regc = alloregs(p->n_right, A0);
    184 			if (REGNUM(regc) != A0) {
    185 				p->n_right = movenode(p->n_right, A0);
    186 				if ((p->n_su & RMASK) == ROREG) {
    187 					p->n_su &= ~RMASK;
    188 					p->n_su |= RREG;
    189 					p->n_right->n_su &= ~LMASK;
    190 					p->n_right->n_su |= LOREG;
    191 				}
    192 				freeregs(regc);
    193 				regblk[A0] |= 1;
    194 			}
    195 		}
    196 		regc = alloregs(p->n_left, R0);
    197 		if (REGNUM(regc) != R0) {
    198 			p->n_left = movenode(p->n_left, R0);
    199 			freeregs(regc);
    200 			regblk[R0] |= 1;
    201 		}
    202 		if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
    203 			regc = alloregs(p->n_right, A0);
    204 			if (REGNUM(regc) != A0) {
    205 				p->n_right = movenode(p->n_right, A0);
    206 				if ((p->n_su & RMASK) == ROREG) {
    207 					p->n_su &= ~RMASK;
    208 					p->n_su |= RREG;
    209 					p->n_right->n_su &= ~LMASK;
    210 					p->n_right->n_su |= LOREG;
    211 				}
    212 			}
    213 		}
    214 		regblk[A0] &= ~1;
    215 		regblk[R0] &= ~1;
    216 		regblk[R2] &= ~1;
    217 		if (q->op == DIV) {
    218 			MKREGC(regc, R0, 1);
    219 			regblk[R0] |= 1;
    220 		} else {
    221 			MKREGC(regc, R2, 1);
    222 			regblk[R2] |= 1;
    223 		}
    224 	} else
    225 		comperr("regalloc");
    226 	p->n_rall = REGNUM(regc);
    227 	return regc;
    228 }
    229 #endif
    230 
    231 /*
    232  * Special handling of some instruction register allocation.
    233  * - left is the register that left node wants.
    234  * - right is the register that right node wants.
    235  * - res is in which register the result will end up.
    236  * - mask is registers that will be clobbered.
    237  *
    238  *  XXX - Fix this function
    239  */
    240 struct rspecial *
    241 nspecial(struct optab *q)
    242 {
    243     switch (q->op) {
    244 
    245     case DIV:
    246     case MOD:
    247 	if(q->ltype & (TINT|TSHORT)){
    248 	    static struct rspecial s[] = {
    249 		{ NRES, R0 }, { NRES, R2}, { 0 } };
    250 	    return s;
    251 	}
    252 	/*
    253 	else if(q->ltype & TCHAR) {
    254 	    static struct rspecial s[] = {
    255 		{ NRES, R0L }, { NRES, R0H}, { 0 } };
    256 	    return s;
    257 	    }*/
    258 	break;
    259 
    260     case MUL:
    261 	/*
    262 	if(q->ltype & (TINT|TSHORT)){
    263 	    static struct rspecial s[] = {
    264 		{ NRES, R0 }, { NRES, R2}, { 0 } };
    265 	    return s;
    266 	    }*/
    267 	comperr("multiplication not implemented");
    268 	break;
    269 
    270     default:
    271 	break;
    272     }
    273     comperr("nspecial entry %d", q - table);
    274     return 0; /* XXX gcc */
    275 }
    276 
    277 
    278 /*
    279  * Splitup a function call and give away its arguments first.
    280  * Calling convention used ("normal" in IAR syntax) is:
    281  * - 1-byte parameters in R0L if possible, otherwise in R0H.
    282  * - 2-byte pointers in A0.
    283  * - 2-byte non-pointers in R0 if no byte-size arguments are found in
    284  *   in the first 6 bytes of parameters, otherwise R2 or at last A0.
    285  * - 4-byte parameters in R2R0.
    286  */
    287 void
    288 gencall(NODE *p, NODE *prev)
    289 {
    290 	NODE *n = 0; /* XXX gcc */
    291 	static int storearg(NODE *);
    292 	int o = p->n_op;
    293 	int ty = optype(o);
    294 
    295 	if (ty == LTYPE)
    296 		return;
    297 
    298 	switch (o) {
    299 	case CALL:
    300 		/* swap arguments on some hardop-converted insns */
    301 		/* Normal call, just push args and be done with it */
    302 		p->n_op = UCALL;
    303 //printf("call\n");
    304 		/* Check if left can be evaluated directly */
    305 		if (p->n_left->n_op == UMUL) {
    306 			TWORD t = p->n_left->n_type;
    307 			int k = (freetemp(szty(t)));
    308 			NODE *n = mklnode(OREG, k, FB, t);
    309 			NODE *q = tcopy(n);
    310 			pass2_compile(ipnode(mkbinode(ASSIGN, n, p->n_left,t)));
    311 			p->n_left = q;
    312 		}
    313 		gencall(p->n_left, p);
    314 		p->n_rval = storearg(p->n_right);
    315 //printf("end call\n");
    316 		break;
    317 
    318 	case UFORTCALL:
    319 	case FORTCALL:
    320 		comperr("FORTCALL");
    321 
    322 	case USTCALL:
    323 	case STCALL:
    324 		/*
    325 		 * Structure return.  Look at the node above
    326 		 * to decide about buffer address:
    327 		 * - FUNARG, allocate space on stack, don't remove.
    328 		 * - nothing, allocate space on stack and remove.
    329 		 * - STASG, get the address of the left side as arg.
    330 		 * - FORCE, this ends up in a return, get supplied addr.
    331 		 * (this is not pretty, but what to do?)
    332 		 */
    333 		if (prev == NULL || prev->n_op == FUNARG) {
    334 			/* Create nodes to generate stack space */
    335 			n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT),
    336 			    mkbinode(MINUS, mklnode(REG, 0, STKREG, INT),
    337 			    mklnode(ICON, p->n_stsize, 0, INT), INT), INT);
    338 //printf("stsize %d\n", p->n_stsize);
    339 			pass2_compile(ipnode(n));
    340 		} else if (prev->n_op == STASG) {
    341 			n = prev->n_left;
    342 			if (n->n_op == UMUL)
    343 				n = nfree(n);
    344 			else if (n->n_op == NAME) {
    345 				n->n_op = ICON; /* Constant reference */
    346 				n->n_type = INCREF(n->n_type);
    347 			} else
    348 				comperr("gencall stasg");
    349 		} else if (prev->n_op == FORCE) {
    350 			; /* do nothing here */
    351 		} else {
    352 			comperr("gencall bad op %d", prev->n_op);
    353 		}
    354 
    355 		/* Deal with standard arguments */
    356 		gencall(p->n_left, p);
    357 		if (o == STCALL) {
    358 			p->n_op = USTCALL;
    359 			p->n_rval = storearg(p->n_right);
    360 		} else
    361 			p->n_rval = 0;
    362 		/* push return struct address */
    363 		if (prev == NULL || prev->n_op == FUNARG) {
    364 			n = mklnode(REG, 0, STKREG, INT);
    365 			if (p->n_rval)
    366 				n = mkbinode(PLUS, n,
    367 				    mklnode(ICON, p->n_rval, 0, INT), INT);
    368 			pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
    369 			if (prev == NULL)
    370 				p->n_rval += p->n_stsize/4;
    371 		} else if (prev->n_op == FORCE) {
    372 			/* return value for this function */
    373 			n = mklnode(OREG, 8, FPREG, INT);
    374 			pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
    375 			p->n_rval++;
    376 		} else {
    377 			pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
    378 			n = p;
    379 			*prev = *p;
    380 			nfree(n);
    381 		}
    382 //printf("end stcall\n");
    383 		break;
    384 
    385 	default:
    386 		if (ty != UTYPE)
    387 			gencall(p->n_right, p);
    388 		gencall(p->n_left, p);
    389 		break;
    390 	}
    391 }
    392 
    393 /*
    394  * Create separate node trees for function arguments.
    395  * This is partly ticky, the strange calling convention
    396  * may cause a bunch of code reorganization here.
    397  */
    398 static int
    399 storearg(NODE *p)
    400 {
    401 	NODE *n, *q, **narry;
    402 	int nch, k, i, nn, rary[4];
    403 	int r0l, r0h, r2, a0, stk, sz;
    404 	TWORD t;
    405 	int maxrargs = 0;
    406 
    407 	if (p->n_op == CM)
    408 		maxrargs = p->n_stalign;
    409 
    410 	/* count the arguments */
    411 	for (i = 1, q = p; q->n_op == CM; q = q->n_left)
    412 		i++;
    413 	nn = i;
    414 
    415 	/* allocate array to store arguments */
    416 	narry = tmpalloc(sizeof(NODE *)*nn);
    417 
    418 	/* enter nodes into array */
    419 	for (q = p; q->n_op == CM; q = q->n_left)
    420 		narry[--i] = q->n_right;
    421 	narry[--i] = q;
    422 
    423 	/* free CM nodes */
    424 	for (q = p; q->n_op == CM; ) {
    425 		n = q->n_left;
    426 		nfree(q);
    427 		q = n;
    428 	}
    429 
    430 	/* count char args */
    431 	r0l = r0h = r2 = a0 = 0;
    432 	for (sz = nch = i = 0; i < nn && i < 6; i++) {
    433 		TWORD t = narry[i]->n_type;
    434 		if (sz >= 6)
    435 			break;
    436 		if (t == CHAR || t == UCHAR) {
    437 			nch++;
    438 			sz++;
    439 		} else if ((t >= SHORT && t <= UNSIGNED) ||
    440 		    t > BTMASK || t == FLOAT) {
    441 			sz += 2;
    442 		} else /* long, double */
    443 			sz += 4;
    444 
    445 	}
    446 
    447 	/*
    448 	 * Now the tricky part. The parameters that should be on stack
    449 	 * must be found and pushed first, then the register parameters.
    450 	 * For the latter, be sure that evaluating them do not use any
    451 	 * registers where argument values already are inserted.
    452 	 * XXX - function pointers?
    453 	 * XXX foo(long a, char b) ???
    454 	 */
    455 	for (stk = 0; stk < 4; stk++) {
    456 		TWORD t;
    457 
    458 		if (stk == nn)
    459 			break;
    460 		t = narry[stk]->n_type;
    461 		if (ISFTN(DECREF(t)))
    462 			t = LONG;
    463 		switch (t) {
    464 		case CHAR: case UCHAR:
    465 			if (r0l) {
    466 				if (r0h)
    467 					break;
    468 				rary[stk] = R2; /* char talk for 'R0H' */
    469 				r0h = 1;
    470 			} else {
    471 				rary[stk] = R0;
    472 				r0l = 1;
    473 			}
    474 			continue;
    475 
    476 		case INT: case UNSIGNED:
    477 			if (r0l || nch) {
    478 				if (r2) {
    479 					if (a0)
    480 						break;
    481 					rary[stk] = A0;
    482 					a0 = 1;
    483 				} else {
    484 					rary[stk] = R2;
    485 					r2 = 1;
    486 				}
    487 			} else {
    488 				rary[stk] = R0;
    489 				r0l = r0h = 1;
    490 			}
    491 			continue;
    492 
    493 		case LONG: case ULONG:
    494 			if (r0l || r2)
    495 				break;
    496 			rary[stk] = R0;
    497 			r0l = r0h = r2 = 1;
    498 			continue;
    499 
    500 		default:
    501 			if (ISPTR(narry[stk]->n_type) &&
    502 			    !ISFTN(DECREF(narry[stk]->n_type))) {
    503 				if (a0) {
    504 					if (r0l || nch) {
    505 						if (r2)
    506 							break;
    507 						rary[stk] = R2;
    508 						r2 = 1;
    509 					} else {
    510 						rary[stk] = R0;
    511 						r0l = r0h = 1;
    512 					}
    513 				} else {
    514 					rary[stk] = A0;
    515 					a0 = 1;
    516 				}
    517 				continue;
    518 			}
    519 			break;
    520 		}
    521 		break;
    522 	}
    523 
    524 	/*
    525 	 * The arguments that must be on stack are stk->nn args.
    526 	 * Argument 0->stk-1 should be put in the rary[] register.
    527 	 */
    528 	for (sz = 0, i = nn-1; i >= stk; i--) { /* first stack args */
    529 		NODE nod;
    530 		pass2_compile(ipnode(mkunode(FUNARG,
    531 		    narry[i], 0, narry[i]->n_type)));
    532 		nod.n_type = narry[i]->n_type;
    533 		sz += tlen(&nod);
    534 	}
    535 	/* if param cannot be addressed directly, evaluate and put on stack */
    536 	for (i = 0; i < stk; i++) {
    537 
    538 		if (canaddr(narry[i]))
    539 			continue;
    540 		t = narry[i]->n_type;
    541 		k = (freetemp(szty(t)));
    542 		n = mklnode(OREG, k, FB, t);
    543 		q = tcopy(n);
    544 		pass2_compile(ipnode(mkbinode(ASSIGN, n, narry[i], t)));
    545 		narry[i] = q;
    546 	}
    547 	/* move args to registers */
    548 	for (i = 0; i < stk; i++) {
    549 		t = narry[i]->n_type;
    550 		pass2_compile(ipnode(mkbinode(ASSIGN,
    551 		    mklnode(REG, 0, rary[i], t), narry[i], t)));
    552 	}
    553 	return sz;
    554 }
    555 
    556 /*
    557  * Tell if a register can hold a specific datatype.
    558  */
    559 #if 0
    560 int
    561 mayuse(int reg, TWORD type)
    562 {
    563 	return 1;  /* Everything is OK */
    564 }
    565 #endif
    566 
    567 #ifdef TAILCALL
    568 void
    569 mktailopt(struct interpass *ip1, struct interpass *ip2)
    570 {
    571 	extern int earlylab;
    572 	extern char *cftname;
    573 	char *fn;
    574 	NODE *p;
    575 
    576 	p = ip1->ip_node->n_left->n_left;
    577 	if (p->n_op == ICON) {
    578 		fn = p->n_name;
    579 		/* calling ourselves */
    580 		p = ip1->ip_node->n_left;
    581 		if (p->n_op == CALL) {
    582 			if (storearg(p->n_right))
    583 				comperr("too many args: fix mktailopt");
    584 			p->n_op = UCALL;
    585 		}
    586 		tfree(ip1->ip_node);
    587 		p = ip2->ip_node->n_left;
    588 		if (strcmp(fn, cftname)) {
    589 			/* Not us, must generate fake prologue */
    590 			ip1->type = IP_ASM;
    591 			ip1->ip_asm = "\tmov.w FB,SP\n\tpop.w FB\n";
    592 			pass2_compile(ip1);
    593 			p->n_lval = p->n_rval = 0;
    594 			p->n_name = fn;
    595 		} else
    596 			p->n_lval = earlylab;
    597 	} else {
    598 		pass2_compile(ip1);
    599 	}
    600 	pass2_compile(ip2);
    601 }
    602 #endif
    603 /*
    604  * Set registers "live" at function calls (like arguments in registers).
    605  * This is for liveness analysis of registers.
    606  */
    607 int *
    608 livecall(NODE *p)
    609 {
    610 	static int r[1] = { -1 }; /* Terminate with -1 */
    611 
    612 	return &r[0];
    613 }
    614 
    615 /*
    616  * Signal whether the instruction is acceptable for this target.
    617  */
    618 int
    619 acceptable(struct optab *op)
    620 {
    621 	return 1;
    622 }
    623