1#include "all.h"
2
3
4char *gasloc, *gassym;
5static int gasasm;
6
7void
8gasinit(enum Asm asmmode)
9{
10 gasasm = asmmode;
11 switch (gasasm) {
12 case Gaself:
13 gasloc = ".L";
14 gassym = "";
15 break;
16 case Gasmacho:
17 gasloc = "L";
18 gassym = "_";
19 break;
20 }
21}
22
23void
24gasemitlnk(char *n, Lnk *l, char *s, FILE *f)
25{
26 char *p;
27
28 if (l->sec) {
29 fprintf(f, ".section %s", l->sec);
30 if (l->secf)
31 fprintf(f, ", %s", l->secf);
32 } else {
33 fputs(s, f);
34 }
35 fputc('\n', f);
36 if (l->align)
37 fprintf(f, ".balign %d\n", l->align);
38 p = n[0] == '"' ? "" : gassym;
39 if (l->export)
40 fprintf(f, ".globl %s%s\n", p, n);
41 fprintf(f, "%s%s:\n", p, n);
42}
43
44void
45gasemitfntail(char *fn, FILE *f)
46{
47 if (gasasm == Gaself) {
48 fprintf(f, ".type %s, @function\n", fn);
49 fprintf(f, ".size %s, .-%s\n", fn, fn);
50 }
51}
52
53void
54gasemitdat(Dat *d, FILE *f)
55{
56 static char *dtoa[] = {
57 [DB] = "\t.byte",
58 [DH] = "\t.short",
59 [DW] = "\t.int",
60 [DL] = "\t.quad"
61 };
62 static int64_t zero;
63 char *p;
64
65 switch (d->type) {
66 case DStart:
67 zero = 0;
68 break;
69 case DEnd:
70 if (zero != -1) {
71 gasemitlnk(d->name, d->lnk, ".bss", f);
72 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
73 }
74 break;
75 case DZ:
76 if (zero != -1)
77 zero += d->u.num;
78 else
79 fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
80 break;
81 default:
82 if (zero != -1) {
83 gasemitlnk(d->name, d->lnk, ".data", f);
84 if (zero > 0)
85 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
86 zero = -1;
87 }
88 if (d->isstr) {
89 if (d->type != DB)
90 err("strings only supported for 'b' currently");
91 fprintf(f, "\t.ascii %s\n", d->u.str);
92 }
93 else if (d->isref) {
94 p = d->u.ref.name[0] == '"' ? "" : gassym;
95 fprintf(f, "%s %s%s%+"PRId64"\n",
96 dtoa[d->type], p, d->u.ref.name,
97 d->u.ref.off);
98 }
99 else {
100 fprintf(f, "%s %"PRId64"\n",
101 dtoa[d->type], d->u.num);
102 }
103 break;
104 }
105}
106
107typedef struct Asmbits Asmbits;
108
109struct Asmbits {
110 char bits[16];
111 int size;
112 Asmbits *link;
113};
114
115static Asmbits *stash;
116
117int
118gasstash(void *bits, int size)
119{
120 Asmbits **pb, *b;
121 int i;
122
123 assert(size == 4 || size == 8 || size == 16);
124 for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
125 if (size <= b->size)
126 if (memcmp(bits, b->bits, size) == 0)
127 return i;
128 b = emalloc(sizeof *b);
129 memcpy(b->bits, bits, size);
130 b->size = size;
131 b->link = 0;
132 *pb = b;
133 return i;
134}
135
136void
137gasemitfin(FILE *f)
138{
139 Asmbits *b;
140 char *p;
141 int sz, i;
142 double d;
143
144 if (gasasm == Gaself)
145 fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n\n");
146 if (!stash)
147 return;
148 fprintf(f, "/* floating point constants */\n.data\n");
149 for (sz=16; sz>=4; sz/=2)
150 for (b=stash, i=0; b; b=b->link, i++) {
151 if (b->size == sz) {
152 fprintf(f,
153 ".balign %d\n"
154 "%sfp%d:",
155 sz, gasloc, i
156 );
157 for (p=b->bits; p<&b->bits[sz]; p+=4)
158 fprintf(f, "\n\t.int %"PRId32,
159 *(int32_t *)p);
160 if (sz <= 8) {
161 if (sz == 4)
162 d = *(float *)b->bits;
163 else
164 d = *(double *)b->bits;
165 fprintf(f, " /* %f */\n", d);
166 } else
167 fprintf(f, "\n");
168 }
169 }
170 while ((b=stash)) {
171 stash = b->link;
172 free(b);
173 }
174}
175