Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20071116001740

Diff

Diff from 1.3 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/mips/local.c

Annotated File View

gmcgarry
1.3
1 /*      $Id: local.c,v 1.3 2007/11/16 00:17:40 gmcgarry Exp $   */
ragge
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  * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
31  * Simon Olsson (simols-1@student.ltu.se) 2005.
32  */
33
gmcgarry
1.3
34 #include "pass1.h"
ragge
1.1
35
gmcgarry
1.2
36 static int inbitsinval;
37
gmcgarry
1.3
38 #ifdef MIPS_BIGENDIAN
39 /*
40  * If we're big endian, then all OREG loads of a type
41  * larger than the destination, must have the
42  * offset changed to point to the correct bytes in memory.
43  */
44 static NODE *
45 offchg(NODE *p)
gmcgarry
1.2
46 {
gmcgarry
1.3
47         NODE *l = p->n_left;
gmcgarry
1.2
48
gmcgarry
1.3
49         if (p->n_op != SCONV)
50                 return;
gmcgarry
1.2
51
gmcgarry
1.3
52         switch (l->n_type) {
53         case SHORT:
54         case USHORT:
55                 if (DEUNSIGN(p->n_type) == CHAR)
56                         l->n_lval += 1;
57                 break;
58         case LONG:
59         case ULONG:
60         case INT:
61         case UNSIGNED:
62                 if (DEUNSIGN(p->n_type) == CHAR)
63                         l->n_lval += 3;
64                 else if (DEUNSIGNED(p->n_type) == SHORT)
65                         l->n_lval += 2;
66                 break;
67         case LONGLONG:
68         case ULONGLONG:
69                 if (DEUNSIGN(p->n_type) == CHAR)
70                         l->n_lval += 7;
71                 else if (DEUNSIGNED(p->n_type) == SHORT)
72                         l->n_lval += 6;
73                 else if (DEUNSIGN(p->n_type) == INT ||
74                     DEUNSIGN(p->n_type) == LONG)
75                         p->n_lval += 4;
76         default:
77                 comperr("offchg: unknown type");
78                 break;
79         }
gmcgarry
1.2
80
gmcgarry
1.3
81         return p;
gmcgarry
1.2
82 }
gmcgarry
1.3
83 #endif
gmcgarry
1.2
84
gmcgarry
1.3
85 /* this is called to do local transformations on
86  * an expression tree preparitory to its being
87  * written out in intermediate code.
88  */
ragge
1.1
89 NODE *
90 clocal(NODE *p)
91 {
gmcgarry
1.3
92         struct symtab *q;
93         NODE *r, *l;
94         int o;
95         int mml;
ragge
1.1
96         TWORD t;
97
98 //printf("in:\n");
99 //fwalk(p, eprint, 0);
gmcgarry
1.3
100
ragge
1.1
101         switcho = p->n_op ){
102
103         case NAME:
104                 if ((q = p->n_sp) == NULL)
105                         return p/* Nothing to care about */
106
107                 switch (q->sclass) {
108
109                 case PARAM:
110                 case AUTO:
111                         /* fake up a structure reference */
112                         r = block(REGNILNILPTR+STRTY00);
113                         r->n_lval = 0;
gmcgarry
1.3
114                         r->n_rval = FP;
ragge
1.1
115                         p = stref(block(STREFrp000));
116                         break;
117
118                 case STATIC:
119                         if (q->slevel == 0)
120                                 break;
121                         p->n_lval = 0;
122                         p->n_sp = q;
123                         break;
124
125                 case REGISTER:
126                         p->n_op = REG;
127                         p->n_lval = 0;
128                         p->n_rval = q->soffset;
129                         break;
130
131                         }
132                 break;
133
134         case FUNARG:
135                 /* Args smaller than int are given as int */
136                 if (p->n_type != CHAR && p->n_type != UCHAR && 
137                     p->n_type != SHORT && p->n_type != USHORT)
138                         break;
139                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
140                 p->n_type = INT;
141                 p->n_sue = MKSUE(INT);
142                 p->n_rval = SZINT;
143                 break;
144
145         case CBRANCH:
146                 l = p->n_left;
147
148                 /*
149                  * Remove unneccessary conversion ops.
150                  */
151                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
152                         if (coptype(l->n_op) != BITYPE)
153                                 break;
154                         if (l->n_right->n_op == ICON) {
155                                 r = l->n_left->n_left;
156                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
157                                         break;
158                                 /* Type must be correct */
159                                 t = r->n_type;
160                                 nfree(l->n_left);
161                                 l->n_left = r;
162                                 l->n_type = t;
163                                 l->n_right->n_type = t;
164                         }
165 #if 0
166                           else if (l->n_right->n_op == SCONV &&
167                             l->n_left->n_type == l->n_right->n_type) {
168                                 r = l->n_left->n_left;
169                                 nfree(l->n_left);
170                                 l->n_left = r;
171                                 r = l->n_right->n_left;
172                                 nfree(l->n_right);
173                                 l->n_right = r;
174                         }
175 #endif
176                 }
177                 break;
178
179         case PCONV:
180                 ml = p->n_left->n_type;
181                 l = p->n_left;
182                 if ((ml == CHAR || ml == UCHAR || ml == SHORT || ml == USHORT)
183                     && l->n_op != ICON)
184                         break;
185                 l->n_type = p->n_type;
186                 l->n_qual = p->n_qual;
187                 l->n_df = p->n_df;
188                 l->n_sue = p->n_sue;
189                 nfree(p);
190                 p = l;
191                 break;
192
193         case SCONV:
194                 l = p->n_left;
195
196                 if (p->n_type == l->n_type) {
197                         nfree(p);
198                         return l;
199                 }
200
gmcgarry
1.3
201 #ifdef MIPS_BIGENDIAN
202                 /*
203                  * If we're big endian, then all OREG loads of a type
204                  * larger than the destination, must have the
205                  * offset changed to point to the correct bytes in memory.
206                  */
207                 if (l->n_type == OREG
208                         p = offchg(p);
209 #endif
210
ragge
1.1
211                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
212                     btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
213                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
214                             l->n_type != FLOAT && l->n_type != DOUBLE &&
215                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
216                                 if (l->n_op == NAME || l->n_op == UMUL) {
217                                         l->n_type = p->n_type;
218                                         nfree(p);
219                                         return l;
220                                 }
221                         }
222                 }
223
224                 if ((p->n_type == INT || p->n_type == UNSIGNED) &&
225                     ISPTR(l->n_type)) {
226                         nfree(p);
227                         return l;
228                 }
229
230                 o = l->n_op;
231                 m = p->n_type;
232
233                 if (o == ICON) {
234                         CONSZ val = l->n_lval;
235
236                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
237                             switch (m) {
238                         case CHAR:
239                                 l->n_lval = (char)val;
240                                 break;
241                         case UCHAR:
242                                 l->n_lval = val & 0377;
243                                 break;
244                         case SHORT:
245                                 l->n_lval = (short)val;
246                                 break;
247                         case USHORT:
248                                 l->n_lval = val & 0177777;
249                                 break;
250                         case ULONG:
251                         case UNSIGNED:
252                                 l->n_lval = val & 0xffffffff;
253                                 break;
254                         case ENUMTY:
255                         case MOETY:
256                         case LONG:
257                         case INT:
258                                 l->n_lval = (int)val;
259                                 break;
260                         case LONGLONG:
261                                 l->n_lval = (long long)val;
262                                 break;
263                         case ULONGLONG:
264                                 l->n_lval = val;
265                                 break;
266                         case VOID:
267                                 break;
268                         case LDOUBLE:
269                         case DOUBLE:
270                         case FLOAT:
271                                 l->n_op = FCON;
272                                 l->n_dcon = val;
273                                 break;
274                         default:
275                                 cerror("unknown type %d"m);
276                         }
277                         l->n_type = m;
278                         nfree(p);
279                         return l;
280                 }
281                 if (DEUNSIGN(p->n_type) == SHORT &&
282                     DEUNSIGN(l->n_type) == SHORT) {
283                         nfree(p);
284                         p = l;
285                 }
286                 break;
287
288         case MOD:
289         case DIV:
290                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
291                         break;
292                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
293                         break;
294                 /* make it an int division by inserting conversions */
295                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
296                 p->n_right = block(SCONVp->n_rightNILINT0MKSUE(INT));
297                 p = block(SCONVpNILp->n_type0MKSUE(p->n_type));
298                 p->n_left->n_type = INT;
299                 break;
300
301         case PMCONV:
302         case PVCONV:
303                 ifp->n_right->n_op != ICON ) cerror"bad conversion"0);
304                 nfree(p);
305                 return(buildtree(o==PMCONV?MUL:DIVp->n_leftp->n_right));
306
307         case FORCE:
308                 /* put return value in return reg */
309                 p->n_op = ASSIGN;
310                 p->n_right = p->n_left;
gmcgarry
1.2
311                 p->n_left = block(REGNILNILp->n_type0MKSUE(INT));
gmcgarry
1.3
312                 p->n_left->n_rval = RETREG(p->n_type);
ragge
1.1
313                 break;
314         }
gmcgarry
1.3
315
ragge
1.1
316 //printf("ut:\n");
317 //fwalk(p, eprint, 0);
318
319         return(p);
320 }
321
322 void
323 myp2tree(NODE *p)
324 {
325 }
326
327 /*ARGSUSED*/
328 int
329 andable(NODE *p)
330 {
331         return(1);  /* all names can have & taken on them */
332 }
333
334 /*
335  * at the end of the arguments of a ftn, set the automatic offset
336  */
337 void
338 cendarg()
339 {
340         autooff = AUTOINIT;
341 }
342
343 /*
344  * is an automatic variable of type t OK for a register variable
345  */
346 int
347 cisreg(TWORD t)
348 {
349         if (t == INT || t == UNSIGNED || t == LONG || t == ULONG)
350                 return(1);
351         return 0/* XXX - fix reg assignment in pftn.c */
352 }
353
354 /*
355  * return a node, for structure references, which is suitable for
356  * being added to a pointer of type t, in order to be off bits offset
357  * into a structure
358  * t, d, and s are the type, dimension offset, and sizeoffset
359  * Be careful about only handling first-level pointers, the following
360  * indirections must be fullword.
361  */
362 NODE *
363 offcon(OFFSZ offTWORD tunion dimfun *dstruct suedef *sue)
364 {
gmcgarry
1.3
365         NODE *p;
ragge
1.1
366
367         if (xdebug)
368                 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
369                     offtdsue->suesize);
370
gmcgarry
1.3
371         p = bcon(off/SZCHAR);
372         return p;
ragge
1.1
373 }
374
375 /*
376  * Allocate off bits on the stack.  p is a tree that when evaluated
377  * is the multiply count for off, t is a NAME node where to write
378  * the allocated address.
379  */
380 void
381 spalloc(NODE *tNODE *pOFFSZ off)
382 {
383         NODE *sp;
384
385         if ((off % SZINT) == 0)
386                 p =  buildtree(MULpbcon(off/SZINT));
387         else if ((off % SZSHORT) == 0) {
388                 p = buildtree(MULpbcon(off/SZSHORT));
389                 p = buildtree(PLUSpbcon(1));
390                 p = buildtree(RSpbcon(1));
391         } else if ((off % SZCHAR) == 0) {
392                 p = buildtree(MULpbcon(off/SZCHAR));
393                 p = buildtree(PLUSpbcon(3));
394                 p = buildtree(RSpbcon(2));
395         } else
396                 cerror("roundsp");
397
398         /* save the address of sp */
399         sp = block(REGNILNILPTR+INTt->n_dft->n_sue);
400         sp->n_lval = 0;
401         sp->n_rval = STKREG;
402         t->n_type = sp->n_type;
403         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
404
405         /* add the size to sp */
406         sp = block(REGNILNILp->n_type00);
407         sp->n_lval = 0;
408         sp->n_rval = STKREG;
409         ecomp(buildtree(PLUSEQspp));
410 }
411
412 /*
413  * print out a constant node
414  * mat be associated with a label
415  */
416 void
gmcgarry
1.2
417 ninval(CONSZ offint fszNODE *p)
ragge
1.1
418 {
gmcgarry
1.3
419         union { float fdouble dlong double lint i[3]; } u;
420         struct symtab *q;
421         TWORD t;
422 #ifndef USE_GAS
423         int i;
424 #endif
ragge
1.1
425
gmcgarry
1.3
426         t = p->n_type;
427         if (t > BTMASK)
428                 t = INT/* pointer */
429
430         if (p->n_op != ICON && p->n_op != FCON)
431                 cerror("ninval: init node not constant");
432
433         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
434                 uerror("element not constant");
435
436         switch (t) {
437         case LONGLONG:
438         case ULONGLONG:
439 #ifdef USE_GAS
440                 printf("\t.dword 0x%llx\n", (long long)p->n_lval);
441 #else
442                 i = (p->n_lval >> 32);
443                 p->n_lval &= 0xffffffff;
444                 p->n_type = INT;
445                 ninval(off32p);
446                 p->n_lval = i;
447                 ninval(off+3232p);
448 #endif
449                 break;
450         case BOOL:
451                 if (p->n_lval > 1)
452                         p->n_lval = p->n_lval != 0;
453                 /* FALLTHROUGH */
454         case INT:
455         case UNSIGNED:
456                 printf("\t.word 0x%x", (int)p->n_lval);
457                 if ((q = p->n_sp) != NULL) {
458                         if ((q->sclass == STATIC && q->slevel > 0) ||
459                             q->sclass == ILABEL) {
460                                 printf("+" LABFMTq->soffset);
461                         } else
462                                 printf("+%s"exname(q->sname));
463                 }
464                 printf("\n");
465                 break;
466         case SHORT:
467         case USHORT:
468                 printf("\t.half 0x%x\n", (int)p->n_lval & 0xffff);
469                 break;
470         case CHAR:
471         case UCHAR:
472                 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
473                 break;
474         case LDOUBLE:
475                 u.i[2] = 0;
476                 u.l = (long double)p->n_dcon;
477                 printf("\t.word\t0x%x,0x%x,0x%x\n"u.i[0], u.i[1], u.i[2]);
478                 break;
479         case DOUBLE:
480                 u.d = (double)p->n_dcon;
481                 printf("\t.word\t0x%x\n"u.i[0]);
482                 printf("\t.word\t0x%x\n"u.i[1]);
483                 break;
484         case FLOAT:
485                 u.f = (float)p->n_dcon;
486                 printf("\t.word\t0x%x\n"u.i[0]);
487                 break;
488         default:
489                 cerror("ninval");
490         }
ragge
1.1
491 }
492
493 /* make a name look like an external name in the local machine */
494 char *
495 exname(char *p)
496 {
497         if (p == NULL)
498                 return "";
499         return p;
500 }
501
502 /*
503  * map types which are not defined on the local machine
504  */
505 TWORD
506 ctype(TWORD type)
507 {
508         switch (BTYPE(type)) {
509         case LONG:
510                 MODTYPE(type,INT);
511                 break;
512
513         case ULONG:
514                 MODTYPE(type,UNSIGNED);
515
516         }
517         return (type);
518 }
519
520 /* curid is a variable which is defined but
521  * is not initialized (and not a function );
522  * This routine returns the storage class for an uninitialized declaration
523  */
524 int
525 noinit()
526 {
527         return(EXTERN);
528 }
529
530 void
531 calldec(NODE *pNODE *q
532 {
533 }
534
535 void
536 extdec(struct symtab *q)
537 {
538 }
539
540 /* make a common declaration for id, if reasonable */
541 void
542 commdec(struct symtab *q)
543 {
544         int off;
545
546         off = tsize(q->stypeq->sdfq->ssue);
547         off = (off+(SZCHAR-1))/SZCHAR;
548
549 #ifdef GCC_COMPAT
550         printf("        .comm %s,0%o\n"gcc_findname(q), off);
551 #else
552         printf("        .comm %s,0%o\n"exname(q->sname), off);
553 #endif
554 }
555
556 /* make a local common declaration for id, if reasonable */
557 void
558 lcommdec(struct symtab *q)
559 {
560         int off;
561
562         off = tsize(q->stypeq->sdfq->ssue);
563         off = (off+(SZCHAR-1))/SZCHAR;
564         if (q->slevel == 0)
565 #ifdef GCC_COMPAT
gmcgarry
1.3
566                 printf("\t.lcomm %s,0%o\n"gcc_findname(q), off);
ragge
1.1
567 #else
gmcgarry
1.3
568                 printf("\t.lcomm %s,0%o\n"exname(q->sname), off);
ragge
1.1
569 #endif
570         else
gmcgarry
1.3
571                 printf("\t.lcomm " LABFMT ",0%o\n"q->soffsetoff);
ragge
1.1
572 }
573
574 /*
575  * print a (non-prog) label.
576  */
577 void
578 deflab1(int label)
579 {
580         printf(LABFMT ":\n"label);
581 }
582
gmcgarry
1.3
583 static char *loctbl[] = { "text""data""bss""data" };
ragge
1.1
584
585 void
586 setloc1(int locc)
587 {
gmcgarry
1.3
588         //printf("setloc1(%d)\n", locc);
589         if ((locc == lastloc) || (lastloc == DATA && locc == STRNG) || (locc == STRNG || lastloc == DATA))
ragge
1.1
590                 return;
591         lastloc = locc;
gmcgarry
1.3
592         printf("\t.%s\n"loctbl[locc]);
ragge
1.1
593 }
gmcgarry
1.2
594
595 /*
596  * Initialize a bitfield.
597  */
598 void
599 infld(CONSZ offint fszCONSZ val)
600 {
601         if (idebug)
602                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
603                     offfszvalinbits);
604         val &= (1 << fsz)-1;
605         while (fsz + inbits >= SZCHAR) {
606                 inval |= (val << inbits);
607                 printf("\t.byte %d\n"inval & 255);
608                 fsz -= (SZCHAR - inbits);
609                 val >>= (SZCHAR - inbits);
610                 inval = inbits = 0;
611         }
612         if (fsz) {
613                 inval |= (val << inbits);
614                 inbits += fsz;
615         }
616 }
617
618 /*
619  * set fsz bits in sequence to zero.
620  */
621 void
622 zbits(OFFSZ offint fsz)
623 {
624         int m;
625
626         if (idebug)
627                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
628         if ((m = (inbits % SZCHAR))) {
629                 m = SZCHAR - m;
630                 if (fsz < m) {
631                         inbits += fsz;
632                         return;
633                 } else {
634                         fsz -= m;
635                         printf("\t.byte %d\n"inval);
636                         inval = inbits = 0;
637                 }
638         }
639         if (fsz >= SZCHAR) {
640                 printf("\t.zero %d\n"fsz/SZCHAR);
641                 fsz -= (fsz/SZCHAR) * SZCHAR;
642         }
643         if (fsz) {
644                 inval = 0;
645                 inbits = fsz;
646         }
647 }
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-09-03 09:00 +0200