Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120422210740

Diff

Diff from 1.27 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/arm/code.c

Annotated File View

plunky
1.27
1 /*      $Id: code.c,v 1.27 2012/04/22 21:07:40 plunky Exp $    */
gmcgarry
1.4
2 /*
3  * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
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
gmcgarry
1.1
30 /*
31  *  Stuff for pass1.
32  */
33
34 #include <assert.h>
35
36 #include "pass1.h"
37 #include "pass2.h"
38
gmcgarry
1.15
39 static int rvnr;
40
ragge
1.8
41 /*
gmcgarry
1.26
42  * Print out assembler segment name.
43  */
44 void
45 setseg(int segchar *name)
46 {
47         switch (seg) {
48         case PROGname = ".text"break;
49         case DATA:
50         case LDATAname = ".data"break;
51         case UDATAbreak;
52         case PICLDATAname = ".section .data.rel.local,\"aw\",@progbits";break;
53         case PICDATAname = ".section .data.rel.rw,\"aw\",@progbits"break;
54         case PICRDATAname = ".section .data.rel.ro,\"aw\",@progbits"break;
55         case STRNG:
56         case RDATAname = ".section .rodata"break;
57         case TLSDATAname = ".section .tdata,\"awT\",@progbits"break;
58         case TLSUDATAname = ".section .tbss,\"awT\",@nobits"break;
59         case CTORSname = ".section\t.ctors,\"aw\",@progbits"break;
60         case DTORSname = ".section\t.dtors,\"aw\",@progbits"break;
61         case NMSEG
62                 printf("\t.section %s,\"aw\",@progbits\n"name);
63                 return;
64         }
65         printf("\t%s\n"name);
66 }
67
68 /*
ragge
1.8
69  * Define everything needed to print out some data (or text).
70  * This means segment, alignment, visibility, etc.
71  */
72 void
73 defloc(struct symtab *sp)
74 {
ragge
1.21
75         char *n;
ragge
1.8
76
ragge
1.21
77         n = sp->soname ? sp->soname : exname(sp->sname);
gmcgarry
1.11
78 #ifdef USE_GAS
ragge
1.8
79         if (ISFTN(t))
ragge
1.21
80                 printf("\t.type %s,%%function\n"n);
gmcgarry
1.11
81 #endif
ragge
1.8
82         if (sp->sclass == EXTDEF)
ragge
1.21
83                 printf("\t.global %s\n"n);
ragge
1.8
84         if (sp->slevel == 0)
ragge
1.21
85                 printf("%s:\n"n);
ragge
1.8
86         else
87                 printf(LABFMT ":\n"sp->soffset);
88 }
89
gmcgarry
1.11
90 /* Put a symbol in a temporary
91  * used by bfcode() and its helpers
92  */
93 static void
94 putintemp(struct symtab *sym)
95 {
gmcgarry
1.26
96         NODE *p;
gmcgarry
1.11
97
gmcgarry
1.26
98         p = tempnode(0sym->stypesym->sdfsym->sap);
99         p = buildtree(ASSIGNpnametree(sym));
100         sym->soffset = regno(p->n_left);
101         sym->sflags |= STNODE;
102         ecomp(p);
gmcgarry
1.11
103 }
104
105 /* setup a 64-bit parameter (double/ldouble/longlong)
106  * used by bfcode() */
107 static void
gmcgarry
1.17
108 param_64bit(struct symtab *symint *argofspint dotemps)
gmcgarry
1.11
109 {
gmcgarry
1.26
110         int argofs = *argofsp;
111         NODE *p, *q;
112         int navail;
gmcgarry
1.11
113
114 #if ALLONGLONG == 64
gmcgarry
1.13
115         /* alignment */
gmcgarry
1.17
116         ++argofs;
117         argofs &= ~1;
118         *argofsp = argofs;
gmcgarry
1.11
119 #endif
120
gmcgarry
1.26
121         navail = NARGREGS - argofs;
gmcgarry
1.11
122
gmcgarry
1.26
123         if (navail < 2) {
gmcgarry
1.13
124                 /* half in and half out of the registers */
125                 if (features(FEATURE_BIGENDIAN)) {
gmcgarry
1.15
126                         cerror("param_64bit");
gmcgarry
1.13
127                         p = q = NULL;
128                 } else {
gmcgarry
1.26
129                         q = block(REGNILNILINT00);
130                         regno(q) = R0 + argofs;
gmcgarry
1.13
131                         if (dotemps) {
132                                 q = block(SCONVqNIL,
ragge
1.22
133                                     ULONGLONG00);
gmcgarry
1.26
134                                 p = nametree(sym);
gmcgarry
1.13
135                                 p->n_type = ULONGLONG;
136                                 p->n_df = 0;
gmcgarry
1.26
137                                 p->n_ap = NULL;
ragge
1.22
138                                 p = block(LSpbcon(32), ULONGLONG00);
139                                 q = block(PLUSpqULONGLONG00);
140                                 p = tempnode(0ULONGLONG00);
gmcgarry
1.13
141                                 sym->soffset = regno(p);
142                                 sym->sflags |= STNODE;
143                         } else {
gmcgarry
1.26
144                                 p = nametree(sym);
gmcgarry
1.13
145                                 regno(p) = sym->soffset;
146                                 p->n_type = INT;
147                                 p->n_df = 0;
gmcgarry
1.26
148                                 p->n_ap = NULL;
gmcgarry
1.13
149                         }
150                 }
gmcgarry
1.26
151                 p = buildtree(ASSIGNpq);
gmcgarry
1.13
152                 ecomp(p);
gmcgarry
1.26
153                 *argofsp = argofs + 2;
gmcgarry
1.13
154                 return;
gmcgarry
1.26
155         }
gmcgarry
1.11
156
gmcgarry
1.26
157         q = block(REGNILNILsym->stypesym->sdfsym->sap);
158         regno(q) = R0R1 + argofs;
159         if (dotemps) {
160                 p = tempnode(0sym->stypesym->sdfsym->sap);
161                 sym->soffset = regno(p);
162                 sym->sflags |= STNODE;
163         } else {
164                 p = nametree(sym);
165         }
166         p = buildtree(ASSIGNpq);
167         ecomp(p);
168         *argofsp = argofs + 2;
gmcgarry
1.11
169 }
170
171 /* setup a 32-bit param on the stack
172  * used by bfcode() */
173 static void
gmcgarry
1.17
174 param_32bit(struct symtab *symint *argofspint dotemps)
gmcgarry
1.11
175 {
gmcgarry
1.26
176         NODE *p, *q;
gmcgarry
1.11
177
gmcgarry
1.26
178         q = block(REGNILNILsym->stypesym->sdfsym->sap);
179         regno(q) = R0 + (*argofsp)++;
180         if (dotemps) {
181                 p = tempnode(0sym->stypesym->sdfsym->sap);
182                 sym->soffset = regno(p);
183                 sym->sflags |= STNODE;
184         } else {
185                 p = nametree(sym);
186         }
187         p = buildtree(ASSIGNpq);
188         ecomp(p);
gmcgarry
1.11
189 }
190
gmcgarry
1.13
191 /* setup a double param on the stack
192  * used by bfcode() */
193 static void
gmcgarry
1.17
194 param_double(struct symtab *symint *argofspint dotemps)
gmcgarry
1.13
195 {
gmcgarry
1.26
196         NODE *p, *q, *t;
197         int tmpnr;
gmcgarry
1.13
198
199         /*
200          * we have to dump the float from the general register
201          * into a temp, since the register allocator doesn't like
202          * floats to be in CLASSA.  This may not work for -xtemps.
203          */
204
gmcgarry
1.26
205         t = tempnode(0ULONGLONG00);
206         tmpnr = regno(t);
207         q = block(REGNILNILINT00);
208         q->n_rval = R0R1 + (*argofsp)++;
209         p = buildtree(ASSIGNtq);
210         ecomp(p);
211
212         if (dotemps) {
213                 sym->soffset = tmpnr;
214                 sym->sflags |= STNODE;
215         } else {
216                 q = tempnode(tmpnrsym->stypesym->sdfsym->sap);
217                 p = nametree(sym);
218                 p = buildtree(ASSIGNpq);
219                 ecomp(p);
220         }
gmcgarry
1.13
221 }
222
223 /* setup a float param on the stack
224  * used by bfcode() */
225 static void
gmcgarry
1.17
226 param_float(struct symtab *symint *argofspint dotemps)
gmcgarry
1.13
227 {
gmcgarry
1.26
228         NODE *p, *q, *t;
229         int tmpnr;
gmcgarry
1.13
230
231         /*
232          * we have to dump the float from the general register
233          * into a temp, since the register allocator doesn't like
234          * floats to be in CLASSA.  This may not work for -xtemps.
235          */
236
gmcgarry
1.26
237         t = tempnode(0INT00);
238         tmpnr = regno(t);
239         q = block(REGNILNILINT00);
240         q->n_rval = R0 + (*argofsp)++;
241         p = buildtree(ASSIGNtq);
242         ecomp(p);
243
244         if (dotemps) {
245                 sym->soffset = tmpnr;
246                 sym->sflags |= STNODE;
247         } else {
248                 q = tempnode(tmpnrsym->stypesym->sdfsym->sap);
249                 p = nametree(sym);
250                 p = buildtree(ASSIGNpq);
251                 ecomp(p);
252         }
gmcgarry
1.13
253 }
254
gmcgarry
1.15
255 /* setup the hidden pointer to struct return parameter
256  * used by bfcode() */
257 static void
258 param_retstruct(void)
259 {
gmcgarry
1.26
260         NODE *p, *q;
gmcgarry
1.15
261
gmcgarry
1.26
262         p = tempnode(0PTR-FTN+cftnsp->stype0cftnsp->sap);
263         rvnr = regno(p);
264         q = block(REGNILNILPTR+STRTY0cftnsp->sap);
265         regno(q) = R0;
266         p = buildtree(ASSIGNpq);
267         ecomp(p);
gmcgarry
1.15
268 }
269
270
271 /* setup struct parameter
272  * push the registers out to memory
273  * used by bfcode() */
274 static void
gmcgarry
1.17
275 param_struct(struct symtab *symint *argofsp)
gmcgarry
1.15
276 {
gmcgarry
1.26
277         int argofs = *argofsp;
278         NODE *p, *q;
279         int navail;
280         int sz;
281         int off;
282         int num;
283         int i;
284
285         navail = NARGREGS - argofs;
286         sz = tsize(sym->stypesym->sdfsym->sap) / SZINT;
287         off = ARGINIT/SZINT + argofs;
288         num = sz > navail ? navail : sz;
289         for (i = 0i < numi++) {
290                 q = block(REGNILNILINT00);
291                 regno(q) = R0 + argofs++;
292                 p = block(REGNILNILINT00);
293                 regno(p) = SP;
294                 p = block(PLUSpbcon(4*off++), INT00);
295                 p = block(UMULpNILINT00);
296                 p = buildtree(ASSIGNpq);
297                 ecomp(p);
298         }
gmcgarry
1.15
299
gmcgarry
1.26
300         *argofsp = argofs;
gmcgarry
1.15
301 }
302
gmcgarry
1.1
303
304 /*
gmcgarry
1.11
305  * Beginning-of-function code:
306  *
307  * 'sp' is an array of indices in symtab for the arguments
308  * 'cnt' is the number of arguments
309  */
310 void
311 bfcode(struct symtab **spint cnt)
312 {
313         union arglist *usym;
314         int saveallargs = 0;
gmcgarry
1.17
315         int iargofs = 0;
gmcgarry
1.11
316
gmcgarry
1.26
317         /*
318          * Detect if this function has ellipses and save all
319          * argument registers onto stack.
320          */
321         usym = cftnsp->sdf->dfun;
322         while (usym && usym->type != TNULL) {
323                 if (usym->type == TELLIPSIS) {
324                         saveallargs = 1;
325                         break;
326                 }
327                 ++usym;
328         }
gmcgarry
1.11
329
gmcgarry
1.16
330         /* if returning a structure, move the hidden argument into a TEMP */
gmcgarry
1.26
331         if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
gmcgarry
1.15
332                 param_retstruct();
gmcgarry
1.17
333                 ++argofs;
gmcgarry
1.11
334         }
335
gmcgarry
1.26
336         /* recalculate the arg offset and create TEMP moves */
337         for (i = 0i < cnti++) {
gmcgarry
1.11
338
gmcgarry
1.15
339                 if (sp[i] == NULL)
340                         continue;
341
gmcgarry
1.26
342                 if ((argofs >= NARGREGS) && !xtemps)
343                         break;
gmcgarry
1.15
344
gmcgarry
1.26
345                 if (argofs > NARGREGS) {
346                         putintemp(sp[i]);
347                 } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) {
gmcgarry
1.17
348                         param_struct(sp[i], &argofs);
gmcgarry
1.26
349                 } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) {
350                         param_64bit(sp[i], &argofsxtemps && !saveallargs);
351                 } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) {
gmcgarry
1.11
352                         if (features(FEATURE_HARDFLOAT))
gmcgarry
1.26
353                                 param_double(sp[i], &argofs,
gmcgarry
1.13
354                                     xtemps && !saveallargs);
gmcgarry
1.11
355                         else
gmcgarry
1.26
356                                 param_64bit(sp[i], &argofs,
gmcgarry
1.11
357                                     xtemps && !saveallargs);
gmcgarry
1.26
358                 } else if (sp[i]->stype == FLOAT) {
gmcgarry
1.11
359                         if (features(FEATURE_HARDFLOAT))
gmcgarry
1.26
360                                 param_float(sp[i], &argofs,
gmcgarry
1.13
361                                     xtemps && !saveallargs);
gmcgarry
1.11
362                         else
gmcgarry
1.26
363                                 param_32bit(sp[i], &argofs,
gmcgarry
1.11
364                                     xtemps && !saveallargs);
gmcgarry
1.26
365                 } else {
366                         param_32bit(sp[i], &argofsxtemps && !saveallargs);
gmcgarry
1.11
367                 }
gmcgarry
1.26
368         }
gmcgarry
1.11
369
gmcgarry
1.26
370         /* if saveallargs, save the rest of the args onto the stack */
371         while (saveallargs && argofs < NARGREGS) {
gmcgarry
1.11
372                 NODE *p, *q;
gmcgarry
1.17
373                 int off = ARGINIT/SZINT + argofs;
ragge
1.22
374                 q = block(REGNILNILINT00);
gmcgarry
1.17
375                 regno(q) = R0 + argofs++;
ragge
1.22
376                 p = block(REGNILNILINT00);
gmcgarry
1.11
377                 regno(p) = FPREG;
ragge
1.22
378                 p = block(PLUSpbcon(4*off), INT00);
379                 p = block(UMULpNILINT00);
gmcgarry
1.11
380                 p = buildtree(ASSIGNpq);
381                 ecomp(p);
382         }
383
384 }
385
386 /*
gmcgarry
1.1
387  * End-of-Function code:
388  */
389 void
plunky
1.27
390 efcode(void)
gmcgarry
1.1
391 {
gmcgarry
1.4
392         NODE *p, *q;
393         int tempnr;
394
gmcgarry
1.1
395         if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
396                 return;
gmcgarry
1.4
397
398         /*
399          * At this point, the address of the return structure on
400          * has been FORCEd to RETREG, which is R0.
401          * We want to copy the contents from there to the address
402          * we placed into the tempnode "rvnr".
403          */
404
405         /* move the pointer out of R0 to a tempnode */
gmcgarry
1.26
406         q = block(REGNILNILPTR+STRTY0cftnsp->sap);
gmcgarry
1.4
407         q->n_rval = R0;
gmcgarry
1.26
408         p = tempnode(0PTR+STRTY0cftnsp->sap);
ragge
1.6
409         tempnr = regno(p);
gmcgarry
1.4
410         p = buildtree(ASSIGNpq);
411         ecomp(p);
412
413         /* get the address from the tempnode */
gmcgarry
1.26
414         q = tempnode(tempnrPTR+STRTY0cftnsp->sap);
gmcgarry
1.4
415         q = buildtree(UMULqNIL);
416         
417         /* now, get the structure destination */
gmcgarry
1.26
418         p = tempnode(rvnrPTR+STRTY0cftnsp->sap);
gmcgarry
1.4
419         p = buildtree(UMULpNIL);
420
421         /* struct assignment */
422         p = buildtree(ASSIGNpq);
423         ecomp(p);
gmcgarry
1.1
424 }
425
426 /*
427  * End-of-job: called just before final exit.
428  */
429 void
plunky
1.27
430 ejobcode(int flag)
gmcgarry
1.1
431 {
plunky
1.24
432         printf("\t.ident \"PCC: %s\"\n"VERSSTR);
gmcgarry
1.1
433 }
434
435 /*
436  * Beginning-of-job: called before compilation starts
437  *
438  * Initialise data structures specific for the local machine.
439  */
440 void
plunky
1.27
441 bjobcode(void)
gmcgarry
1.1
442 {
443 }
444
445 /*
446  * fix up type of field p
447  */
448 void
449 fldty(struct symtab *p)
450 {
451 }
452
gmcgarry
1.4
453 /*
454  * Build target-dependent switch tree/table.
455  *
456  * Return 1 if successfull, otherwise return 0 and the
457  * target-independent tree will be used.
458  */
stefan
1.3
459 int
460 mygenswitch(int numTWORD typestruct swents **pint n)
gmcgarry
1.1
461 {
stefan
1.3
462         return 0;
gmcgarry
1.1
463 }
464
gmcgarry
1.13
465
466 /*
467  * Straighten a chain of CM ops so that the CM nodes
468  * only appear on the left node.
469  *
gmcgarry
1.26
470  *        CM           CM
471  *      CM  CM     CM  b
472  *       x y  a b       CM  a
473  *                    x  y
gmcgarry
1.13
474  */
475 static NODE *
476 straighten(NODE *p)
477 {
478         NODE *r = p->n_right;
479
480         if (p->n_op != CM || r->n_op != CM)
481                 return p;
482
483         p->n_right = r->n_left;
484         r->n_left = p;
485
486         return r;
487 }
488
gmcgarry
1.15
489 static NODE *
490 reverse1(NODE *pNODE *a)
491 {
492         NODE *l = p->n_left;
493         NODE *r = p->n_right;
494
495         a->n_right = r;
496         p->n_left = a;
497
498         if (l->n_op == CM) {
499                 return reverse1(lp);
500         } else {
501                 p->n_right = l;
502                 return p;
503         }
504 }
505
506 /*
507  * Reverse a chain of CM ops
508  */
509 static NODE *
510 reverse(NODE *p)
511 {
512         NODE *l = p->n_left;
513         NODE *r = p->n_right;
514
515         p->n_left = r;
516
517         if (l->n_op == CM)
518                 return reverse1(lp);
519
520         p->n_right = l;
521
522         return p;
523 }
524
gmcgarry
1.13
525
gmcgarry
1.11
526 /* push arg onto the stack */
527 /* called by moveargs() */
528 static NODE *
529 pusharg(NODE *pint *regp)
530 {
gmcgarry
1.15
531         NODE *q;
532         int sz;
gmcgarry
1.11
533
gmcgarry
1.26
534         /* convert to register size, if smaller */
535         sz = tsize(p->n_typep->n_dfp->n_ap);
536         if (sz < SZINT)
537                 p = block(SCONVpNILINT00);
gmcgarry
1.11
538
gmcgarry
1.26
539         q = block(REGNILNILINT00);
540         regno(q) = SP;
gmcgarry
1.12
541
542         if (szty(p->n_type) == 1) {
543                 ++(*regp);
ragge
1.22
544                 q = block(MINUSEQqbcon(4), INT00);
gmcgarry
1.12
545         } else {
gmcgarry
1.13
546                 (*regp) += 2;
ragge
1.22
547                 q = block(MINUSEQqbcon(8), INT00);
gmcgarry
1.12
548         }
gmcgarry
1.11
549
gmcgarry
1.26
550         q = block(UMULqNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.11
551
gmcgarry
1.12
552         return buildtree(ASSIGNqp);
gmcgarry
1.11
553 }
554
gmcgarry
1.13
555 /* setup call stack with 32-bit argument */
556 /* called from moveargs() */
557 static NODE *
558 movearg_32bit(NODE *pint *regp)
559 {
560         int reg = *regp;
561         NODE *q;
562
gmcgarry
1.26
563         q = block(REGNILNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.13
564         regno(q) = reg++;
565         q = buildtree(ASSIGNqp);
566
567         *regp = reg;
568         return q;
569 }
570
gmcgarry
1.11
571 /* setup call stack with 64-bit argument */
572 /* called from moveargs() */
573 static NODE *
574 movearg_64bit(NODE *pint *regp)
575 {
gmcgarry
1.26
576         int reg = *regp;
577         NODE *q, *r;
gmcgarry
1.11
578
579 #if ALLONGLONG == 64
gmcgarry
1.26
580         /* alignment */
581         ++reg;
582         reg &= ~1;
gmcgarry
1.13
583         *regp = reg;
gmcgarry
1.11
584 #endif
585
gmcgarry
1.26
586         if (reg > R3) {
587                 q = pusharg(pregp);
gmcgarry
1.13
588         } else if (reg == R3) {
589                 /* half in and half out of the registers */
590                 r = tcopy(p);
gmcgarry
1.15
591                 if (!features(FEATURE_BIGENDIAN)) {
ragge
1.22
592                         q = block(SCONVpNILINT00);
gmcgarry
1.15
593                         q = movearg_32bit(qregp);     /* little-endian */
594                         r = buildtree(RSrbcon(32));
ragge
1.22
595                         r = block(SCONVrNILINT00);
gmcgarry
1.15
596                         r = pusharg(rregp); /* little-endian */
gmcgarry
1.14
597                 } else {
gmcgarry
1.15
598                         q = buildtree(RSpbcon(32));
ragge
1.22
599                         q = block(SCONVqNILINT00);
gmcgarry
1.15
600                         q = movearg_32bit(qregp);     /* big-endian */
ragge
1.22
601                         r = block(SCONVrNILINT00);
gmcgarry
1.15
602                         r = pusharg(rregp); /* big-endian */
gmcgarry
1.14
603                 }
gmcgarry
1.26
604                 q = straighten(block(CMqrp->n_typep->n_dfp->n_ap));
605         } else {
606                 q = block(REGNILNILp->n_typep->n_dfp->n_ap);
607                 regno(q) = R0R1 + (reg - R0);
608                 q = buildtree(ASSIGNqp);
609                 *regp = reg + 2;
610         }
gmcgarry
1.11
611
gmcgarry
1.26
612         return q;
gmcgarry
1.11
613 }
614
gmcgarry
1.13
615 /* setup call stack with float/double argument */
gmcgarry
1.11
616 /* called from moveargs() */
617 static NODE *
gmcgarry
1.13
618 movearg_float(NODE *pint *regp)
gmcgarry
1.11
619 {
gmcgarry
1.15
620         NODE *q, *r;
621         TWORD ty = INCREF(p->n_type);
gmcgarry
1.13
622         int tmpnr;
gmcgarry
1.11
623
gmcgarry
1.26
624         /*
625          * Floats are passed in the general registers for
gmcgarry
1.13
626          * compatibily with libraries compiled to handle soft-float.
gmcgarry
1.26
627          */
gmcgarry
1.11
628
gmcgarry
1.15
629         if (xtemps) {
630                 /* bounce on TOS */
gmcgarry
1.26
631                 r = block(REGNILNILtyp->n_dfp->n_ap);
gmcgarry
1.15
632                 regno(r) = SP;
gmcgarry
1.26
633                 r = block(PLUSrbcon(-4), typ->n_dfp->n_ap);
634                 r = block(UMULrNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.15
635                 r = buildtree(ASSIGNrp);
636                 ecomp(r);
637
638                 /* bounce into temp */
ragge
1.22
639                 r = block(REGNILNILPTR+INT00);
gmcgarry
1.15
640                 regno(r) = SP;
ragge
1.22
641                 r = block(PLUSrbcon(-8), PTR+INT00);
642                 r = block(UMULrNILINT00);
643                 q = tempnode(0INT00);
gmcgarry
1.15
644                 tmpnr = regno(q);
645                 r = buildtree(ASSIGNqr);
646                 ecomp(r);
647         } else {
648                 /* copy directly into temp */
gmcgarry
1.26
649                 q = tempnode(0p->n_typep->n_dfp->n_ap);
gmcgarry
1.15
650                 tmpnr = regno(q);
651                 r = buildtree(ASSIGNqp);
652                 ecomp(r);
653         }
654
655         /* copy from temp to register parameter */
ragge
1.22
656         r = tempnode(tmpnrINT00);
657         q = block(REGNILNILINT00);
gmcgarry
1.15
658         regno(q) = (*regp)++;
659         p = buildtree(ASSIGNqr);
660
661         return p;
662 }
663
664 /* setup call stack with float/double argument */
665 /* called from moveargs() */
666 static NODE *
667 movearg_double(NODE *pint *regp)
668 {
669         NODE *q, *r;
670         TWORD ty = INCREF(p->n_type);
671         int tmpnr;
672
673         if (xtemps) {
674                 /* bounce on TOS */
gmcgarry
1.26
675                 r = block(REGNILNILtyp->n_dfp->n_ap);
gmcgarry
1.15
676                 regno(r) = SP;
gmcgarry
1.26
677                 r = block(PLUSrbcon(-8), typ->n_dfp->n_ap);
678                 r = block(UMULrNILp->n_typep->n_dfp->n_ap);
gmcgarry
1.15
679                 r = buildtree(ASSIGNrp);
680                 ecomp(r);
681
682                 /* bounce into temp */
ragge
1.22
683                 r = block(REGNILNILPTR+LONGLONG00);
gmcgarry
1.15
684                 regno(r) = SP;
ragge
1.22
685                 r = block(PLUSrbcon(-8), PTR+LONGLONG00);
686                 r = block(UMULrNILLONGLONG00);
687                 q = tempnode(0LONGLONG00);
gmcgarry
1.15
688                 tmpnr = regno(q);
689                 r = buildtree(ASSIGNqr);
690                 ecomp(r);
gmcgarry
1.13
691         } else {
gmcgarry
1.15
692                 /* copy directly into temp */
gmcgarry
1.26
693                 q = tempnode(0p->n_typep->n_dfp->n_ap);
gmcgarry
1.15
694                 tmpnr = regno(q);
695                 r = buildtree(ASSIGNqp);
696                 ecomp(r);
697         }
698
699         /* copy from temp to register parameter */
ragge
1.22
700         r = tempnode(tmpnrLONGLONG00);
701         q = block(REGNILNILLONGLONG00);
gmcgarry
1.15
702         regno(q) = R0R1 - R0 + (*regp);
703         p = buildtree(ASSIGNqr);
704
gmcgarry
1.26
705         (*regp) += 2;
gmcgarry
1.15
706
707         return p;
708 }
709
710
711 /* setup call stack with a structure */
712 /* called from moveargs() */
713 static NODE *
714 movearg_struct(NODE *pint *regp)
715 {
716         int reg = *regp;
717         NODE *l, *q, *t, *r;
718         int tmpnr;
719         int navail;
720         int num;
721         int sz;
722         int ty;
723         int i;
724
725         assert(p->n_op == STARG);
726
727         navail = NARGREGS - (reg - R0);
728         navail = navail < 0 ? 0 : navail;
gmcgarry
1.26
729         sz = tsize(p->n_typep->n_dfp->n_ap) / SZINT;
gmcgarry
1.15
730         num = sz > navail ? navail : sz;
731
732         /* remove STARG node */
733         l = p->n_left;
734         nfree(p);
735         ty = l->n_type;
736
737         /*
738          * put it into a TEMP, rather than tcopy(), since the tree
739          * in p may have side-affects
740          */
gmcgarry
1.26
741         t = tempnode(0tyl->n_dfl->n_ap);
gmcgarry
1.15
742         tmpnr = regno(t);
743         q = buildtree(ASSIGNtl);
744
745         /* copy structure into registers */
746         for (i = 0i < numi++) {
gmcgarry
1.26
747                 t = tempnode(tmpnrty00);
748                 t = block(SCONVtNILPTR+INT00);
749                 t = block(PLUStbcon(4*i), PTR+INT00);
750                 t = buildtree(UMULtNIL);
751
752                 r = block(REGNILNILINT00);
753                 regno(r) = reg++;
754                 r = buildtree(ASSIGNrt);
gmcgarry
1.15
755
gmcgarry
1.26
756                 q = block(CMqrINT00);
gmcgarry
1.15
757         }
758
759         /* put the rest of the structure on the stack */
760         for (i = numi < szi++) {
gmcgarry
1.26
761                 t = tempnode(tmpnrty00);
762                 t = block(SCONVtNILPTR+INT00);
763                 t = block(PLUStbcon(4*i), PTR+INT00);
764                 t = buildtree(UMULtNIL);
765                 r = pusharg(t, &reg);
766                 q = block(CMqrINT00);
gmcgarry
1.13
767         }
gmcgarry
1.11
768
gmcgarry
1.15
769         q = reverse(q);
770
771         *regp = reg;
772         return q;
gmcgarry
1.11
773 }
gmcgarry
1.1
774
gmcgarry
1.15
775
gmcgarry
1.11
776 static NODE *
gmcgarry
1.13
777 moveargs(NODE *pint *regp)
gmcgarry
1.1
778 {
gmcgarry
1.26
779         NODE *r, **rp;
780         int reg;
gmcgarry
1.11
781
gmcgarry
1.26
782         if (p->n_op == CM) {
783                 p->n_left = moveargs(p->n_leftregp);
784                 r = p->n_right;
785                 rp = &p->n_right;
786         } else {
787                 r = p;
788                 rp = &p;
789         }
gmcgarry
1.1
790
gmcgarry
1.26
791         reg = *regp;
gmcgarry
1.1
792
gmcgarry
1.26
793         if (reg > R3 && r->n_op != STARG) {
794                 *rp = pusharg(rregp);
gmcgarry
1.15
795         } else if (r->n_op == STARG) {
796                 *rp = movearg_struct(rregp);
gmcgarry
1.26
797         } else if (DEUNSIGN(r->n_type) == LONGLONG) {
798                 *rp = movearg_64bit(rregp);
gmcgarry
1.11
799         } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
gmcgarry
1.15
800                 *rp = movearg_double(rregp);
gmcgarry
1.11
801         } else if (r->n_type == FLOAT) {
gmcgarry
1.13
802                 *rp = movearg_float(rregp);
gmcgarry
1.26
803         } else {
804                 *rp = movearg_32bit(rregp);
805         }
gmcgarry
1.1
806
gmcgarry
1.15
807         return straighten(p);
808 }
809
810 /*
811  * Fixup arguments to pass pointer-to-struct as first argument.
812  *
813  * called from funcode().
814  */
815 static NODE *
816 retstruct(NODE *p)
817 {
gmcgarry
1.26
818         NODE *l, *r, *t, *q;
819         TWORD ty;
gmcgarry
1.15
820
gmcgarry
1.26
821         l = p->n_left;
822         r = p->n_right;
gmcgarry
1.15
823
gmcgarry
1.26
824         ty = DECREF(l->n_type) - FTN;
gmcgarry
1.15
825
gmcgarry
1.26
826 //      assert(tsize(ty, l->n_df, l->n_ap) == SZINT);
gmcgarry
1.11
827
gmcgarry
1.26
828         /* structure assign */
829         q = tempnode(0tyl->n_dfl->n_ap);
830         q = buildtree(ADDROFqNIL);
831
832         /* insert hidden assignment at beginning of list */
833         if (r->n_op != CM) {
834                 p->n_right = block(CMqrINCREF(ty), l->n_dfl->n_ap);
835         } else {
836                 for (t = rt->n_left->n_op == CMt = t->n_left)
837                         ;
838                 t->n_left = block(CMqt->n_leftINCREF(ty),
839                             l->n_dfl->n_ap);
840         }
841
842         return p;
gmcgarry
1.1
843 }
844
845 /*
846  * Called with a function call with arguments as argument.
847  * This is done early in buildtree() and only done once.
848  */
849 NODE *
850 funcode(NODE *p)
851 {
gmcgarry
1.11
852         int reg = R0;
gmcgarry
1.4
853
gmcgarry
1.15
854         if (p->n_type == STRTY+FTN || p->n_type == UNIONTY+FTN) {
855                 p = retstruct(p);
gmcgarry
1.11
856                 reg = R1;
gmcgarry
1.15
857         }
gmcgarry
1.11
858
gmcgarry
1.13
859         p->n_right = moveargs(p->n_right, &reg);
gmcgarry
1.4
860
gmcgarry
1.15
861         if (p->n_right == NULL)
862                 p->n_op += (UCALL - CALL);
863
gmcgarry
1.1
864         return p;
865 }
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-08-31 00:13 +0200