Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20101211142537

Diff

Diff from 1.44 to:

Annotations

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

Annotated File View

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