Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20100530190004

Diff

Diff from 1.22 to:

Annotations

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

Annotated File View

ragge
1.22
1 /*      $Id: code.c,v 1.22 2010/05/30 19:00:04 ragge Exp $      */
mickey
1.1
2 /*
3  * Copyright (c) 2008 Michael Shalayeff
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 # include "pass1.h"
32
ragge
1.11
33 static int nssengprnrsprsaoff;
ragge
1.14
34 static int thisssethisgprthisrsp;
ragge
1.8
35 enum { INTEGER = 1INTMEMSSESSEMEMX87STRREGSTRMEM };
ragge
1.10
36 static const int argregsi[] = { RDIRSIRDXRCXR08R09 };
ragge
1.11
37 /*
38  * The Register Save Area looks something like this.
39  * It is put first on stack with fixed offsets.
40  * struct {
41  *      long regs[6];
42  *      double xmm[8][2]; // 16 byte in width
43  * };
44  */
45 #define RSASZ           (6*SZLONG+8*2*SZDOUBLE)
46 #define RSALONGOFF(x)   (RSASZ-(x)*SZLONG)
47 #define RSADBLOFF(x)    ((8*2*SZDOUBLE)-(x)*SZDOUBLE*2)
48 /* va_list */
49 #define VAARGSZ         (SZINT*2+SZPOINT(CHAR)*2)
50 #define VAGPOFF(x)      (x)
51 #define VAFPOFF(x)      (x-SZINT)
52 #define VAOFA(x)        (x-SZINT-SZINT)
53 #define VARSA(x)        (x-SZINT-SZINT-SZPOINT(0))
mickey
1.1
54
55 int lastloc = -1;
ragge
1.18
56 static int stroffset;
mickey
1.1
57
ragge
1.8
58 static int argtyp(TWORD tunion dimfun *dfstruct suedef *sue);
ragge
1.14
59 static NODE *movtomem(NODE *pint offint reg);
ragge
1.18
60 static NODE *movtoreg(NODE *pint rno);
ragge
1.8
61
mickey
1.1
62 /*
63  * Define everything needed to print out some data (or text).
64  * This means segment, alignment, visibility, etc.
65  */
66 void
67 defloc(struct symtab *sp)
68 {
69         extern char *nextsect;
70         static char *loctbl[] = { "text""data""section .rodata" };
ragge
1.6
71         int weak = 0;
ragge
1.18
72         char *name;
mickey
1.1
73         TWORD t;
74         int s;
75
76         if (sp == NULL) {
77                 lastloc = -1;
78                 return;
79         }
80         t = sp->stype;
81         s = ISFTN(t) ? PROG : ISCON(cqual(tsp->squal)) ? RDATA : DATA;
ragge
1.18
82         if ((name = sp->soname) == NULL)
83                 name = exname(sp->sname);
mickey
1.1
84 #ifdef TLS
85         if (sp->sflags & STLS) {
86                 if (s != DATA)
87                         cerror("non-data symbol in tls section");
88                 nextsect = ".tdata";
89         }
90 #endif
ragge
1.6
91 #ifdef GCC_COMPAT
92         {
93                 struct gcc_attrib *ga;
94
95                 if ((ga = gcc_get_attr(sp->ssueGCC_ATYP_SECTION)) != NULL)
96                         nextsect = ga->a1.sarg;
97                 if ((ga = gcc_get_attr(sp->ssueGCC_ATYP_WEAK)) != NULL)
98                         weak = 1;
ragge
1.18
99                 if (gcc_get_attr(sp->ssueGCC_ATYP_DESTRUCTOR)) {
100                         printf("\t.section\t.dtors,\"aw\",@progbits\n");
101                         printf("\t.align 8\n\t.quad\t%s\n"name);
102                         lastloc = -1;
103                 }
104                 if (gcc_get_attr(sp->ssueGCC_ATYP_CONSTRUCTOR)) {
105                         printf("\t.section\t.ctors,\"aw\",@progbits\n");
106                         printf("\t.align 8\n\t.quad\t%s\n"name);
107                         lastloc = -1;
108                 }
ragge
1.20
109                 if ((ga = gcc_get_attr(sp->ssueGCC_ATYP_VISIBILITY)) &&
110                     strcmp(ga->a1.sarg"default"))
ragge
1.19
111                         printf("\t.%s %s\n"ga->a1.sargname);
ragge
1.6
112         }
113 #endif
114
mickey
1.1
115         if (nextsect) {
116                 printf("        .section %s\n"nextsect);
117                 nextsect = NULL;
118                 s = -1;
119         } else if (s != lastloc)
120                 printf("        .%s\n"loctbl[s]);
121         lastloc = s;
122         while (ISARY(t))
123                 t = DECREF(t);
ragge
1.3
124         s = ISFTN(t) ? ALINT : talign(tsp->ssue);
125         if (s > ALCHAR)
126                 printf("        .align %d\n"s/ALCHAR);
ragge
1.6
127         if (weak)
128                 printf("        .weak %s\n"name);
mickey
1.16
129         else if (sp->sclass == EXTDEF) {
130                 printf("\t.globl %s\n"name);
131                 printf("\t.type %s,@%s\n"name,
132                     ISFTN(t)? "function" : "object");
133         }
mickey
1.1
134         if (sp->slevel == 0)
ragge
1.6
135                 printf("%s:\n"name);
mickey
1.1
136         else
137                 printf(LABFMT ":\n"sp->soffset);
138 }
139
140 /*
141  * code for the end of a function
142  * deals with struct return here
143  */
144 void
145 efcode()
146 {
ragge
1.18
147         struct symtab *sp;
mickey
1.1
148         extern int gotnr;
ragge
1.18
149         TWORD t;
ragge
1.21
150         NODE *p, *r, *l;
151         int o;
mickey
1.1
152
153         gotnr = 0;      /* new number for next fun */
ragge
1.18
154         sp = cftnsp;
155         t = DECREF(sp->stype);
ragge
1.21
156         if (t != STRTY && t != UNIONTY)
mickey
1.1
157                 return;
ragge
1.18
158         if (argtyp(tsp->sdfsp->ssue) != STRMEM)
159                 return;
160
ragge
1.21
161         /* call memcpy() to put return struct at destination */
162 #define  cmop(x,y) block(CM, x, y, INT, 0, MKSUE(INT))
163         r = tempnode(stroffsetINCREF(t), sp->sdfsp->ssue);
164         l = block(REGNILNILINCREF(t), sp->sdfsp->ssue);
165         regno(l) = RAX;
166         o = tsize(tsp->sdfsp->ssue)/SZCHAR;
167         r = cmop(cmop(rl), bcon(o));
168
169         blevel++; /* Remove prototype at exit of function */
170         sp = lookup(addname("memcpy"), 0);
171         if (sp->stype == UNDEF) {
172                 sp->ssue = MKSUE(VOID);
173                 p = talloc();
174                 p->n_op = NAME;
175                 p->n_sp = sp;
176                 p->n_sue = sp->ssue;
177                 p->n_type = VOID|FTN|(PTR<<TSHIFT);
178                 defid(pEXTERN);
179                 nfree(p);
180         }
181         blevel--;
182
183         p = doacall(spnametree(sp), r);
mickey
1.1
184         ecomp(p);
ragge
1.21
185         
186
187         /* RAX contains destination after memcpy() */
mickey
1.1
188 }
189
190 /*
191  * code for the beginning of a function; a is an array of
192  * indices in symtab for the arguments; n is the number
193  */
194 void
ragge
1.8
195 bfcode(struct symtab **sint cnt)
mickey
1.1
196 {
ragge
1.11
197         union arglist *al;
ragge
1.8
198         struct symtab *sp;
199         NODE *p, *r;
200         int irnotyp;
mickey
1.1
201
202         /* recalculate the arg offset and create TEMP moves */
ragge
1.8
203         /* Always do this for reg, even if not optimizing, to free arg regs */
ragge
1.9
204         nsse = ngpr = 0;
205         nrsp = ARGINIT;
ragge
1.17
206         if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
207                 sp = cftnsp;
ragge
1.18
208                 if (argtyp(DECREF(sp->stype), sp->sdfsp->ssue) == STRMEM) {
209                         r = block(REGNILNILLONG0MKSUE(LONG));
ragge
1.21
210                         regno(r) = argregsi[ngpr++];
ragge
1.18
211                         p = tempnode(0r->n_typer->n_dfr->n_sue);
212                         stroffset = regno(p);
213                         ecomp(buildtree(ASSIGNpr));
214                 }
ragge
1.17
215         }
216
ragge
1.8
217         for (i = 0i < cnti++) {
218                 sp = s[i];
219
220                 if (sp == NULL)
221                         continue/* XXX when happens this? */
222
223                 switch (typ = argtyp(sp->stypesp->sdfsp->ssue)) {
224                 case INTEGER:
225                 case SSE:
226                         if (typ == SSE)
227                                 rno = XMM0 + nsse++;
228                         else
229                                 rno = argregsi[ngpr++];
230                         r = block(REGNILNILsp->stypesp->sdfsp->ssue);
231                         regno(r) = rno;
232                         p = tempnode(0sp->stypesp->sdfsp->ssue);
233                         sp->soffset = regno(p);
234                         sp->sflags |= STNODE;
235                         ecomp(buildtree(ASSIGNpr));
236                         break;
ragge
1.9
237
238                 case INTMEM:
239                         sp->soffset = nrsp;
240                         nrsp += SZLONG;
241                         if (xtemps) {
242                                 p = tempnode(0sp->stypesp->sdfsp->ssue);
243                                 p = buildtree(ASSIGNpnametree(sp));
244                                 sp->soffset = regno(p->n_left);
245                                 sp->sflags |= STNODE;
246                                 ecomp(p);
247                         }
248                         break;
249
ragge
1.17
250                 case STRMEM/* Struct in memory */
251                         sp->soffset = nrsp;
252                         nrsp += tsize(sp->stypesp->sdfsp->ssue);
253                         break;
254
255                 case STRREG/* Struct in register */
256                         /* Allocate space on stack for the struct */
257                         /* For simplicity always fetch two longwords */
258                         autooff += (2*SZLONG);
259
260                         r = block(REGNILNILLONG0MKSUE(LONG));
261                         regno(r) = argregsi[ngpr++];
262                         ecomp(movtomem(r, -autooffFPREG));
263
264                         if (tsize(sp->stypesp->sdfsp->ssue) > SZLONG) {
265                                 r = block(REGNILNILLONG0MKSUE(LONG));
266                                 regno(r) = argregsi[ngpr++];
267                                 ecomp(movtomem(r, -autooff+SZLONGFPREG));
268                         }
269
270                         sp->soffset = -autooff;
271                         break;
272
ragge
1.8
273                 default:
ragge
1.9
274                         cerror("bfcode: %d"typ);
mickey
1.1
275                 }
276         }
ragge
1.11
277
278         /* Check if there are varargs */
279         if (cftnsp->sdf == NULL || cftnsp->sdf->dfun == NULL)
280                 return/* no prototype */
281         al = cftnsp->sdf->dfun;
ragge
1.15
282
ragge
1.11
283         for (; al->type != TELLIPSISal++) {
284                 if (al->type == TNULL)
285                         return;
ragge
1.15
286                 if (BTYPE(al->type) == STRTY || BTYPE(al->type) == UNIONTY ||
287                     ISARY(al->type))
ragge
1.11
288                         al++;
289         }
290
291         /* fix stack offset */
292         SETOFF(autooffALMAX);
293
294         /* Save reg arguments in the reg save area */
295         p = NIL;
296         for (i = ngpri < 6i++) {
297                 r = block(REGNILNILLONG0MKSUE(LONG));
298                 regno(r) = argregsi[i];
ragge
1.14
299                 r = movtomem(r, -RSALONGOFF(i)-autooffFPREG);
ragge
1.11
300                 p = (p == NIL ? r : block(COMOPprINT0MKSUE(INT)));
301         }
302         for (i = nssei < 8i++) {
303                 r = block(REGNILNILDOUBLE0MKSUE(DOUBLE));
304                 regno(r) = i + XMM0;
ragge
1.14
305                 r = movtomem(r, -RSADBLOFF(i)-autooffFPREG);
ragge
1.11
306                 p = (p == NIL ? r : block(COMOPprINT0MKSUE(INT)));
307         }
308         autooff += RSASZ;
309         rsaoff = autooff;
ragge
1.14
310         thissse = nsse;
311         thisgpr = ngpr;
312         thisrsp = nrsp;
ragge
1.11
313
314         ecomp(p);
mickey
1.1
315 }
316
317
318 /*
319  * by now, the automatics and register variables are allocated
320  */
321 void
322 bccode()
323 {
324         SETOFF(autooffSZINT);
325 }
326
327 /* called just before final exit */
328 /* flag is 1 if errors, 0 if none */
329 void
330 ejobcode(int flag )
331 {
332 #define _MKSTR(x) #x
333 #define MKSTR(x) _MKSTR(x)
334 #define OS MKSTR(TARGOS)
335         printf("\t.ident \"PCC: %s (%s)\"\n\t.end\n"PACKAGE_STRINGOS);
336 }
337
ragge
1.11
338 /*
339  * Varargs stuff:
340  * The ABI says that va_list should be declared as this typedef.
341  * We handcraft it here and then just reference it.
342  *
343  * typedef struct {
344  *      unsigned int gp_offset;
345  *      unsigned int fp_offset;
346  *      void *overflow_arg_area;
347  *      void *reg_save_area;
348  * } __builtin_va_list[1];
349  */
ragge
1.13
350
ragge
1.11
351 static char *gp_offset, *fp_offset, *overflow_arg_area, *reg_save_area;
ragge
1.13
352
mickey
1.1
353 void
354 bjobcode()
355 {
ragge
1.11
356         struct rstack *rp;
357         NODE *p, *q;
358         char *c;
359
360         gp_offset = addname("gp_offset");
361         fp_offset = addname("fp_offset");
362         overflow_arg_area = addname("overflow_arg_area");
363         reg_save_area = addname("reg_save_area");
364
365         rp = bstruct(NULLSTNAMENULL);
366         p = block(NAMENILNILUNSIGNED0MKSUE(UNSIGNED));
367         soumemb(pgp_offset0);
368         soumemb(pfp_offset0);
369         p->n_type = VOID+PTR;
370         p->n_sue = MKSUE(VOID);
371         soumemb(poverflow_arg_area0);
372         soumemb(preg_save_area0);
373         nfree(p);
374         q = dclstruct(rp);
375         c = addname("__builtin_va_list");
376         p = block(LBbdty(NAMEc), bcon(1), INT0MKSUE(INT));
377         p = tymerge(qp);
378         p->n_sp = lookup(c0);
379         defid(pTYPEDEF);
380         nfree(q);
381         nfree(p);
382 }
383
384 static NODE *
385 mkstkref(int offTWORD typ)
386 {
387         NODE *p;
388
389         p = block(REGNILNILPTR|typ0MKSUE(LONG));
390         regno(p) = FPREG;
391         return buildtree(PLUSpbcon(off/SZCHAR));
392 }
393
394 NODE *
395 amd64_builtin_stdarg_start(NODE *fNODE *a)
396 {
397         NODE *p, *r;
398
399         /* use the values from the function header */
400         p = a->n_left;
401         r = buildtree(ASSIGNstructref(ccopy(p), STREFreg_save_area),
402             mkstkref(-rsaoffVOID));
403         r = buildtree(COMOPr,
404             buildtree(ASSIGNstructref(ccopy(p), STREFoverflow_arg_area),
ragge
1.14
405             mkstkref(thisrspVOID)));
ragge
1.11
406         r = buildtree(COMOPr,
407             buildtree(ASSIGNstructref(ccopy(p), STREFgp_offset),
ragge
1.14
408             bcon(thisgpr*(SZLONG/SZCHAR))));
ragge
1.11
409         r = buildtree(COMOPr,
410             buildtree(ASSIGNstructref(ccopy(p), STREFfp_offset),
ragge
1.14
411             bcon(thissse*(SZDOUBLE*2/SZCHAR)+48)));
ragge
1.11
412
413         tfree(f);
414         tfree(a);
415         return r;
mickey
1.1
416 }
417
ragge
1.12
418 /*
419  * Create a tree that should be like the expression
420  *      ((long *)(l->gp_offset >= 48 ?
421  *          l->overflow_arg_area += 8, l->overflow_arg_area :
422  *          l->gp_offset += 8, l->reg_save_area + l->gp_offset))[-1]
ragge
1.13
423  * ...or similar for floats.
ragge
1.12
424  */
425 static NODE *
ragge
1.13
426 bva(NODE *apTWORD dtchar *otint addtoint max)
ragge
1.12
427 {
428         NODE *cm1, *cm2, *gpo, *ofa, *l1, *qc;
ragge
1.13
429         TWORD nt;
ragge
1.12
430
431         ofa = structref(ccopy(ap), STREFoverflow_arg_area);
ragge
1.13
432         l1 = buildtree(PLUSEQccopy(ofa), bcon(addto));
ragge
1.12
433         cm1 = buildtree(COMOPl1ofa);
434
ragge
1.13
435         gpo = structref(ccopy(ap), STREFot);
436         l1 = buildtree(PLUSEQccopy(gpo), bcon(addto));
ragge
1.12
437         cm2 = buildtree(COMOPl1buildtree(PLUSccopy(gpo),
438             structref(ccopy(ap), STREFreg_save_area)));
439         qc = buildtree(QUEST,
ragge
1.13
440             buildtree(GEgpobcon(max)),
ragge
1.12
441             buildtree(COLONcm1cm2));
ragge
1.13
442
443         nt = (dt == DOUBLE ? DOUBLE : LONG);
444         l1 = block(NAMENILNILnt|PTR0MKSUE(nt));
445         l1 = buildtree(CASTl1qc);
446         qc = l1->n_right;
447         nfree(l1->n_left);
448         nfree(l1);
449
ragge
1.14
450         /* qc has now a real type, for indexing */
451         addto = dt == DOUBLE ? 2 : 1;
ragge
1.13
452         qc = buildtree(UMULbuildtree(PLUSqcbcon(-addto)), NIL);
453
454         l1 = block(NAMENILNILdt0MKSUE(BTYPE(dt)));
ragge
1.12
455         l1 = buildtree(CASTl1qc);
ragge
1.13
456         qc = l1->n_right;
ragge
1.12
457         nfree(l1->n_left);
458         nfree(l1);
ragge
1.13
459
460         return qc;
ragge
1.12
461 }
462
ragge
1.11
463 NODE *
ragge
1.12
464 amd64_builtin_va_arg(NODE *fNODE *a)
465 {
466         NODE *ap, *r;
ragge
1.13
467         TWORD dt;
ragge
1.12
468
469         ap = a->n_left;
ragge
1.13
470         dt = a->n_right->n_type;
471         if (dt <= ULONGLONG || ISPTR(dt)) {
ragge
1.12
472                 /* type might be in general register */
ragge
1.13
473                 r = bva(apdtgp_offset848);
474         } else if (dt == FLOAT || dt == DOUBLE) {
475                 /* Float are promoted to double here */
476                 if (dt == FLOAT)
477                         dt = DOUBLE;
478                 r = bva(apdtfp_offset16RSASZ/SZCHAR);
ragge
1.12
479         } else {
ragge
1.13
480                 uerror("amd64_builtin_va_arg not supported type");
481                 goto bad;
ragge
1.12
482         }
483         tfree(a);
484         tfree(f);
485         return r;
486 bad:
487         uerror("bad argument to __builtin_va_arg");
488         return bcon(0);
489 }
ragge
1.11
490
491 NODE *
ragge
1.13
492 amd64_builtin_va_end(NODE *fNODE *a)
493 {
494         tfree(f);
495         tfree(a);
496         return bcon(0); /* nothing */
497 }
ragge
1.11
498
499 NODE *
500 amd64_builtin_va_copy(NODE *fNODE *a) { cerror("amd64_builtin_va_copy"); return NULL; }
501
ragge
1.7
502 static NODE *
503 movtoreg(NODE *pint rno)
mickey
1.1
504 {
505         NODE *r;
506
ragge
1.9
507         r = block(REGNILNILp->n_typep->n_dfp->n_sue);
ragge
1.7
508         regno(r) = rno;
509         return clocal(buildtree(ASSIGNrp));
510 }  
511
ragge
1.9
512 static NODE *
ragge
1.14
513 movtomem(NODE *pint offint reg)
ragge
1.9
514 {
515         struct symtab s;
516         NODE *r, *l;
517
518         s.stype = p->n_type;
519         s.sdf = p->n_df;
520         s.ssue = p->n_sue;
521         s.soffset = off;
ragge
1.11
522         s.sclass = AUTO;
ragge
1.9
523
524         l = block(REGNILNILPTR+STRTY00);
525         l->n_lval = 0;
ragge
1.14
526         regno(l) = reg;
ragge
1.9
527
528         r = block(NAMENILNILp->n_typep->n_dfp->n_sue);
529         r->n_sp = &s;
530         r = stref(block(STREFlr000));
531
532         return clocal(buildtree(ASSIGNrp));
533 }  
534
ragge
1.7
535
536 /*
537  * AMD64 parameter classification.
538  */
539 static int
ragge
1.8
540 argtyp(TWORD tunion dimfun *dfstruct suedef *sue)
ragge
1.7
541 {
542         int cl = 0;
543
ragge
1.9
544         if (t <= ULONG || ISPTR(t)) {
ragge
1.7
545                 cl = ngpr < 6 ? INTEGER : INTMEM;
546         } else if (t == FLOAT || t == DOUBLE) {
ragge
1.8
547                 cl = nsse < 8 ? SSE : SSEMEM;
ragge
1.7
548         } else if (t == LDOUBLE) {
549                 cl = X87/* XXX */
550         } else if (t == STRTY) {
ragge
1.17
551                 /* XXX no SSEOP handling */
552                 if ((tsize(tdfsue) > 2*SZLONG) ||
553                     (gcc_get_attr(sueGCC_ATYP_PACKED) != NULL))
ragge
1.7
554                         cl = STRMEM;
555                 else
ragge
1.17
556                         cl = STRREG;
ragge
1.7
557         } else
558                 cerror("FIXME: classify");
559         return cl;
560 }
561
562 static void
563 argput(NODE *p)
564 {
565         NODE *q;
ragge
1.17
566         int typrssz;
mickey
1.1
567
ragge
1.7
568         /* first arg may be struct return pointer */
569         /* XXX - check if varargs; setup al */
ragge
1.8
570         switch (typ = argtyp(p->n_typep->n_dfp->n_sue)) {
ragge
1.7
571         case INTEGER:
572         case SSE:
573                 q = talloc();
574                 *q = *p;
575                 if (typ == SSE)
576                         r = XMM0 + nsse++;
577                 else
578                         r = argregsi[ngpr++];
579                 q = movtoreg(qr);
580                 *p = *q;
581                 nfree(q);
582                 break;
583         case X87:
584                 cerror("no long double yet");
585                 break;
ragge
1.9
586
587         case INTMEM:
588                 q = talloc();
589                 *q = *p;
590                 r = nrsp;
591                 nrsp += SZLONG;
ragge
1.14
592                 q = movtomem(qrSTKREG);
ragge
1.9
593                 *p = *q;
594                 nfree(q);
595                 break;
596
ragge
1.17
597         case STRREG/* Struct in registers */
598                 /* Cast to long pointer and move to the registers */
599                 ssz = tsize(p->n_typep->n_dfp->n_sue);
600
601                 if (ssz <= SZLONG) {
602                         q = cast(p->n_leftLONG+PTR0);
603                         q = buildtree(UMULqNIL);
604                         q = movtoreg(qargregsi[ngpr++]);
605                         *p = *q;
606                         nfree(q);
607                 } else if (ssz <= SZLONG*2) {
608                         NODE *qt, *q1, *q2, *ql, *qr;
609
610                         qt = tempnode(0LONG+PTR0MKSUE(LONG));
611                         q1 = ccopy(qt);
612                         q2 = ccopy(qt);
613                         ql = buildtree(ASSIGNqtcast(p->n_left,LONG+PTR0));
614                         qr = movtoreg(buildtree(UMULq1NIL),
615                             argregsi[ngpr++]);
616                         ql = buildtree(COMOPqlqr);
617                         qr = buildtree(UMULbuildtree(PLUSq2bcon(1)), NIL);
618                         qr = movtoreg(qrargregsi[ngpr++]);
619                         q = buildtree(COMOPqlqr);
620                         *p = *q;
621                         nfree(q);
622                 } else
623                         cerror("STRREG");
624                 break;
625
ragge
1.7
626         case STRMEM:
627                 /* Struct moved to memory */
628         default:
ragge
1.9
629                 cerror("argument %d"typ);
mickey
1.1
630         }
ragge
1.7
631 }
mickey
1.1
632
633
634 /*
635  * Called with a function call with arguments as argument.
636  * This is done early in buildtree() and only done once.
637  * Returns p.
638  */
639 NODE *
640 funcode(NODE *p)
641 {
ragge
1.8
642         NODE *l, *r;
mickey
1.1
643
ragge
1.9
644         nsse = ngpr = nrsp = 0;
ragge
1.17
645         /* Check if hidden arg needed */
646         /* If so, add it in pass2 */
647         if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY ||
648             l->n_type == INCREF(FTN)+UNIONTY) {
649                 int ssz = tsize(BTYPE(l->n_type), l->n_dfl->n_sue);
650                 if (ssz > 2*SZLONG)
651                         ngpr++;
652         }
ragge
1.7
653         listf(p->n_rightargput);
ragge
1.8
654
ragge
1.22
655         /* Check if there are varargs */
656         if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) {
657                 ; /* Need RAX */
658         } else {
659                 union arglist *al = l->n_df->dfun;
660
661                 for (; al->type != TELLIPSISal++) {
662                         if (al->type == TNULL)
663                                 return p/* No need */
664                         if (BTYPE(al->type) == STRTY ||
665                             BTYPE(al->type) == UNIONTY ||
666                             ISARY(al->type))
667                                 al++;
668                 }
669         }
670
ragge
1.8
671         /* Always emit number of SSE regs used */
672         l = movtoreg(bcon(nsse), RAX);
673         if (p->n_right->n_op != CM) {
674                 p->n_right = block(CMlp->n_rightINT0MKSUE(INT));
675         } else {
676                 for (r = p->n_rightr->n_left->n_op == CMr = r->n_left)
677                         ;
678                 r->n_left = block(CMlr->n_leftINT0MKSUE(INT));
679         }
mickey
1.1
680         return p;
681 }
682
683 /*
684  * return the alignment of field of type t
685  */
686 int
687 fldal(unsigned int t)
688 {
689         uerror("illegal field type");
690         return(ALINT);
691 }
692
693 /* fix up type of field p */
694 void
695 fldty(struct symtab *p)
696 {
697 }
698
699 /*
700  * XXX - fix genswitch.
701  */
702 int
703 mygenswitch(int numTWORD typestruct swents **pint n)
704 {
705         return 0;
706 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-27 10:24 +0100