Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101028200730

Diff

Diff from 1.32 to:

Annotations

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

Annotated File View

ragge
1.32
1 /*      $Id: code.c,v 1.32 2010/10/28 20:07:30 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.23
58 static int argtyp(TWORD tunion dimfun *dfstruct attr *ap);
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         }
ragge
1.28
80         if (kflag) {
81                 loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits";
82                 loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits";
83         }
mickey
1.1
84         t = sp->stype;
85         s = ISFTN(t) ? PROG : ISCON(cqual(tsp->squal)) ? RDATA : DATA;
ragge
1.18
86         if ((name = sp->soname) == NULL)
87                 name = exname(sp->sname);
mickey
1.1
88 #ifdef TLS
89         if (sp->sflags & STLS) {
90                 if (s != DATA)
91                         cerror("non-data symbol in tls section");
92                 nextsect = ".tdata";
93         }
94 #endif
ragge
1.6
95 #ifdef GCC_COMPAT
96         {
ragge
1.23
97                 struct attr *ga;
ragge
1.6
98
ragge
1.23
99                 if ((ga = attr_find(sp->sapGCC_ATYP_SECTION)) != NULL)
100                         nextsect = ga->sarg(0);
101                 if ((ga = attr_find(sp->sapGCC_ATYP_WEAK)) != NULL)
ragge
1.6
102                         weak = 1;
ragge
1.23
103                 if (attr_find(sp->sapGCC_ATYP_DESTRUCTOR)) {
ragge
1.18
104                         printf("\t.section\t.dtors,\"aw\",@progbits\n");
105                         printf("\t.align 8\n\t.quad\t%s\n"name);
106                         lastloc = -1;
107                 }
ragge
1.23
108                 if (attr_find(sp->sapGCC_ATYP_CONSTRUCTOR)) {
ragge
1.18
109                         printf("\t.section\t.ctors,\"aw\",@progbits\n");
110                         printf("\t.align 8\n\t.quad\t%s\n"name);
111                         lastloc = -1;
112                 }
ragge
1.23
113                 if ((ga = attr_find(sp->sapGCC_ATYP_VISIBILITY)) &&
114                     strcmp(ga->sarg(0), "default"))
115                         printf("\t.%s %s\n"ga->sarg(0), name);
ragge
1.6
116         }
117 #endif
118
mickey
1.1
119         if (nextsect) {
120                 printf("        .section %s\n"nextsect);
121                 nextsect = NULL;
122                 s = -1;
123         } else if (s != lastloc)
124                 printf("        .%s\n"loctbl[s]);
125         lastloc = s;
126         while (ISARY(t))
127                 t = DECREF(t);
ragge
1.23
128         s = ISFTN(t) ? ALINT : talign(tsp->sap);
ragge
1.3
129         if (s > ALCHAR)
130                 printf("        .align %d\n"s/ALCHAR);
ragge
1.6
131         if (weak)
132                 printf("        .weak %s\n"name);
mickey
1.16
133         else if (sp->sclass == EXTDEF) {
134                 printf("\t.globl %s\n"name);
135                 printf("\t.type %s,@%s\n"name,
136                     ISFTN(t)? "function" : "object");
137         }
mickey
1.1
138         if (sp->slevel == 0)
ragge
1.6
139                 printf("%s:\n"name);
mickey
1.1
140         else
141                 printf(LABFMT ":\n"sp->soffset);
142 }
143
144 /*
145  * code for the end of a function
146  * deals with struct return here
147  */
148 void
149 efcode()
150 {
ragge
1.18
151         struct symtab *sp;
mickey
1.1
152         extern int gotnr;
ragge
1.18
153         TWORD t;
ragge
1.21
154         NODE *p, *r, *l;
155         int o;
mickey
1.1
156
157         gotnr = 0;      /* new number for next fun */
ragge
1.18
158         sp = cftnsp;
159         t = DECREF(sp->stype);
ragge
1.21
160         if (t != STRTY && t != UNIONTY)
mickey
1.1
161                 return;
ragge
1.23
162         if (argtyp(tsp->sdfsp->sap) != STRMEM)
ragge
1.18
163                 return;
164
ragge
1.21
165         /* call memcpy() to put return struct at destination */
ragge
1.23
166 #define  cmop(x,y) block(CM, x, y, INT, 0, MKAP(INT))
167         r = tempnode(stroffsetINCREF(t), sp->sdfsp->sap);
168         l = block(REGNILNILINCREF(t), sp->sdfsp->sap);
ragge
1.21
169         regno(l) = RAX;
ragge
1.23
170         o = tsize(tsp->sdfsp->sap)/SZCHAR;
ragge
1.21
171         r = cmop(cmop(rl), bcon(o));
172
173         blevel++; /* Remove prototype at exit of function */
174         sp = lookup(addname("memcpy"), 0);
175         if (sp->stype == UNDEF) {
ragge
1.23
176                 sp->sap = MKAP(VOID);
ragge
1.21
177                 p = talloc();
178                 p->n_op = NAME;
179                 p->n_sp = sp;
ragge
1.23
180                 p->n_ap = sp->sap;
ragge
1.21
181                 p->n_type = VOID|FTN|(PTR<<TSHIFT);
182                 defid(pEXTERN);
183                 nfree(p);
184         }
185         blevel--;
186
187         p = doacall(spnametree(sp), r);
mickey
1.1
188         ecomp(p);
ragge
1.21
189         
190
191         /* RAX contains destination after memcpy() */
mickey
1.1
192 }
193
194 /*
195  * code for the beginning of a function; a is an array of
196  * indices in symtab for the arguments; n is the number
197  */
198 void
ragge
1.8
199 bfcode(struct symtab **sint cnt)
mickey
1.1
200 {
ragge
1.11
201         union arglist *al;
ragge
1.8
202         struct symtab *sp;
203         NODE *p, *r;
204         int irnotyp;
mickey
1.1
205
206         /* recalculate the arg offset and create TEMP moves */
ragge
1.8
207         /* Always do this for reg, even if not optimizing, to free arg regs */
ragge
1.9
208         nsse = ngpr = 0;
209         nrsp = ARGINIT;
ragge
1.17
210         if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
211                 sp = cftnsp;
ragge
1.23
212                 if (argtyp(DECREF(sp->stype), sp->sdfsp->sap) == STRMEM) {
213                         r = block(REGNILNILLONG0MKAP(LONG));
ragge
1.21
214                         regno(r) = argregsi[ngpr++];
ragge
1.23
215                         p = tempnode(0r->n_typer->n_dfr->n_ap);
ragge
1.18
216                         stroffset = regno(p);
217                         ecomp(buildtree(ASSIGNpr));
218                 }
ragge
1.17
219         }
220
ragge
1.8
221         for (i = 0i < cnti++) {
222                 sp = s[i];
223
224                 if (sp == NULL)
225                         continue/* XXX when happens this? */
226
ragge
1.23
227                 switch (typ = argtyp(sp->stypesp->sdfsp->sap)) {
ragge
1.8
228                 case INTEGER:
229                 case SSE:
230                         if (typ == SSE)
231                                 rno = XMM0 + nsse++;
232                         else
233                                 rno = argregsi[ngpr++];
ragge
1.23
234                         r = block(REGNILNILsp->stypesp->sdfsp->sap);
ragge
1.8
235                         regno(r) = rno;
ragge
1.23
236                         p = tempnode(0sp->stypesp->sdfsp->sap);
ragge
1.8
237                         sp->soffset = regno(p);
238                         sp->sflags |= STNODE;
239                         ecomp(buildtree(ASSIGNpr));
240                         break;
ragge
1.9
241
ragge
1.30
242                 case SSEMEM:
243                         sp->soffset = nrsp;
244                         nrsp += SZDOUBLE;
245                         if (xtemps) {
246                                 p = tempnode(0sp->stypesp->sdfsp->sap);
247                                 p = buildtree(ASSIGNpnametree(sp));
248                                 sp->soffset = regno(p->n_left);
249                                 sp->sflags |= STNODE;
250                                 ecomp(p);
251                         }
252                         break;
253
ragge
1.9
254                 case INTMEM:
255                         sp->soffset = nrsp;
256                         nrsp += SZLONG;
257                         if (xtemps) {
ragge
1.23
258                                 p = tempnode(0sp->stypesp->sdfsp->sap);
ragge
1.9
259                                 p = buildtree(ASSIGNpnametree(sp));
260                                 sp->soffset = regno(p->n_left);
261                                 sp->sflags |= STNODE;
262                                 ecomp(p);
263                         }
264                         break;
265
ragge
1.17
266                 case STRMEM/* Struct in memory */
267                         sp->soffset = nrsp;
ragge
1.23
268                         nrsp += tsize(sp->stypesp->sdfsp->sap);
ragge
1.17
269                         break;
270
ragge
1.31
271                 case X87/* long double args */
272                         sp->soffset = nrsp;
273                         nrsp += SZLDOUBLE;
274                         break;
275
ragge
1.17
276                 case STRREG/* Struct in register */
277                         /* Allocate space on stack for the struct */
278                         /* For simplicity always fetch two longwords */
279                         autooff += (2*SZLONG);
280
ragge
1.23
281                         r = block(REGNILNILLONG0MKAP(LONG));
ragge
1.17
282                         regno(r) = argregsi[ngpr++];
283                         ecomp(movtomem(r, -autooffFPREG));
284
ragge
1.23
285                         if (tsize(sp->stypesp->sdfsp->sap) > SZLONG) {
286                                 r = block(REGNILNILLONG0MKAP(LONG));
ragge
1.17
287                                 regno(r) = argregsi[ngpr++];
288                                 ecomp(movtomem(r, -autooff+SZLONGFPREG));
289                         }
290
291                         sp->soffset = -autooff;
292                         break;
293
ragge
1.8
294                 default:
ragge
1.9
295                         cerror("bfcode: %d"typ);
mickey
1.1
296                 }
297         }
ragge
1.11
298
299         /* Check if there are varargs */
300         if (cftnsp->sdf == NULL || cftnsp->sdf->dfun == NULL)
301                 return/* no prototype */
302         al = cftnsp->sdf->dfun;
ragge
1.15
303
ragge
1.11
304         for (; al->type != TELLIPSISal++) {
305                 if (al->type == TNULL)
306                         return;
ragge
1.15
307                 if (BTYPE(al->type) == STRTY || BTYPE(al->type) == UNIONTY ||
308                     ISARY(al->type))
ragge
1.11
309                         al++;
310         }
311
312         /* fix stack offset */
313         SETOFF(autooffALMAX);
314
315         /* Save reg arguments in the reg save area */
316         p = NIL;
317         for (i = ngpri < 6i++) {
ragge
1.23
318                 r = block(REGNILNILLONG0MKAP(LONG));
ragge
1.11
319                 regno(r) = argregsi[i];
ragge
1.14
320                 r = movtomem(r, -RSALONGOFF(i)-autooffFPREG);
ragge
1.23
321                 p = (p == NIL ? r : block(COMOPprINT0MKAP(INT)));
ragge
1.11
322         }
323         for (i = nssei < 8i++) {
ragge
1.23
324                 r = block(REGNILNILDOUBLE0MKAP(DOUBLE));
ragge
1.11
325                 regno(r) = i + XMM0;
ragge
1.14
326                 r = movtomem(r, -RSADBLOFF(i)-autooffFPREG);
ragge
1.23
327                 p = (p == NIL ? r : block(COMOPprINT0MKAP(INT)));
ragge
1.11
328         }
329         autooff += RSASZ;
330         rsaoff = autooff;
ragge
1.14
331         thissse = nsse;
332         thisgpr = ngpr;
333         thisrsp = nrsp;
ragge
1.11
334
335         ecomp(p);
mickey
1.1
336 }
337
338
339 /*
340  * by now, the automatics and register variables are allocated
341  */
342 void
343 bccode()
344 {
345         SETOFF(autooffSZINT);
346 }
347
348 /* called just before final exit */
349 /* flag is 1 if errors, 0 if none */
350 void
351 ejobcode(int flag )
352 {
353 #define _MKSTR(x) #x
354 #define MKSTR(x) _MKSTR(x)
355 #define OS MKSTR(TARGOS)
356         printf("\t.ident \"PCC: %s (%s)\"\n\t.end\n"PACKAGE_STRINGOS);
357 }
358
ragge
1.11
359 /*
360  * Varargs stuff:
361  * The ABI says that va_list should be declared as this typedef.
362  * We handcraft it here and then just reference it.
363  *
364  * typedef struct {
365  *      unsigned int gp_offset;
366  *      unsigned int fp_offset;
367  *      void *overflow_arg_area;
368  *      void *reg_save_area;
369  * } __builtin_va_list[1];
370  */
ragge
1.13
371
ragge
1.11
372 static char *gp_offset, *fp_offset, *overflow_arg_area, *reg_save_area;
ragge
1.13
373
mickey
1.1
374 void
375 bjobcode()
376 {
ragge
1.11
377         struct rstack *rp;
378         NODE *p, *q;
379         char *c;
380
381         gp_offset = addname("gp_offset");
382         fp_offset = addname("fp_offset");
383         overflow_arg_area = addname("overflow_arg_area");
384         reg_save_area = addname("reg_save_area");
385
386         rp = bstruct(NULLSTNAMENULL);
ragge
1.23
387         p = block(NAMENILNILUNSIGNED0MKAP(UNSIGNED));
ragge
1.11
388         soumemb(pgp_offset0);
389         soumemb(pfp_offset0);
390         p->n_type = VOID+PTR;
ragge
1.23
391         p->n_ap = MKAP(VOID);
ragge
1.11
392         soumemb(poverflow_arg_area0);
393         soumemb(preg_save_area0);
394         nfree(p);
395         q = dclstruct(rp);
396         c = addname("__builtin_va_list");
ragge
1.23
397         p = block(LBbdty(NAMEc), bcon(1), INT0MKAP(INT));
ragge
1.11
398         p = tymerge(qp);
399         p->n_sp = lookup(c0);
400         defid(pTYPEDEF);
401         nfree(q);
402         nfree(p);
403 }
404
405 static NODE *
406 mkstkref(int offTWORD typ)
407 {
408         NODE *p;
409
ragge
1.23
410         p = block(REGNILNILPTR|typ0MKAP(LONG));
ragge
1.11
411         regno(p) = FPREG;
412         return buildtree(PLUSpbcon(off/SZCHAR));
413 }
414
415 NODE *
ragge
1.24
416 amd64_builtin_stdarg_start(NODE *fNODE *aTWORD t)
ragge
1.11
417 {
418         NODE *p, *r;
419
420         /* use the values from the function header */
421         p = a->n_left;
422         r = buildtree(ASSIGNstructref(ccopy(p), STREFreg_save_area),
423             mkstkref(-rsaoffVOID));
424         r = buildtree(COMOPr,
425             buildtree(ASSIGNstructref(ccopy(p), STREFoverflow_arg_area),
ragge
1.14
426             mkstkref(thisrspVOID)));
ragge
1.11
427         r = buildtree(COMOPr,
428             buildtree(ASSIGNstructref(ccopy(p), STREFgp_offset),
ragge
1.14
429             bcon(thisgpr*(SZLONG/SZCHAR))));
ragge
1.11
430         r = buildtree(COMOPr,
431             buildtree(ASSIGNstructref(ccopy(p), STREFfp_offset),
ragge
1.14
432             bcon(thissse*(SZDOUBLE*2/SZCHAR)+48)));
ragge
1.11
433
434         tfree(f);
435         tfree(a);
436         return r;
mickey
1.1
437 }
438
ragge
1.12
439 /*
440  * Create a tree that should be like the expression
441  *      ((long *)(l->gp_offset >= 48 ?
442  *          l->overflow_arg_area += 8, l->overflow_arg_area :
443  *          l->gp_offset += 8, l->reg_save_area + l->gp_offset))[-1]
ragge
1.13
444  * ...or similar for floats.
ragge
1.12
445  */
446 static NODE *
ragge
1.29
447 bva(NODE *apNODE *dpchar *otint addtoint max)
ragge
1.12
448 {
449         NODE *cm1, *cm2, *gpo, *ofa, *l1, *qc;
ragge
1.13
450         TWORD nt;
ragge
1.12
451
452         ofa = structref(ccopy(ap), STREFoverflow_arg_area);
ragge
1.13
453         l1 = buildtree(PLUSEQccopy(ofa), bcon(addto));
ragge
1.12
454         cm1 = buildtree(COMOPl1ofa);
455
ragge
1.13
456         gpo = structref(ccopy(ap), STREFot);
457         l1 = buildtree(PLUSEQccopy(gpo), bcon(addto));
ragge
1.12
458         cm2 = buildtree(COMOPl1buildtree(PLUSccopy(gpo),
459             structref(ccopy(ap), STREFreg_save_area)));
460         qc = buildtree(QUEST,
ragge
1.13
461             buildtree(GEgpobcon(max)),
ragge
1.12
462             buildtree(COLONcm1cm2));
ragge
1.13
463
ragge
1.29
464         nt = (dp->n_type == DOUBLE ? DOUBLE : LONG);
ragge
1.23
465         l1 = block(NAMENILNILnt|PTR0MKAP(nt));
ragge
1.13
466         l1 = buildtree(CASTl1qc);
467         qc = l1->n_right;
468         nfree(l1->n_left);
469         nfree(l1);
470
ragge
1.14
471         /* qc has now a real type, for indexing */
ragge
1.29
472         addto = dp->n_type == DOUBLE ? 2 : 1;
ragge
1.13
473         qc = buildtree(UMULbuildtree(PLUSqcbcon(-addto)), NIL);
474
ragge
1.29
475         l1 = block(NAMENILNILdp->n_typedp->n_dfdp->n_ap);
ragge
1.12
476         l1 = buildtree(CASTl1qc);
ragge
1.13
477         qc = l1->n_right;
ragge
1.12
478         nfree(l1->n_left);
479         nfree(l1);
ragge
1.13
480
481         return qc;
ragge
1.12
482 }
483
ragge
1.11
484 NODE *
ragge
1.24
485 amd64_builtin_va_arg(NODE *fNODE *aTWORD t)
ragge
1.12
486 {
ragge
1.29
487         NODE *ap, *r, *dp;
ragge
1.12
488
489         ap = a->n_left;
ragge
1.29
490         dp = a->n_right;
491         if (dp->n_type <= ULONGLONG || ISPTR(dp->n_type)) {
ragge
1.12
492                 /* type might be in general register */
ragge
1.29
493                 r = bva(apdpgp_offset848);
494         } else if (dp->n_type == FLOAT || dp->n_type == DOUBLE) {
ragge
1.13
495                 /* Float are promoted to double here */
ragge
1.29
496                 if (dp->n_type == FLOAT)
497                         dp->n_type = DOUBLE;
498                 r = bva(apdpfp_offset16RSASZ/SZCHAR);
ragge
1.12
499         } else {
ragge
1.13
500                 uerror("amd64_builtin_va_arg not supported type");
501                 goto bad;
ragge
1.12
502         }
503         tfree(a);
504         tfree(f);
505         return r;
506 bad:
507         uerror("bad argument to __builtin_va_arg");
508         return bcon(0);
509 }
ragge
1.11
510
511 NODE *
ragge
1.24
512 amd64_builtin_va_end(NODE *fNODE *aTWORD t)
ragge
1.13
513 {
514         tfree(f);
515         tfree(a);
516         return bcon(0); /* nothing */
517 }
ragge
1.11
518
519 NODE *
ragge
1.24
520 amd64_builtin_va_copy(NODE *fNODE *aTWORD t) { cerror("amd64_builtin_va_copy"); return NULL; }
ragge
1.11
521
ragge
1.7
522 static NODE *
523 movtoreg(NODE *pint rno)
mickey
1.1
524 {
525         NODE *r;
526
ragge
1.23
527         r = block(REGNILNILp->n_typep->n_dfp->n_ap);
ragge
1.7
528         regno(r) = rno;
529         return clocal(buildtree(ASSIGNrp));
530 }  
531
ragge
1.9
532 static NODE *
ragge
1.14
533 movtomem(NODE *pint offint reg)
ragge
1.9
534 {
535         struct symtab s;
536         NODE *r, *l;
537
538         s.stype = p->n_type;
ragge
1.25
539         s.squal = 0;
ragge
1.9
540         s.sdf = p->n_df;
ragge
1.23
541         s.sap = p->n_ap;
ragge
1.9
542         s.soffset = off;
ragge
1.11
543         s.sclass = AUTO;
ragge
1.9
544
545         l = block(REGNILNILPTR+STRTY00);
546         l->n_lval = 0;
ragge
1.14
547         regno(l) = reg;
ragge
1.9
548
ragge
1.23
549         r = block(NAMENILNILp->n_typep->n_dfp->n_ap);
ragge
1.9
550         r->n_sp = &s;
551         r = stref(block(STREFlr000));
552
553         return clocal(buildtree(ASSIGNrp));
554 }  
555
ragge
1.7
556
557 /*
558  * AMD64 parameter classification.
559  */
560 static int
ragge
1.23
561 argtyp(TWORD tunion dimfun *dfstruct attr *ap)
ragge
1.7
562 {
563         int cl = 0;
564
ragge
1.9
565         if (t <= ULONG || ISPTR(t)) {
ragge
1.7
566                 cl = ngpr < 6 ? INTEGER : INTMEM;
567         } else if (t == FLOAT || t == DOUBLE) {
ragge
1.8
568                 cl = nsse < 8 ? SSE : SSEMEM;
ragge
1.7
569         } else if (t == LDOUBLE) {
570                 cl = X87/* XXX */
ragge
1.26
571         } else if (t == STRTY || t == UNIONTY) {
ragge
1.32
572                 int sz = tsize(tdfap);
573
574                 if (sz > 2*SZLONG || ((sz+SZLONG)/SZLONG)+ngpr > 6 ||
575                     attr_find(apGCC_ATYP_PACKED) != NULL)
ragge
1.7
576                         cl = STRMEM;
577                 else
ragge
1.17
578                         cl = STRREG;
ragge
1.7
579         } else
580                 cerror("FIXME: classify");
581         return cl;
582 }
583
ragge
1.26
584 static NODE *
ragge
1.7
585 argput(NODE *p)
586 {
587         NODE *q;
ragge
1.17
588         int typrssz;
mickey
1.1
589
ragge
1.26
590         if (p->n_op == CM) {
591                 p->n_left = argput(p->n_left);
592                 p->n_right = argput(p->n_right);
593                 return p;
594         }
595
ragge
1.7
596         /* first arg may be struct return pointer */
597         /* XXX - check if varargs; setup al */
ragge
1.23
598         switch (typ = argtyp(p->n_typep->n_dfp->n_ap)) {
ragge
1.7
599         case INTEGER:
600         case SSE:
601                 if (typ == SSE)
602                         r = XMM0 + nsse++;
603                 else
604                         r = argregsi[ngpr++];
ragge
1.26
605                 p = movtoreg(pr);
ragge
1.7
606                 break;
ragge
1.26
607
ragge
1.7
608         case X87:
ragge
1.25
609                 r = nrsp;
610                 nrsp += SZLDOUBLE;
ragge
1.26
611                 p = movtomem(prSTKREG);
ragge
1.7
612                 break;
ragge
1.9
613
ragge
1.30
614         case SSEMEM:
615                 r = nrsp;
616                 nrsp += SZDOUBLE;
617                 p = movtomem(prSTKREG);
618                 break;
619
ragge
1.9
620         case INTMEM:
621                 r = nrsp;
622                 nrsp += SZLONG;
ragge
1.26
623                 p = movtomem(prSTKREG);
ragge
1.9
624                 break;
625
ragge
1.17
626         case STRREG/* Struct in registers */
627                 /* Cast to long pointer and move to the registers */
ragge
1.27
628                 /* XXX can overrun struct size */
ragge
1.23
629                 ssz = tsize(p->n_typep->n_dfp->n_ap);
ragge
1.17
630
631                 if (ssz <= SZLONG) {
632                         q = cast(p->n_leftLONG+PTR0);
ragge
1.27
633                         nfree(p);
ragge
1.17
634                         q = buildtree(UMULqNIL);
ragge
1.26
635                         p = movtoreg(qargregsi[ngpr++]);
ragge
1.17
636                 } else if (ssz <= SZLONG*2) {
637                         NODE *qt, *q1, *q2, *ql, *qr;
638
ragge
1.23
639                         qt = tempnode(0LONG+PTR0MKAP(LONG));
ragge
1.17
640                         q1 = ccopy(qt);
641                         q2 = ccopy(qt);
642                         ql = buildtree(ASSIGNqtcast(p->n_left,LONG+PTR0));
ragge
1.27
643                         nfree(p);
ragge
1.17
644                         qr = movtoreg(buildtree(UMULq1NIL),
645                             argregsi[ngpr++]);
646                         ql = buildtree(COMOPqlqr);
647                         qr = buildtree(UMULbuildtree(PLUSq2bcon(1)), NIL);
648                         qr = movtoreg(qrargregsi[ngpr++]);
ragge
1.26
649                         p = buildtree(COMOPqlqr);
ragge
1.17
650                 } else
651                         cerror("STRREG");
652                 break;
653
ragge
1.26
654         case STRMEM: {
655                 struct symtab s;
656                 NODE *l, *t;
657
658                 q = buildtree(UMULp->n_leftNIL);
659
660                 s.stype = p->n_type;
661                 s.squal = 0;
662                 s.sdf = p->n_df;
663                 s.sap = p->n_ap;
664                 s.soffset = nrsp;
665                 s.sclass = AUTO;
666
667                 nrsp += tsize(p->n_typep->n_dfp->n_ap);
668
669                 l = block(REGNILNILPTR+STRTY00);
670                 l->n_lval = 0;
671                 regno(l) = STKREG;
672
673                 t = block(NAMENILNILp->n_typep->n_dfp->n_ap);
674                 t->n_sp = &s;
675                 t = stref(block(STREFlt000));
676
677                 t = (buildtree(ASSIGNtq));
678                 nfree(p);
679                 p = t->n_left;
680                 nfree(t);
681                 break;
682                 }
683
ragge
1.7
684         default:
ragge
1.9
685                 cerror("argument %d"typ);
mickey
1.1
686         }
ragge
1.26
687         return p;
ragge
1.7
688 }
mickey
1.1
689
ragge
1.26
690 /*
691  * Sort arglist so that register assignments ends up last.
692  */
693 static int
694 argsort(NODE *p)
695 {
696         NODE *q;
697         int rv = 0;
698
699         if (p->n_op != CM)
700                 return rv;
701         if (p->n_right->n_op == ASSIGN && p->n_right->n_left->n_op == REG) {
702                 if (p->n_left->n_op == CM &&
703                     p->n_left->n_right->n_op == STASG) {
704                         q = p->n_left->n_right;
705                         p->n_left->n_right = p->n_right;
706                         p->n_right = q;
707                         rv = 1;
708                 } else if (p->n_left->n_op == STASG) {
709                         q = p->n_left;
710                         p->n_left = p->n_right;
711                         p->n_right = q;
712                         rv = 1;
713                 }
714         }
715         return rv | argsort(p->n_left);
716 }
mickey
1.1
717
718 /*
719  * Called with a function call with arguments as argument.
720  * This is done early in buildtree() and only done once.
721  * Returns p.
722  */
723 NODE *
724 funcode(NODE *p)
725 {
ragge
1.8
726         NODE *l, *r;
mickey
1.1
727
ragge
1.9
728         nsse = ngpr = nrsp = 0;
ragge
1.17
729         /* Check if hidden arg needed */
730         /* If so, add it in pass2 */
731         if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY ||
732             l->n_type == INCREF(FTN)+UNIONTY) {
ragge
1.23
733                 int ssz = tsize(BTYPE(l->n_type), l->n_dfl->n_ap);
ragge
1.17
734                 if (ssz > 2*SZLONG)
735                         ngpr++;
736         }
ragge
1.26
737
738         /* Convert just regs to assign insn's */
739         p->n_right = argput(p->n_right);
740
741         /* Must sort arglist so that STASG ends up first */
742         /* This avoids registers being clobbered */
743         while (argsort(p->n_right))
744                 ;
ragge
1.8
745
ragge
1.22
746         /* Check if there are varargs */
747         if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) {
748                 ; /* Need RAX */
749         } else {
750                 union arglist *al = l->n_df->dfun;
751
752                 for (; al->type != TELLIPSISal++) {
753                         if (al->type == TNULL)
754                                 return p/* No need */
755                         if (BTYPE(al->type) == STRTY ||
756                             BTYPE(al->type) == UNIONTY ||
757                             ISARY(al->type))
758                                 al++;
759                 }
760         }
761
ragge
1.8
762         /* Always emit number of SSE regs used */
763         l = movtoreg(bcon(nsse), RAX);
764         if (p->n_right->n_op != CM) {
ragge
1.23
765                 p->n_right = block(CMlp->n_rightINT0MKAP(INT));
ragge
1.8
766         } else {
767                 for (r = p->n_rightr->n_left->n_op == CMr = r->n_left)
768                         ;
ragge
1.23
769                 r->n_left = block(CMlr->n_leftINT0MKAP(INT));
ragge
1.8
770         }
mickey
1.1
771         return p;
772 }
773
774 /*
775  * return the alignment of field of type t
776  */
777 int
778 fldal(unsigned int t)
779 {
780         uerror("illegal field type");
781         return(ALINT);
782 }
783
784 /* fix up type of field p */
785 void
786 fldty(struct symtab *p)
787 {
788 }
789
790 /*
791  * XXX - fix genswitch.
792  */
793 int
794 mygenswitch(int numTWORD typestruct swents **pint n)
795 {
796         return 0;
797 }
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-23 10:21 +0200