Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20080106160559

Diff

Diff from 1.14 to:

Annotations

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

Annotated File View

ragge
1.14
1 /*      $Id: local.c,v 1.14 2008/01/06 16:05:59 ragge 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.7
34 #include <assert.h>
gmcgarry
1.3
35 #include "pass1.h"
ragge
1.1
36
gmcgarry
1.2
37 static int inbitsinval;
38
gmcgarry
1.3
39 /* this is called to do local transformations on
40  * an expression tree preparitory to its being
41  * written out in intermediate code.
42  */
ragge
1.1
43 NODE *
44 clocal(NODE *p)
45 {
gmcgarry
1.3
46         struct symtab *q;
47         NODE *r, *l;
48         int o;
gmcgarry
1.7
49         int m;
gmcgarry
1.6
50         TWORD ty;
gmcgarry
1.8
51         int tmpnrisptrvoid = 0;
ragge
1.1
52
gmcgarry
1.7
53 #ifdef PCC_DEBUG
54         if (xdebug) {
gmcgarry
1.8
55                 printf("clocal in: %p\n"p);
gmcgarry
1.7
56                 fwalk(peprint0);
57         }
58 #endif
gmcgarry
1.3
59
gmcgarry
1.6
60         switch (o = p->n_op) {
ragge
1.1
61
gmcgarry
1.8
62         case UCALL:
63         case CALL:
64         case STCALL:
65         case USTCALL:
66                 if (p->n_type == VOID)
67                         break;
68                 /*
69                  * if the function returns void*, ecode() invokes
70                  * delvoid() to convert it to uchar*.
71                  * We just let this happen on the ASSIGN to the temp,
72                  * and cast the pointer back to void* on access
73                  * from the temp.
74                  */
75                 if (p->n_type == PTR+VOID)
76                         isptrvoid = 1;
77                 r = tempnode(0p->n_typep->n_dfp->n_sue);
ragge
1.12
78                 tmpnr = regno(r);
gmcgarry
1.8
79                 r = block(ASSIGNrpp->n_typep->n_dfp->n_sue);
gmcgarry
1.9
80
gmcgarry
1.8
81                 p = tempnode(tmpnrr->n_typer->n_dfr->n_sue);
82                 if (isptrvoid) {
83                         p = block(PCONVpNILPTR+VOID,
84                             p->n_dfMKSUE(PTR+VOID));
85                 }
gmcgarry
1.9
86                 p = buildtree(COMOPrp);
gmcgarry
1.8
87                 break;
88
ragge
1.1
89         case NAME:
90                 if ((q = p->n_sp) == NULL)
91                         return p/* Nothing to care about */
92
93                 switch (q->sclass) {
94
95                 case PARAM:
96                 case AUTO:
97                         /* fake up a structure reference */
98                         r = block(REGNILNILPTR+STRTY00);
99                         r->n_lval = 0;
gmcgarry
1.3
100                         r->n_rval = FP;
ragge
1.1
101                         p = stref(block(STREFrp000));
102                         break;
103
104                 case STATIC:
105                         if (q->slevel == 0)
106                                 break;
107                         p->n_lval = 0;
108                         p->n_sp = q;
109                         break;
110
111                 case REGISTER:
112                         p->n_op = REG;
113                         p->n_lval = 0;
114                         p->n_rval = q->soffset;
115                         break;
116
gmcgarry
1.7
117                 }
ragge
1.1
118                 break;
119
120         case FUNARG:
121                 /* Args smaller than int are given as int */
122                 if (p->n_type != CHAR && p->n_type != UCHAR && 
123                     p->n_type != SHORT && p->n_type != USHORT)
124                         break;
125                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
126                 p->n_type = INT;
127                 p->n_sue = MKSUE(INT);
128                 p->n_rval = SZINT;
129                 break;
130
131         case CBRANCH:
132                 l = p->n_left;
133
134                 /*
135                  * Remove unneccessary conversion ops.
136                  */
137                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
138                         if (coptype(l->n_op) != BITYPE)
139                                 break;
140                         if (l->n_right->n_op == ICON) {
141                                 r = l->n_left->n_left;
142                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
143                                         break;
144                                 /* Type must be correct */
gmcgarry
1.6
145                                 ty = r->n_type;
ragge
1.1
146                                 nfree(l->n_left);
147                                 l->n_left = r;
gmcgarry
1.6
148                                 l->n_type = ty;
149                                 l->n_right->n_type = ty;
ragge
1.1
150                         }
151 #if 0
152                           else if (l->n_right->n_op == SCONV &&
153                             l->n_left->n_type == l->n_right->n_type) {
154                                 r = l->n_left->n_left;
155                                 nfree(l->n_left);
156                                 l->n_left = r;
157                                 r = l->n_right->n_left;
158                                 nfree(l->n_right);
159                                 l->n_right = r;
160                         }
161 #endif
162                 }
163                 break;
164
165         case PCONV:
gmcgarry
1.7
166                 /* Remove redundant PCONV's. Be careful */
ragge
1.1
167                 l = p->n_left;
gmcgarry
1.7
168                 if (l->n_op == ICON) {
169                         l->n_lval = (unsigned)l->n_lval;
170                         goto delp;
171                 }
gmcgarry
1.8
172                 if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) {
gmcgarry
1.7
173                         /* float etc? */
174                         p->n_left = block(SCONVlNIL,
175                             UNSIGNED0MKSUE(UNSIGNED));
176                         break;
177                 }
178                 /* if left is SCONV, cannot remove */
179                 if (l->n_op == SCONV)
180                         break;
181
182                 /* avoid ADDROF TEMP */
183                 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
ragge
1.1
184                         break;
gmcgarry
1.7
185
186                 /* if conversion to another pointer type, just remove */
187                 if (p->n_type > BTMASK && l->n_type > BTMASK)
188                         goto delp;
189                 break;
190
191         delp:   l->n_type = p->n_type;
ragge
1.1
192                 l->n_qual = p->n_qual;
193                 l->n_df = p->n_df;
194                 l->n_sue = p->n_sue;
195                 nfree(p);
196                 p = l;
197                 break;
198
199         case SCONV:
200                 l = p->n_left;
201
202                 if (p->n_type == l->n_type) {
203                         nfree(p);
gmcgarry
1.8
204                         p = l;
205                         break;
ragge
1.1
206                 }
207
208                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
209                     btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
210                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
211                             l->n_type != FLOAT && l->n_type != DOUBLE &&
212                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
gmcgarry
1.8
213                                 if (l->n_op == NAME || l->n_op == UMUL ||
214                                     l->n_op == TEMP) {
ragge
1.1
215                                         l->n_type = p->n_type;
216                                         nfree(p);
gmcgarry
1.8
217                                         p = l;
218                                         break;
ragge
1.1
219                                 }
220                         }
221                 }
222
gmcgarry
1.8
223                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
224                     coptype(l->n_op) == BITYPE) {
225                         l->n_type = p->n_type;
226                         nfree(p);
227                         p = l;
228                 }
229
230                 if (DEUNSIGN(p->n_type) == SHORT &&
231                     DEUNSIGN(l->n_type) == SHORT) {
ragge
1.1
232                         nfree(p);
gmcgarry
1.8
233                         p = l;
ragge
1.1
234                 }
235
gmcgarry
1.9
236                 /* convert float/double to int before to (u)char/(u)short */
gmcgarry
1.8
237                 if ((DEUNSIGN(p->n_type) == CHAR ||
238                     DEUNSIGN(p->n_type) == SHORT) &&
239                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
240                     l->n_type == LDOUBLE)) {
241                         p = block(SCONVpNILp->n_typep->n_dfp->n_sue);
242                         p->n_left->n_type = INT;
243                         break;
244                 }
245
gmcgarry
1.9
246                 /* convert (u)char/(u)short to int before float/double */
247                 if  ((p->n_type == FLOAT || p->n_type == DOUBLE ||
248                     p->n_type == LDOUBLE) && (DEUNSIGN(l->n_type) == CHAR ||
249                     DEUNSIGN(l->n_type) == SHORT)) {
250                         p = block(SCONVpNILp->n_typep->n_dfp->n_sue);
251                         p->n_left->n_type = INT;
252                         break;
253                 }
gmcgarry
1.8
254
ragge
1.1
255                 o = l->n_op;
256                 m = p->n_type;
257
258                 if (o == ICON) {
259                         CONSZ val = l->n_lval;
260
261                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
262                             switch (m) {
gmcgarry
1.10
263                         case BOOL:
264                                 l->n_lval = l->n_lval != 0;
265                                 break;
ragge
1.1
266                         case CHAR:
267                                 l->n_lval = (char)val;
268                                 break;
269                         case UCHAR:
270                                 l->n_lval = val & 0377;
271                                 break;
272                         case SHORT:
273                                 l->n_lval = (short)val;
274                                 break;
275                         case USHORT:
276                                 l->n_lval = val & 0177777;
277                                 break;
278                         case ULONG:
279                         case UNSIGNED:
280                                 l->n_lval = val & 0xffffffff;
281                                 break;
282                         case LONG:
283                         case INT:
284                                 l->n_lval = (int)val;
285                                 break;
286                         case LONGLONG:
287                                 l->n_lval = (long long)val;
288                                 break;
289                         case ULONGLONG:
290                                 l->n_lval = val;
291                                 break;
292                         case VOID:
293                                 break;
294                         case LDOUBLE:
295                         case DOUBLE:
296                         case FLOAT:
297                                 l->n_op = FCON;
298                                 l->n_dcon = val;
299                                 break;
300                         default:
301                                 cerror("unknown type %d"m);
302                         }
303                         l->n_type = m;
304                         nfree(p);
305                         p = l;
306                 }
307                 break;
308
309         case MOD:
310         case DIV:
311                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
312                         break;
313                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
314                         break;
315                 /* make it an int division by inserting conversions */
316                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
317                 p->n_right = block(SCONVp->n_rightNILINT0MKSUE(INT));
318                 p = block(SCONVpNILp->n_type0MKSUE(p->n_type));
319                 p->n_left->n_type = INT;
320                 break;
321
322         case PMCONV:
323         case PVCONV:
324                 ifp->n_right->n_op != ICON ) cerror"bad conversion"0);
325                 nfree(p);
gmcgarry
1.8
326                 p = buildtree(o==PMCONV?MUL:DIVp->n_leftp->n_right);
327                 break;
ragge
1.1
328
329         case FORCE:
330                 /* put return value in return reg */
331                 p->n_op = ASSIGN;
332                 p->n_right = p->n_left;
gmcgarry
1.2
333                 p->n_left = block(REGNILNILp->n_type0MKSUE(INT));
gmcgarry
1.3
334                 p->n_left->n_rval = RETREG(p->n_type);
ragge
1.1
335                 break;
336         }
gmcgarry
1.3
337
gmcgarry
1.8
338 #ifdef PCC_DEBUG
339         if (xdebug) {
340                 printf("clocal out: %p\n"p);
341                 fwalk(peprint0);
342         }
343 #endif
ragge
1.1
344
345         return(p);
346 }
347
348 void
349 myp2tree(NODE *p)
350 {
ragge
1.14
351         struct symtab *sp;
ragge
1.11
352
ragge
1.14
353         if (p->n_op != FCON
ragge
1.11
354                 return;
355
356         /* Write float constants to memory */
357  
ragge
1.14
358         sp = tmpalloc(sizeof(struct symtab));
359         sp->sclass = STATIC;
360         sp->slevel = 1/* fake numeric label */
361         sp->soffset = getlab();
362         sp->sflags = 0;
363         sp->stype = p->n_type;
364         sp->squal = (CON >> TSHIFT);
365
366         defloc(sp);
ragge
1.11
367         ninval(0btdims[p->n_type].suesizep);
ragge
1.14
368
ragge
1.11
369         p->n_op = NAME;
ragge
1.14
370         p->n_lval = 0;
371         p->n_sp = sp;
ragge
1.11
372
ragge
1.1
373 }
374
375 /*ARGSUSED*/
376 int
377 andable(NODE *p)
378 {
379         return(1);  /* all names can have & taken on them */
380 }
381
382 /*
383  * at the end of the arguments of a ftn, set the automatic offset
384  */
385 void
386 cendarg()
387 {
388         autooff = AUTOINIT;
389 }
390
391 /*
392  * is an automatic variable of type t OK for a register variable
393  */
394 int
395 cisreg(TWORD t)
396 {
397         if (t == INT || t == UNSIGNED || t == LONG || t == ULONG)
398                 return(1);
399         return 0/* XXX - fix reg assignment in pftn.c */
400 }
401
402 /*
403  * return a node, for structure references, which is suitable for
404  * being added to a pointer of type t, in order to be off bits offset
405  * into a structure
406  * t, d, and s are the type, dimension offset, and sizeoffset
407  * Be careful about only handling first-level pointers, the following
408  * indirections must be fullword.
409  */
410 NODE *
411 offcon(OFFSZ offTWORD tunion dimfun *dstruct suedef *sue)
412 {
gmcgarry
1.3
413         NODE *p;
ragge
1.1
414
415         if (xdebug)
416                 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
417                     offtdsue->suesize);
418
gmcgarry
1.3
419         p = bcon(off/SZCHAR);
420         return p;
ragge
1.1
421 }
422
423 /*
424  * Allocate off bits on the stack.  p is a tree that when evaluated
425  * is the multiply count for off, t is a NAME node where to write
426  * the allocated address.
427  */
428 void
429 spalloc(NODE *tNODE *pOFFSZ off)
430 {
431         NODE *sp;
gmcgarry
1.10
432         int nbytes = off / SZCHAR;
ragge
1.1
433
gmcgarry
1.10
434         p = buildtree(MULpbcon(nbytes));
435         p = buildtree(PLUSpbcon(7));
436         p = buildtree(ANDpbcon(~7));
437
438         /* subtract the size from sp */
439         sp = block(REGNILNILp->n_type00);
440         sp->n_lval = 0;
441         sp->n_rval = SP;
442         ecomp(buildtree(MINUSEQspp));
ragge
1.1
443
444         /* save the address of sp */
445         sp = block(REGNILNILPTR+INTt->n_dft->n_sue);
gmcgarry
1.6
446         sp->n_rval = SP;
ragge
1.1
447         t->n_type = sp->n_type;
448         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
449 }
450
451 /*
452  * print out a constant node
453  * mat be associated with a label
454  */
455 void
gmcgarry
1.2
456 ninval(CONSZ offint fszNODE *p)
ragge
1.1
457 {
gmcgarry
1.10
458         union { float fdouble dint i[2]; } u;
gmcgarry
1.3
459         struct symtab *q;
460         TWORD t;
461 #ifndef USE_GAS
gmcgarry
1.5
462         int ij;
gmcgarry
1.3
463 #endif
ragge
1.1
464
gmcgarry
1.3
465         t = p->n_type;
466         if (t > BTMASK)
467                 t = INT/* pointer */
468
469         if (p->n_op != ICON && p->n_op != FCON)
470                 cerror("ninval: init node not constant");
471
472         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
473                 uerror("element not constant");
474
475         switch (t) {
476         case LONGLONG:
477         case ULONGLONG:
478 #ifdef USE_GAS
gmcgarry
1.10
479                 printf("\t.dword %lld\n", (long long)p->n_lval);
gmcgarry
1.3
480 #else
gmcgarry
1.5
481                 i = p->n_lval >> 32;
482                 j = p->n_lval & 0xffffffff;
gmcgarry
1.3
483                 p->n_type = INT;
gmcgarry
1.5
484                 if (bigendian) {
485                         p->n_lval = j;
486                         ninval(off32p);
487                         p->n_lval = i;
488                         ninval(off+3232p);
489                 } else {
490                         p->n_lval = i;
491                         ninval(off32p);
492                         p->n_lval = j;
493                         ninval(off+3232p);
494                 }
gmcgarry
1.3
495 #endif
496                 break;
497         case BOOL:
498                 if (p->n_lval > 1)
499                         p->n_lval = p->n_lval != 0;
500                 /* FALLTHROUGH */
501         case INT:
502         case UNSIGNED:
gmcgarry
1.10
503                 printf("\t.word " CONFMT, (CONSZ)p->n_lval);
gmcgarry
1.3
504                 if ((q = p->n_sp) != NULL) {
505                         if ((q->sclass == STATIC && q->slevel > 0) ||
506                             q->sclass == ILABEL) {
507                                 printf("+" LABFMTq->soffset);
508                         } else
ragge
1.13
509                                 printf("+%s"exname(q->soname));
gmcgarry
1.3
510                 }
511                 printf("\n");
512                 break;
513         case SHORT:
514         case USHORT:
gmcgarry
1.10
515                 printf("\t.half %d\n", (int)p->n_lval & 0xffff);
gmcgarry
1.3
516                 break;
517         case CHAR:
518         case UCHAR:
519                 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
520                 break;
521         case LDOUBLE:
522         case DOUBLE:
523                 u.d = (double)p->n_dcon;
gmcgarry
1.9
524                 if (bigendian) {
gmcgarry
1.10
525                         printf("\t.word\t%d\n"u.i[0]);
526                         printf("\t.word\t%d\n"u.i[1]);
gmcgarry
1.9
527                 } else {
gmcgarry
1.10
528                         printf("\t.word\t%d\n"u.i[1]);
529                         printf("\t.word\t%d\n"u.i[0]);
gmcgarry
1.9
530                 }
gmcgarry
1.3
531                 break;
532         case FLOAT:
533                 u.f = (float)p->n_dcon;
534                 printf("\t.word\t0x%x\n"u.i[0]);
535                 break;
536         default:
537                 cerror("ninval");
538         }
ragge
1.1
539 }
540
541 /* make a name look like an external name in the local machine */
542 char *
543 exname(char *p)
544 {
545         if (p == NULL)
546                 return "";
547         return p;
548 }
549
550 /*
551  * map types which are not defined on the local machine
552  */
553 TWORD
554 ctype(TWORD type)
555 {
556         switch (BTYPE(type)) {
557         case LONG:
558                 MODTYPE(type,INT);
559                 break;
560
561         case ULONG:
562                 MODTYPE(type,UNSIGNED);
563
564         }
565         return (type);
566 }
567
568 /* curid is a variable which is defined but
569  * is not initialized (and not a function );
570  * This routine returns the storage class for an uninitialized declaration
571  */
572 int
573 noinit()
574 {
575         return(EXTERN);
576 }
577
578 void
579 calldec(NODE *pNODE *q
580 {
581 }
582
583 void
584 extdec(struct symtab *q)
585 {
586 }
587
ragge
1.14
588 /*
589  * Print out a string of characters.
590  * Assume that the assembler understands C-style escape
591  * sequences.
592  */
593 void
594 instring(struct symtab *sp)
595 {
596         char *s, *str;
597
598         defloc(sp);
599         str = sp->sname;
600
601         /* be kind to assemblers and avoid long strings */
602         printf("\t.ascii \"");
603         for (s = str; *s != 0; ) {
604                 if (*s++ == '\\') {
605                         (void)esccon(&s);
606                 }
607                 if (s - str > 60) {
608                         fwrite(str1s - strstdout);
609                         printf("\"\n\t.ascii \"");
610                         str = s;
611                 }
612         }
613         fwrite(str1s - strstdout);
614         printf("\\0\"\n");
615 }
616
617 /*
618  * Print out a wide string by calling ninval().
619  */
620 void
621 inwstring(struct symtab *sp)
622 {
623         char *s = sp->sname;
624         NODE *p;
625
626         defloc(sp);
627         p = bcon(0);
628         do {
629                 if (*s++ == '\\')
630                         p->n_lval = esccon(&s);
631                 else
632                         p->n_lval = (unsigned char)s[-1];
633                 ninval(0, (MKSUE(WCHAR_TYPE))->suesizep);
634         } while (s[-1] != 0);
635         nfree(p);
636 }
637
638 /* make a common declaration for id, if reasonable */
639 void
640 defzero(struct symtab *sp)
641 {
642         int off;
643
644         off = tsize(sp->stypesp->sdfsp->ssue);
645         off = (off+(SZCHAR-1))/SZCHAR;
646         printf("        .%scomm "sp->sclass == STATIC ? "l" : "");
647         if (sp->slevel == 0)
648                 printf("%s,0%o\n"exname(sp->soname), off);
649         else
650                 printf(LABFMT ",0%o\n"sp->soffsetoff);
651 }
652
653
654 #ifdef notdef
ragge
1.1
655 /* make a common declaration for id, if reasonable */
656 void
657 commdec(struct symtab *q)
658 {
659         int off;
660
661         off = tsize(q->stypeq->sdfq->ssue);
662         off = (off+(SZCHAR-1))/SZCHAR;
663
ragge
1.13
664         printf("        .comm %s,%d\n"exname(q->soname), off);
ragge
1.1
665 }
666
667 /* make a local common declaration for id, if reasonable */
668 void
669 lcommdec(struct symtab *q)
670 {
671         int off;
672
673         off = tsize(q->stypeq->sdfq->ssue);
674         off = (off+(SZCHAR-1))/SZCHAR;
675         if (q->slevel == 0)
ragge
1.13
676                 printf("\t.lcomm %s,%d\n"exname(q->soname), off);
ragge
1.1
677         else
gmcgarry
1.9
678                 printf("\t.lcomm " LABFMT ",%d\n"q->soffsetoff);
ragge
1.1
679 }
680
681 /*
682  * print a (non-prog) label.
683  */
684 void
685 deflab1(int label)
686 {
687         printf(LABFMT ":\n"label);
688 }
689
gmcgarry
1.9
690 /* ro-text, rw-data, ro-data, ro-strings */
691 static char *loctbl[] = { "text""data""rdata""rdata" };
ragge
1.1
692
693 void
694 setloc1(int locc)
695 {
gmcgarry
1.10
696         if (locc == lastloc && locc != STRNG)
ragge
1.1
697                 return;
gmcgarry
1.10
698         if (locc == DATA && lastloc == STRNG)
699                 return;
700
701         if (locc != lastloc) {
702                 lastloc = locc;
703                 printf("\t.%s\n"loctbl[locc]);
704         }
705
706         if (locc == STRNG)
707                 printf("\t.align 2\n");
ragge
1.1
708 }
ragge
1.14
709 #endif
gmcgarry
1.2
710
711 /*
712  * Initialize a bitfield.
713  */
714 void
715 infld(CONSZ offint fszCONSZ val)
716 {
717         if (idebug)
718                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
719                     offfszvalinbits);
720         val &= (1 << fsz)-1;
721         while (fsz + inbits >= SZCHAR) {
722                 inval |= (val << inbits);
723                 printf("\t.byte %d\n"inval & 255);
724                 fsz -= (SZCHAR - inbits);
725                 val >>= (SZCHAR - inbits);
726                 inval = inbits = 0;
727         }
728         if (fsz) {
729                 inval |= (val << inbits);
730                 inbits += fsz;
731         }
732 }
733
734 /*
735  * set fsz bits in sequence to zero.
736  */
737 void
738 zbits(OFFSZ offint fsz)
739 {
740         int m;
741
742         if (idebug)
743                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
744         if ((m = (inbits % SZCHAR))) {
745                 m = SZCHAR - m;
746                 if (fsz < m) {
747                         inbits += fsz;
748                         return;
749                 } else {
750                         fsz -= m;
751                         printf("\t.byte %d\n"inval);
752                         inval = inbits = 0;
753                 }
754         }
755         if (fsz >= SZCHAR) {
756                 printf("\t.zero %d\n"fsz/SZCHAR);
757                 fsz -= (fsz/SZCHAR) * SZCHAR;
758         }
759         if (fsz) {
760                 inval = 0;
761                 inbits = fsz;
762         }
763 }
gmcgarry
1.6
764
765 /*
766  * va_start(ap, last) implementation.
767  *
768  * f is the NAME node for this builtin function.
769  * a is the argument list containing:
770  *         CM
771  *      ap   last
gmcgarry
1.7
772  *
773  * It turns out that this is easy on MIPS.  Just write the
774  * argument registers to the stack in va_arg_start() and
775  * use the traditional method of walking the stackframe.
gmcgarry
1.6
776  */
777 NODE *
778 mips_builtin_stdarg_start(NODE *fNODE *a)
779 {
gmcgarry
1.7
780         NODE *p, *q;
gmcgarry
1.6
781         int sz = 1;
gmcgarry
1.7
782         int i;
gmcgarry
1.6
783
784         /* check num args and type */
785         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
786             !ISPTR(a->n_left->n_type))
787                 goto bad;
788
gmcgarry
1.7
789         /*
790          * look at the offset of the last org to calculate the
791          * number of remain registers that need to be written
792          * to the stack.
793          */
794         if (xtemps) {
795                 for (i = 0i < nargregsi++) {
796                         q = block(REGNILNILPTR+INT0MKSUE(INT));
797                         q->n_rval = A0 + i;
798                         p = block(REGNILNILPTR+INT0MKSUE(INT));
799                         p->n_rval = SP;
800                         p = block(PLUSpbcon(ARGINIT+i), PTR+INT0MKSUE(INT));
801                         p = buildtree(UMULpNIL);
802                         p = buildtree(ASSIGNpq);
803                         ecomp(p);
804                 }
805         }
806
gmcgarry
1.6
807         /* must first deal with argument size; use int size */
808         p = a->n_right;
gmcgarry
1.7
809         if (p->n_type < INT) {
810                 /* round up to word */
gmcgarry
1.6
811                 sz = SZINT / tsize(p->n_typep->n_dfp->n_sue);
gmcgarry
1.7
812         }
813
814         /*
815          * Once again, if xtemps, the register is written to a
816          * temp.  We cannot take the address of the temp and
817          * walk from there.
818          *
819          * No solution at the moment...
820          */
821         assert(!xtemps);
822
823         p = buildtree(ADDROFpNIL);  /* address of last arg */
824         p = optim(buildtree(PLUSpbcon(sz)));
825         q = block(NAMENILNILPTR+VOID00);
826         q = buildtree(CASTqp);
827         p = q->n_right;
828         nfree(q->n_left);
829         nfree(q);
830         p = buildtree(ASSIGNa->n_leftp);
831         tfree(f);
832         nfree(a);
833
834         return p;
835
gmcgarry
1.6
836 bad:
gmcgarry
1.7
837         uerror("bad argument to __builtin_stdarg_start");
838         return bcon(0);
gmcgarry
1.6
839 }
840
841 NODE *
842 mips_builtin_va_arg(NODE *fNODE *a)
843 {
gmcgarry
1.7
844         NODE *p, *q, *r;
845         int sztmpnr;
846
847         /* check num args and type */
848         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
849             !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
850                 goto bad;
851
852         /* create a copy to a temp node */
853         p = tcopy(a->n_left);
854         q = tempnode(0p->n_typep->n_dfp->n_sue);
ragge
1.12
855         tmpnr = regno(q);
gmcgarry
1.7
856         p = buildtree(ASSIGNqp);
857
858         r = a->n_right;
859         sz = tsize(r->n_typer->n_dfr->n_sue) / SZCHAR;
gmcgarry
1.9
860         if (sz < SZINT/SZCHAR) {
861                 werror("%s%s promoted to int when passed through ...",
862                         r->n_type & 1 ? "unsigned " : "",
863                         DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
864                 sz = SZINT/SZCHAR;
865         }
gmcgarry
1.7
866         q = buildtree(PLUSEQa->n_leftbcon(sz));
867         q = buildtree(COMOPpq);
868
869         nfree(a->n_right);
870         nfree(a);
871         nfree(f); 
872
873         p = tempnode(tmpnrINCREF(r->n_type), r->n_dfr->n_sue);
874         p = buildtree(UMULpNIL);
875         p = buildtree(COMOPqp);
876
877         return p;
878
879 bad:
880         uerror("bad argument to __builtin_va_arg");
881         return bcon(0);
gmcgarry
1.6
882 }
883
884 NODE *
885 mips_builtin_va_end(NODE *fNODE *a)
886 {
gmcgarry
1.7
887         tfree(f);
888         tfree(a);
889         return bcon(0);
gmcgarry
1.6
890 }
891
892 NODE *
893 mips_builtin_va_copy(NODE *fNODE *a)
894 {
gmcgarry
1.7
895         if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
896                 goto bad;
897         tfree(f);
898         f = buildtree(ASSIGNa->n_lefta->n_right);
899         nfree(a);
gmcgarry
1.6
900         return f;
gmcgarry
1.7
901
902 bad:
903         uerror("bad argument to __buildtin_va_copy");
904         return bcon(0);
gmcgarry
1.6
905 }
ragge
1.13
906 /*
907  * Give target the opportunity of handling pragmas.
908  */
909 int
910 mypragma(char **ary)
911 {
912         return 0; }
913
914 /*
915  * Called when a identifier has been declared, to give target last word.
916  */
917 void
918 fixdef(struct symtab *sp)
919 {
920 }
921
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-01 20:34 +0200