1 | #include "all.h" |
2 | |
3 | |
4 | char *gasloc, *gassym; |
5 | static int gasasm; |
6 | |
7 | void |
8 | gasinit(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 | |
23 | void |
24 | gasemitlnk(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 | |
44 | void |
45 | gasemitfntail(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 | |
53 | void |
54 | gasemitdat(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 | |
107 | typedef struct Asmbits Asmbits; |
108 | |
109 | struct Asmbits { |
110 | char bits[16]; |
111 | int size; |
112 | Asmbits *link; |
113 | }; |
114 | |
115 | static Asmbits *stash; |
116 | |
117 | int |
118 | gasstash(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 | |
136 | void |
137 | gasemitfin(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 | |