cgen.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
---
cgen.c (7571B)
---
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include <scc/scc.h>
5
6 #include "../cc2.h"
7 #include "arch.h"
8
9 #define NLOCALS 16
10
11 struct local {
12 Symbol *sym;
13 struct local *next;
14 };
15
16 static Symbol *retlabel;
17 static int offpar, offvar;
18
19 static Node *reguse[NPAIRS];
20 static int upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};
21 static int lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
22 static int pair[] = {
23 [A] = A,
24 [H] = HL, [L] = HL, [HL] = HL,
25 [B] = BC, [C] = BC, [BC] = BC,
26 [D] = DE, [E] = DE, [DE] = DE,
27 [IYL] = IY, [IYH] = IY, [IY] = IY
28 };
29
30 static Node regs[] = {
31 [E] = {
32 .op = OMREG,
33 .type.size = 1,
34 .u.reg = E
35 },
36 [D] = {
37 .op = OMREG,
38 .type.size = 1,
39 .u.reg = D
40 },
41 [H] = {
42 .op = OMREG,
43 .type.size = 1,
44 .u.reg = H
45 },
46 [L] = {
47 .op = OMREG,
48 .type.size = 1,
49 .u.reg = L
50 },
51 [C] = {
52 .op= OMREG,
53 .type.size = 1,
54 .u.reg = C
55 },
56 [B] = {
57 .op= OMREG,
58 .type.size = 1,
59 .u.reg = B
60 },
61 [A] = {
62 .op= OMREG,
63 .type.size = 1,
64 .u.reg = A
65 },
66 [IYL] = {
67 .op = OMREG,
68 .type.size = 1,
69 .u.reg = IYL
70 },
71 [IYH] = {
72 .op = OMREG,
73 .type.size = 1,
74 .u.reg = IYH
75 },
76 [DE] = {
77 .op = OMREG,
78 .type.size = 2,
79 .u.reg = DE
80 },
81 [HL] = {
82 .op = OMREG,
83 .type.size = 2,
84 .u.reg = HL
85 },
86 [BC] = {
87 .op = OMREG,
88 .type.size = 2,
89 .u.reg = BC
90 },
91 [IX] = {
92 .op = OMREG,
93 .type.size = 2,
94 .u.reg = IX
95 },
96 [IY] = {
97 .op = OMREG,
98 .type.size = 2,
99 .u.reg = IY
100 },
101 [SP] = {
102 .op = OMREG,
103 .type.size = 2,
104 .u.reg = SP
105 }
106 };
107
108 void
109 defpar(Symbol *sym)
110 {
111 unsigned align, size;
112
113 if (sym->kind != SREG && sym->kind != SAUTO)
114 return;
115 align = sym->type.align;
116 size = sym->type.size;
117
118 if (offpar == 0)
119 offpar = +2;
120
121 sym->u.off = offpar;
122 offpar += size;
123 offpar += offpar & 1;
124 }
125
126 void
127 defvar(Symbol *sym)
128 {
129 unsigned long align, size;
130
131 if (sym->kind != SREG && sym->kind != SAUTO)
132 return;
133 align = sym->type.align;
134 size = sym->type.size;
135
136 if (offvar == 0)
137 offvar = -2;
138
139 sym->u.off = offvar;
140 offvar -= size;
141 offvar -= offpar & 1;
142 }
143
144 static Node *
145 function(void)
146 {
147 Node aux;
148
149 memset(reguse, 0, sizeof(reguse));
150
151 retlabel = newlabel();
152
153 code(ASPUSH, NULL, ®s[IX], NULL);
154 code(ASMOV, ®s[IX], ®s[SP], NULL);
155
156 constnode(&aux, offvar + 2, &ptrtype);
157 code(ASMOV, ®s[HL], &aux, NULL);
158 code(ASADD, ®s[HL], ®s[SP], ®s[HL]);
159 code(ASMOV, ®s[SP], ®s[HL], NULL);
160 }
161
162 static void
163 efunction(void)
164 {
165 setlabel(retlabel);
166 code(ASMOV, ®s[SP], ®s[IX], NULL);
167 code(ASPOP, ®s[IX], NULL, NULL);
168 code(ASRET, NULL, NULL, NULL);
169 offpar = offvar = 0;
170 }
171
172 static void
173 allocreg(Node *np)
174 {
175 }
176
177 static void
178 store(Node *np)
179 {
180 }
181
182 static void
183 load(Node *np)
184 {
185 }
186
187 static void
188 spill(int reg)
189 {
190 Node *np, *r;
191 Symbol *sym;
192 int p, h, l;
193
194 if ((np = reguse[reg]) == NULL)
195 return;
196 r = ®s[reg];
197
198 store(r);
199 p = pair[reg];
200 l = lower[p];
201 h = upper[p];
202
203 if (reg >= NREGS)
204 reguse[l] = reguse[h] = NULL;
205 else
206 reguse[reg] = NULL;
207
208 if (!reguse[l] && !reguse[h])
209 reguse[p] = NULL;
210 }
211
212 static void
213 use(int reg, Node *np)
214 {
215 reguse[reg] = np;
216
217 if (reg < NREGS) {
218 reguse[pair[reg]] = np;
219 } else if (reg >= NREGS && reg < NPAIRS) {
220 reguse[lower[reg]] = np;
221 reguse[upper[reg]] = np;
222 } else {
223 abort();
224 }
225 }
226
227 static void
228 load2(Node *np, int dst)
229 {
230 long offl, offh;
231 Node low, high;
232
233 switch (np->op) {
234 case OAUTO:
235 offl = np->u.sym->u.off - 1;
236 offh = offl + 1;
237 break;
238 default:
239 abort();
240 }
241
242 code(ASLD, ®s[lower[dst]], idxnode(&low, offl), NULL);
243 code(ASLD, ®s[upper[dst]], idxnode(&high, offh), NULL);
244 use(dst, np);
245 }
246
247 static void
248 moveto1(Node *np, int dst)
249 {
250 int src;
251 Node *pdst = ®s[dst];
252
253 switch (np->op) {
254 case OAUTO:
255 code(ASLD, pdst, np, NULL);
256 break;
257 case OMREG:
258 src = np->u.reg;
259 if (src == dst)
260 return;
261
262 code(ASMOV, pdst, ®s[np->u.reg], NULL);
263 break;
264 default:
265 abort();
266 }
267
268 use(dst, np);
269 }
270
271 static void
272 moveto2(Node *np, int dst)
273 {
274 int src;
275 Node aux;
276
277 switch (np->op) {
278 case OAUTO:
279 load2(np, dst);
280 break;
281 case OMREG:
282 src = np->u.reg;
283 if (src == dst)
284 return;
285
286 if (src == HL && dst == DE || src == DE && dst == HL) {
287 code(ASEXHL, ®s[HL], ®s[HL], ®s[DE]);
288 use(src, reguse[dst]);
289 } else {
290 code(ASMOV, ®s[lower[dst]], ®s[lower[src]], NULL);
291 code(ASMOV, ®s[upper[dst]], ®s[upper[src]], NULL);
292 }
293 break;
294 default:
295 abort();
296 }
297
298 use(dst, np);
299 }
300
301 static void
302 moveto4(Node *np, int dst)
303 {
304 abort();
305 }
306
307 static void
308 moveto8(Node *np, int dst)
309 {
310 abort();
311 }
312
313 static void
314 moveto(Node *np, int reg)
315 {
316 switch (np->type.size) {
317 case 1:
318 moveto1(np, reg);
319 break;
320 case 2:
321 moveto2(np, reg);
322 break;
323 case 4:
324 moveto4(np, reg);
325 break;
326 case 8:
327 moveto4(np, reg);
328 break;
329 default:
330 abort();
331 }
332 }
333
334 static int
335 cmpnode(Node *n1, Node *n2)
336 {
337 if (n1 == n2)
338 return 1;
339 if (!n1 || !n2)
340 return 0;
341 if (n1->op != n2->op)
342 return 0;
343
344 switch (n1->op) {
345 case OAUTO:
346 return n1->u.sym == n2->u.sym;
347 default:
348 return 0;
349 }
350 }
351
352 static void
353 move(Node *np, int reg)
354 {
355 int i;
356
357 switch (np->type.size) {
358 case 1:
359 for (i = A; i < NREGS; ++i) {
360 if (cmpnode(reguse[i], np))
361 goto found;
362 }
363 break;
364 case 2:
365 for (i = AF; i < NPAIRS; ++i) {
366 if (cmpnode(reguse[i], np))
367 goto found;
368 }
369 break;
370 case 4:
371 abort();
372 case 8:
373 abort();
374 }
375
376 moveto(np, reg);
377 return;
378
379 found:
380 moveto(®s[i], reg);
381 }
382
383 static int
384 whatacc(Node *np)
385 {
386 switch (np->type.size) {
387 case 1:
388 return A;
389 case 2:
390 return HL;
391 case 4:
392 return HLDE;
393 case 8:
394 return EXHLDE;
395 default:
396 abort();
397 }
398 }
399
400 static Node *
401 acc(Node *np)
402 {
403 int reg = whatacc(np);
404 move(np, reg);
405 return ®s[reg];
406 }
407
408 static Node *
409 rhs(Node *np)
410 {
411 switch (np->op) {
412 case OAUTO:
413 return acc(np);
414 case OMEM:
415 case OSNEG:
416 case OTMP:
417 case OCONST:
418 case OREG:
419 case OMOD:
420 case OSHL:
421 case OBAND:
422 case OBOR:
423 case OBXOR:
424 case OSHR:
425 case ODIV:
426 case OLT:
427 case OGT:
428 case OLE:
429 case OGE:
430 case OADD:
431 case OSUB:
432 case OMUL:
433 case OEQ:
434 case ONE:
435 case OCALL:
436 case OCALLE:
437 case OCAST:
438 case OASSIG:
439 case OASK:
440 case OCOMMA:
441 case OPTR:
442 case OADDR:
443 case OFIELD:
444 case OBUILTIN:
445 default:
446 abort();
447 }
448 }
449
450 static Node *
451 field(Node *np, int islhs)
452 {
453 }
454
455 static Node *
456 lhs(Node *np)
457 {
458 switch (np->op) {
459 case OMEM:
460 case OAUTO:
461 return np;
462 case OPTR:
463 return rhs(np->left);
464 case OFIELD:
465 return field(np, 1);
466 default:
467 abort();
468 }
469 }
470
471 static void
472 ret(Node *np)
473 {
474 Node aux;
475
476 if (np->left)
477 acc(np->left);
478 label2node(&aux, retlabel);
479 code(ASJP, NULL, &aux, NULL);
480 }
481
482 static Node *
483 cgen(Node *np)
484 {
485 Node aux, *next;
486
487 setlabel(np->label);
488 switch (np->op) {
489 case OBFUN:
490 function();
491 break;
492 case OEFUN:
493 efunction();
494 break;
495 case ONOP:
496 case OBLOOP:
497 case OELOOP:
498 break;
499 case OJMP:
500 label2node(&aux, np->u.sym);
501 code(ASJP, NULL, &aux, NULL);
502 break;
503 case OBRANCH:
504 /* TODO */
505 break;
506 case ORET:
507 ret(np);
508 break;
509 case OBSWITCH:
510 /* TODO */
511 break;
512 default:
513 rhs(np);
514 break;
515 }
516 return np;
517 }
518
519 /*
520 * This is strongly influenced by
521 * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
522 * calculate addresability as follows
523 * AUTO => 11 value+fp
524 * REG => 13 reg
525 * STATIC => 12 (value)
526 * CONST => 20 $value
527 */
528 Node *
529 tsethi(Node *np)
530 {
531 Node *l, *r;
532
533 l = np->left;
534 r = np->right;
535 switch (np->op) {
536 case OAUTO:
537 np->address = 11;
538 break;
539 case OREG:
540 np->address = 13;
541 break;
542 case OMEM:
543 np->address = 12;
544 break;
545 case OCONST:
546 np->address = 20;
547 break;
548 default:
549 l = sethi(l);
550 r = sethi(r);
551 break;
552 }
553
554 np->left = l;
555 np->right = r;
556
557 return np;
558 }
559
560 void
561 genasm(void)
562 {
563 apply(cgen);
564 }