scc

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

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

  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
 11struct local {
 12	Symbol *sym;
 13	struct local *next;
 14};
 15
 16static Symbol *retlabel;
 17static int offpar, offvar;
 18
 19static Node *reguse[NPAIRS];
 20static int upper[] = {[DE] = D, [HL] = H, [BC] = B,  [IY] = IYH};
 21static int lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
 22static 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
 30static 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
108void
109defpar(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
126void
127defvar(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
144static Node *
145function(void)
146{
147	Node aux;
148
149	memset(reguse, 0, sizeof(reguse));
150
151	retlabel = newlabel();
152
153	code(ASPUSH, NULL, &regs[IX], NULL);
154	code(ASMOV, &regs[IX], &regs[SP], NULL);
155
156	constnode(&aux, offvar + 2, &ptrtype);
157	code(ASMOV, &regs[HL], &aux, NULL);
158	code(ASADD, &regs[HL], &regs[SP], &regs[HL]);
159	code(ASMOV, &regs[SP], &regs[HL], NULL);
160}
161
162static void
163efunction(void)
164{
165	setlabel(retlabel);
166	code(ASMOV, &regs[SP], &regs[IX], NULL);
167	code(ASPOP, &regs[IX], NULL, NULL);
168	code(ASRET, NULL, NULL, NULL);
169	offpar = offvar = 0;
170}
171
172static void
173allocreg(Node *np)
174{
175}
176
177static void
178store(Node *np)
179{
180}
181
182static void
183load(Node *np)
184{
185}
186
187static void
188spill(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 = &regs[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
212static void
213use(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
227static void
228load2(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, &regs[lower[dst]], idxnode(&low, offl), NULL);
243	code(ASLD, &regs[upper[dst]], idxnode(&high, offh), NULL);
244	use(dst, np);
245}
246
247static void
248moveto1(Node *np, int dst)
249{
250	int src;
251	Node *pdst = &regs[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, &regs[np->u.reg], NULL);
263		break;
264	default:
265		abort();
266	}
267
268	use(dst, np);
269}
270
271static void
272moveto2(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, &regs[HL], &regs[HL], &regs[DE]);
288			use(src, reguse[dst]);
289		} else {
290			code(ASMOV, &regs[lower[dst]], &regs[lower[src]], NULL);
291			code(ASMOV, &regs[upper[dst]], &regs[upper[src]], NULL);
292		}
293		break;
294	default:
295		abort();
296	}
297
298	use(dst, np);
299}
300
301static void
302moveto4(Node *np, int dst)
303{
304	abort();
305}
306
307static void
308moveto8(Node *np, int dst)
309{
310	abort();
311}
312
313static void
314moveto(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
334static int
335cmpnode(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
352static void
353move(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
379found:
380	moveto(&regs[i], reg);
381}
382
383static int
384whatacc(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
400static Node *
401acc(Node *np)
402{
403	int reg = whatacc(np);
404	move(np, reg);
405	return &regs[reg];
406}
407
408static Node *
409rhs(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
450static Node *
451field(Node *np, int islhs)
452{
453}
454
455static Node *
456lhs(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
471static void
472ret(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
482static Node *
483cgen(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 */
528Node *
529tsethi(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
560void
561genasm(void)
562{
563	apply(cgen);
564}