code.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
code.c (4580B)
---
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <scc/cstd.h>
6 #include <scc/scc.h>
7
8 #include "../cc2.h"
9 #include "arch.h"
10
11 #define ADDR_LEN (INTIDENTSIZ+64)
12
13 enum segment {
14 CODESEG,
15 DATASEG,
16 BSSSEG,
17 NOSEG
18 };
19
20 static void src(void), dst(void), bin(void), lit(void), jmp(void);
21
22 static struct opdata {
23 void (*fun)(void);
24 char *txt;
25 } optbl[] = {
26 [ASPUSH] = {.fun = src, .txt = "push"},
27 [ASPOP] = {.fun = dst, .txt = "pop"},
28
29 [ASRET] = {.fun = lit, .txt = "ret"},
30 [ASJP] = {.fun = jmp, .txt = "jp"},
31 [ASJP] = {.fun = jmp, .txt = "jr"},
32 [ASBRANCH] = {0},
33
34 [ASMOV] = {.fun = bin, .txt = "ld"},
35 [ASEXHL] = {.fun = bin, .txt = "ex"},
36
37 [ASADD] = {.fun = bin, .txt = "add"},
38 [ASLD] = {.fun = bin, .txt = "ld"},
39 };
40
41 static int curseg = NOSEG;
42 static unsigned long offpar, offvar;
43
44 static void
45 segment(int seg)
46 {
47 static char *txt[] = {
48 [CODESEG] = "\t.text\n",
49 [DATASEG] = "\t.data\n",
50 [BSSSEG] = "\t.bss\n",
51 };
52
53 if (seg == curseg)
54 return;
55 fputs(txt[seg], stdout);
56 curseg = seg;
57 }
58
59 static char *
60 symname(Symbol *sym)
61 {
62 static char name[ADDR_LEN];
63
64 if (sym->name) {
65 switch (sym->kind) {
66 case SGLOB:
67 case SEXTRN:
68 snprintf(name, sizeof(name), "_%s", sym->name);
69 return name;
70 case SPRIV:
71 return sym->name;
72 }
73 }
74
75 sprintf(name, ".%d", sym->numid);
76
77 return name;
78 }
79
80 static void
81 label(Symbol *sym)
82 {
83 int seg;
84 char *name = symname(sym);
85
86 if (sym->type.flags & FUNF)
87 seg = CODESEG;
88 else if (sym->type.flags & INITF)
89 seg = DATASEG;
90 else
91 seg = BSSSEG;
92 segment(seg);
93
94 switch (sym->kind) {
95 case SEXTRN:
96 printf("\t.extrn\t%s\n", name);
97 return;
98 case SGLOB:
99 printf("\t.globl\t%s\n", name);
100 break;
101 }
102
103 printf("%s:\n", name);
104 }
105
106 static void
107 emitconst(Node *np)
108 {
109 switch (np->type.size) {
110 case 1:
111 printf("%d", (int) np->u.i & 0xFF);
112 break;
113 case 2:
114 printf("%d", (int) np->u.i & 0xFFFF);
115 break;
116 case 4:
117 printf("%ld", (long) np->u.i & 0xFFFFFFFF);
118 break;
119 default:
120 abort();
121 }
122 }
123
124 static void
125 emittree(Node *np)
126 {
127 if (!np)
128 return;
129
130 switch (np->op) {
131 case OSTRING:
132 pprint(np->u.s);
133 free(np->u.s);
134 np->u.s = NULL;
135 break;
136 case OCONST:
137 emitconst(np);
138 break;
139 case OADDR:
140 emittree(np->left);
141 break;
142 case OLABEL:
143 case OMEM:
144 fputs(symname(np->u.sym), stdout);
145 break;
146 default:
147 emittree(np->left);
148 printf(" %c ", np->op);
149 emittree(np->right);
150 break;
151 }
152 }
153
154 static void
155 size2asm(Type *tp)
156 {
157 char *s;
158
159 /*
160 * In z80 we can ignore the alignment
161 */
162 if (tp->flags & STRF) {
163 s = "\tDB\t";
164 } else {
165 switch (tp->size) {
166 case 1:
167 s = "\tDB\t";
168 break;
169 case 2:
170 s = "\tDW\t";
171 break;
172 case 4:
173 s = "\tDD\t";
174 break;
175 default:
176 s = "\tDS\t%lu,";
177 break;
178 }
179 }
180 printf(s, tp->size);
181 }
182
183 void
184 deftype(Type *tp)
185 {
186 }
187
188 void
189 defglobal(Symbol *sym)
190 {
191 label(sym);
192 if (sym->kind == SEXTRN || (sym->type.flags & INITF))
193 return;
194 size2asm(&sym->type);
195 puts("0");
196 }
197
198 void
199 data(Node *np)
200 {
201 size2asm(&np->type);
202 emittree(np);
203 putchar('\n');
204 }
205
206 void
207 writeout(void)
208 {
209 label(curfun);
210
211 for (pc = prog; pc; pc = pc->next) {
212 if (pc->label)
213 printf("%s:\n", symname(pc->label));
214 if (pc->op == ASLABEL)
215 continue;
216 (*optbl[pc->op].fun)();
217 }
218 }
219
220 void
221 endinit(void)
222 {
223 }
224
225 static char *
226 addr2txt(Addr *a)
227 {
228 static char *regnames[] = {
229 [A] = "a",
230 [B] = "b",
231 [C] = "c",
232 [D] = "d",
233 [E] = "e",
234 [H] = "h",
235 [L] = "l",
236 [IYL] = "iyl",
237 [IYH] = "iyh",
238 [AF] = "af",
239 [HL] = "hl",
240 [DE] = "de",
241 [BC] = "bc",
242 [IY] = "iy",
243 [SP] = "sp",
244 [IX] = "ix",
245 };
246 static char addr[INTIDENTSIZ+1];
247
248 switch (a->kind) {
249 case SREG:
250 return regnames[a->u.reg];
251 case SINDEX:
252 sprintf(addr,"%ld(ix)", a->u.off);
253 return addr;
254 case SLABEL:
255 case STMP:
256 case SGLOB:
257 case SEXTRN:
258 case SPRIV:
259 case SLOCAL:
260 return symname(a->u.sym);
261 case SCONST:
262 sprintf(addr, "%lld", a->u.i);
263 return addr;
264 default:
265 abort();
266 }
267 }
268
269 static void
270 lit(void)
271 {
272 struct opdata *p = &optbl[pc->op];
273
274 printf("\t%s\n", p->txt);
275 }
276
277 static void
278 bin(void)
279 {
280 struct opdata *p = &optbl[pc->op];
281 char to[ADDR_LEN], from[ADDR_LEN];
282
283 strcpy(from, addr2txt(&pc->from1));
284 strcpy(to, addr2txt(&pc->to));
285 printf("\t%s\t%s,%s\n", p->txt, from, to);
286 }
287
288 static void
289 src(void)
290 {
291 struct opdata *p = &optbl[pc->op];
292 char from[ADDR_LEN];
293
294 strcpy(from, addr2txt(&pc->from1));
295 printf("\t%s\t%s\n", p->txt, from);
296 }
297
298 static void
299 dst(void)
300 {
301 struct opdata *p = &optbl[pc->op];
302 char to[ADDR_LEN];
303
304 strcpy(to, addr2txt(&pc->to));
305 printf("\t%s\t%s\n", p->txt, to);
306 }
307
308 static void
309 jmp(void)
310 {
311 struct opdata *p = &optbl[pc->op];
312
313 printf("\t%s\t%s\n", p->txt, addr2txt(&pc->from1));
314 }