scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 13enum segment {
 14	CODESEG,
 15	DATASEG,
 16	BSSSEG,
 17	NOSEG
 18};
 19
 20static void src(void), dst(void), bin(void), lit(void), jmp(void);
 21
 22static 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
 41static int curseg = NOSEG;
 42static unsigned long offpar, offvar;
 43
 44static void
 45segment(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
 59static char *
 60symname(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
 80static void
 81label(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
106static void
107emitconst(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
124static void
125emittree(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
154static void
155size2asm(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
183void
184deftype(Type *tp)
185{
186}
187
188void
189defglobal(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
198void
199data(Node *np)
200{
201	size2asm(&np->type);
202	emittree(np);
203	putchar('\n');
204}
205
206void
207writeout(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
220void
221endinit(void)
222{
223}
224
225static char *
226addr2txt(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
269static void
270lit(void)
271{
272	struct opdata *p = &optbl[pc->op];
273
274	printf("\t%s\n", p->txt);
275}
276
277static void
278bin(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
288static void
289src(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
298static void
299dst(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
308static void
309jmp(void)
310{
311	struct opdata *p = &optbl[pc->op];
312
313	printf("\t%s\t%s\n", p->txt, addr2txt(&pc->from1));
314}