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@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
deltest(NODE * p)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
autoincr(NODE * p)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
notoff(TWORD t,int r,CONSZ off,char * cp)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
offstar(NODE * p,int shape)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
shumul(NODE * p,int shape)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
setincr(NODE * p)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
setbin(NODE * p)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
setasg(NODE * p,int cookie)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
setuni(NODE * p,int cookie)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 *
nspecial(struct optab * q)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
gencall(NODE * p,NODE * prev)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
storearg(NODE * p)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
mktailopt(struct interpass * ip1,struct interpass * ip2)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 *
livecall(NODE * p)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
acceptable(struct optab * op)619 acceptable(struct optab *op)
620 {
621 return 1;
622 }
623