Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101102193758

Diff

Diff from 1.34 to:

Annotations

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

Annotated File View

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