File:  [Research Unix] / researchv10no / cmd / lcc / gen2 / mc / pseudos.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

/* C compiler: MC68020 code generator */

#include "c.h"

#define	AREG	0	/* an address register */
#define	DREG	1	/* a data register */
#define FREG	2	/* a floating point register */

#if mc68020 || mc68030 || NeXT
#include <stab.h>
#include "stabbsd.c"
#endif

dclproto(static void address,(Symbol, Symbol, int));
dclproto(static void defaddress,(Symbol));
dclproto(static void defconst,(int, Value));
dclproto(static void defstring,(int, char *));
dclproto(static void defsymbol,(Symbol));
dclproto(static void doarg,(Node));
dclproto(static void emitspecial,(Node));
dclproto(static void function,(Symbol, Symbol [], Symbol [], int));
dclproto(static void global,(Symbol));
dclproto(static void import,(Symbol));
dclproto(static void local,(Symbol));
dclproto(static void progbeg,(int, char **));
dclproto(static void segment,(int));
dclproto(static void space,(int));

dclproto(static void initgen,(void));
dclproto(static void final,(Node));

Interface mcInterface = {
	"mc",
	1, 1, 0,	/* char */
	2, 2, 0,	/* short */
	4, 2, 0,	/* int */
	4, 2, 1,	/* float */
	8, 2, 1,	/* double */
	4, 2, 0,	/* T * */
	0, 2, 0,	/* struct */
	1,		/* left_to_right */
	0,		/* little_endian */
	1,		/* jump_on_return */
	0,		/* mulops_are_calls */
	0,		/* compl_band */
	0,		/* no_argb */
	NODAG,		/* no_dag */
	address,
	blockbeg,
	blockend,
	defaddress,
	defconst,
	defstring,
	defsymbol,
	0,
	export,
	function,
	gen,
	global,
	import,
	local,
	progbeg,
	progend,
	segment,
	space,
#if mc68020 || mc68030 || NeXT
	stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
#else
	0, 0, 0, 0, 0, 0, 0,
#endif
	{".globl %s\n", 1, 0, {".text", ".bss", ".data", ".text", ".data2"},
	doarg, docall, 0, 0, 0,
	final, 0, emitspecial }
}, nextInterface = {
	"next",
	1, 1, 0,	/* char */
	2, 2, 0,	/* short */
	4, 2, 0,	/* int */
	4, 2, 1,	/* float */
	8, 2, 1,	/* double */
	4, 2, 0,	/* T * */
	0, 2, 0,	/* struct */
	1,		/* left_to_right */
	0,		/* little_endian */
	1,		/* jump_on_return */
	0,		/* mulops_are_calls */
	0,		/* compl_band */
	0,		/* no_argb */
	NODAG,		/* no_dag */
	address,
	blockbeg,
	blockend,
	defaddress,
	defconst,
	defstring,
	defsymbol,
	0,
	export,
	function,
	gen,
	global,
	import,
	local,
	progbeg,
	progend,
	segment,
	space,
#if mc68020 || mc68030 || NeXT
	stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
#else
	0, 0, 0, 0, 0, 0, 0,
#endif
	{".globl %s\n", 1, 0, {".text", ".bss", ".data", ".text", ".data2"},
	doarg, docall, 0, 0, 0,
	final, 0, emitspecial }

};

static Symbol a0, a1, d0, d1, d1234, fp0;

/* address - initialize q for addressing expression p+n */
static void address(q, p, n) Symbol q, p; {
	q->x.offset = p->x.offset + n;
	if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
		q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n);
	else
		q->x.name = stringd(q->x.offset);
}

static void defaddress(p) Symbol p; {
	if (p->scope == LABELS)
		print(".align 2; ");	/* for switch tables */
	print(".long %s\n", p->x.name);
}

/* defconst - define a constant */
static void defconst(ty, v) Value v; {
	struct real r;

	switch (ty) {
	case C: print(".byte %d\n",   v.uc); break;
	case S: print(".word %d\n",   v.ss); break;
	case I: print(".long %d\n",   v.i ); break;
	case U: print(".long 0x%x\n", v.u ); break;
	case P: print(".long 0x%x\n", v.p ); break;
	case F:
		r = decode(F, v.f);
		if (v.f)
			r.exp = (r.exp + 127)&0xff;
		print(".long 0x%x\n", (r.sign<<31) | (r.exp<<23) | (r.msb>>9));
		break;
	case D:
		r = decode(D, v.d);
		if (v.d)
			r.exp = (r.exp + 1023)&0x7ff;
		print(".long 0x%x,0x%x\n",
			(r.sign<<31) | (r.exp<<20) | (r.msb>>12),
			( r.msb<<20) | (r.lsb>>12));
		break;
	default:
		assert(0);
	}
}

static void defstring(n, s) char *s; {
	genascii(".ascii", ".byte", n, s);
}

/* defsymbol - compute and store p's back-end name */
static void defsymbol(p) Symbol p; {
	if (p->scope == CONSTANTS)
		p->x.name = p->name;
	else if (p->scope >= LOCAL && p->sclass == STATIC)
		p->x.name = stringf("L%d", genlabel(1));
	else if (p->generated)
		p->x.name = stringf("L%s", p->name);
	else
		p->x.name = stringf("_%s", p->name);
}

/* doarg - assign offset for next ARG node */
static void doarg(p) Node p; {
	assert(p);
	assert(p->syms[0]);
	assert(p->syms[1]);
	p->syms[2] = intconst(mkactual(p->syms[1]->u.c.v.i, p->syms[0]->u.c.v.i, 4));
}

static void emitspecial(p) Node p; {}

/* function - generate code for a function */
static void function(p, caller, callee, n) Symbol p, callee[], caller[]; {
	int i;
	unsigned fmask, imask;

	initfunc(n, 8, 0);
	for (i = 0; callee[i]; i++) {
		assert(caller[i]);
		callee[i]->x.offset = caller[i]->x.offset = offset;
		callee[i]->x.name = caller[i]->x.name = stringd(offset);
		offset = roundup(offset + caller[i]->type->size, 4);
		getregvar(callee[i], rmap[ttob(callee[i]->type)]);
	}
	assert(caller[i] == 0);
	offset = 0;
	gencode(caller, callee);
	mvregvars();
	fmask = 0;
	if (usedmask[FREG])
		for (i = 0; i < 8; i++)
			if (usedmask[FREG]&(1<<i))
				fmask |= 0x80>>i;
	imask = (((usedmask[AREG]&eemask[AREG])<<8) | (usedmask[DREG]&eemask[DREG]));
	maxoffset += 12*bitcount(fmask) + 4*bitcount(imask);
	print(".align 2\n%s:link a6,#-%d\n", p->x.name, maxoffset + argbuildsize);
	savemask[DREG] = usedmask[DREG]&eemask[DREG];
	savemask[AREG] = usedmask[AREG]&eemask[AREG];
	savemask[FREG] = usedmask[FREG]&eemask[FREG];
	savebase[DREG] = -maxoffset;
	savebase[AREG] = savebase[DREG] + 4*bitcount(savemask[DREG]);
	savebase[FREG] = savebase[AREG] + 4*bitcount(savemask[AREG]);
	if (fmask)
		print("fmovemx #0x%x,a6@(%d)\n", fmask, -maxoffset + 4*bitcount(imask));
	if (imask)
		print("moveml #0x%x,a6@(%d)\n", imask, -maxoffset);
	if (isstruct(freturn(p->type)))
		print("movl a1,a6@(-4)\n");
	if (pflag) {
		int lab = genlabel(1);
		print("movl #L%d,a0\njsr mcount\n", lab);
		print("%s\n.even\nL%d: .skip 4\n.text\n", IR->x.segnames[BSS-1], lab);
	}
	emitcode();
	if (ttob(p->type->type) == F)
		print("fmoves fp0,d0\n");
	else if (ttob(p->type->type) == D)
		print("fmoved fp0,sp@-; movl sp@+,d0; movl sp@+,d1\n");
	if (imask)
		print("moveml a6@(%d),#0x%x\n", -maxoffset, imask);
	if (fmask)
		print("fmovemx a6@(%d),#0x%x\n", -maxoffset + 4*bitcount(imask), fmask);
	print("unlk a6\nrts\n");
}

/* global - global id */
static void global(p) Symbol p; {
	assert(p->u.seg);
	if (IR == &nextInterface && p->u.seg == BSS && Aflag >= 2) {
		if (p->type->align > 1)
			print(".align %d; ", p->type->align);
		print("%s:.skip ", p->x.name);
	} else if (p->u.seg == BSS && (p->sclass == STATIC || Aflag >= 2))
		print(".lcomm %s,", p->x.name);
	else if (p->u.seg == BSS)
		print(".comm %s,", p->x.name);
	else {
		if (p->type->align > 1)
			print(".align %d; ", p->type->align);
		print("%s:", p->x.name);
	}
}

static void import(p) Symbol p; {}

/* local - local */
static void local(p) Symbol p; {
	if (getregvar(p, rmap[ttob(p->type)]) == 0)
		p->x.name = stringd(mkauto(p, 4));
}

/* progbeg - beginning of program */
static void progbeg(argc, argv) char *argv[]; {
	nregsets = 3;
	eemask[AREG] = 0x3c; eemask[DREG] = 0xfc; eemask[FREG] = 0xff;
	tmask[AREG]  = 0x07; tmask[DREG] = 0x1f; tmask[FREG] = 0x0f;
	vmask[AREG]  = 0x38; vmask[DREG] = 0xe0; vmask[FREG] = 0xf0;
	parseflags(argc, argv);
	kflag = IR == &nextInterface;
	if (kflag)
		IR->x.segnames[BSS-1] = ".data";
	initgen();
	a0	= mkregs("%d", 0, 0, 1, 1, AREG, P, 0);
	a1	= mkregs("%d", 1, 1, 1, 1, AREG, P, 0);
	d0	= mkregs("%d", 0, 0, 1, 1, DREG, I, 0);
	d1234	= mkregs("%d", 1, 4, 1, 1, DREG, I, 0);
	fp0	= mkregs("%d", 0, 0, 1, 1, FREG, D, 0);
	rmap[P] = mkregs("%d", 0, 5, 1, 1, AREG, P, 0);
	rmap[I] = mkregs("%d", 0, 7, 1, 1, DREG, I, 0);
	rmap[D] = mkregs("%d", 0, 7, 1, 1, FREG, D, 0);
	rmap[F] = rmap[D]; rmap[C] = rmap[S] = rmap[U] = rmap[I];
}

static void segment(n) {
	setseg(n);
}

static void space(n) {
	spacen(n, ".skip");
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.