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