scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }