Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140529192002

Diff

Diff from 1.21 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/m16c/order.c

Annotated File View

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