Index: uspace/app/pcc/arch/nova/local2.c
===================================================================
--- uspace/app/pcc/arch/nova/local2.c	(revision a7de7182d18160e8d93036ebe6875ba02f0d95ee)
+++ uspace/app/pcc/arch/nova/local2.c	(revision a7de7182d18160e8d93036ebe6875ba02f0d95ee)
@@ -0,0 +1,580 @@
+/*	$Id: local2.c,v 1.7 2008/11/01 08:29:37 mickey Exp $	*/
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+# include <ctype.h>
+# include <string.h>
+
+void acon(NODE *p);
+int argsize(NODE *p);
+
+void
+deflab(int label)
+{
+	printf(LABFMT ":\n", label);
+}
+
+static int prolnum;
+static struct ldq {
+	struct ldq *next;
+	int val;
+	int lab;
+	char *name;
+} *ldq;
+
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+	int i, j;
+
+	for (j = i = 0; i < MAXREGS; i++)
+		if (TESTBIT(ipp->ipp_regs, i))
+			j++;
+
+	printf(".LP%d:	.word 0%o\n", prolnum, j);
+	if (ipp->ipp_vis)
+		printf("	.globl %s\n", ipp->ipp_name);
+	printf("%s:\n", ipp->ipp_name);
+	printf("	sta 3,@40\n");	/* save ret pc on stack */
+	printf("	lda 2,.LP%d-.,1\n", prolnum);
+	printf("	jsr @45\n");
+	prolnum++;
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+	int i, j;
+
+	if (ipp->ipp_ip.ip_lbl == 0)
+		return; /* no code needs to be generated */
+
+	/* return from function code */
+	for (j = i = 0; i < MAXREGS; i++)
+		if (TESTBIT(ipp->ipp_regs, i))
+			j++;
+	printf("	lda 2,.LP%d-.,1\n", prolnum);
+	printf("	jmp @46\n");
+	printf(".LP%d:	.word 0%o\n", prolnum, j);
+	prolnum++;
+	while (ldq) {
+		printf(".LP%d:	.word 0%o", ldq->lab, ldq->val);
+		if (ldq->name && *ldq->name)
+			printf("+%s", ldq->name);
+		printf("\n");
+		ldq = ldq->next;
+	}
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+	char *str = 0;
+
+	switch (o) {
+	case PLUS:
+		str = "add";
+		break;
+	case MINUS:
+		str = "sub";
+		break;
+	case AND:
+		str = "and";
+		break;
+	case OR:
+		cerror("hopcode OR");
+		break;
+	case ER:
+		cerror("hopcode xor");
+		str = "xor";
+		break;
+	default:
+		comperr("hopcode2: %d", o);
+		str = 0; /* XXX gcc */
+	}
+	printf("%s%c", str, f);
+}
+
+#if 0
+/*
+ * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
+ */
+int
+tlen(p) NODE *p;
+{
+	switch(p->n_type) {
+		case CHAR:
+		case UCHAR:
+			return(1);
+
+		case SHORT:
+		case USHORT:
+			return(SZSHORT/SZCHAR);
+
+		case DOUBLE:
+			return(SZDOUBLE/SZCHAR);
+
+		case INT:
+		case UNSIGNED:
+		case LONG:
+		case ULONG:
+			return(SZINT/SZCHAR);
+
+		case LONGLONG:
+		case ULONGLONG:
+			return SZLONGLONG/SZCHAR;
+
+		default:
+			if (!ISPTR(p->n_type))
+				comperr("tlen type %d not pointer");
+			return SZPOINT(p->n_type)/SZCHAR;
+		}
+}
+#endif
+
+int
+fldexpand(NODE *p, int cookie, char **cp)
+{
+	return 0;
+}
+
+#if 0
+/*
+ * Assign to a bitfield.
+ * Clumsy at least, but what to do?
+ */
+static void
+bfasg(NODE *p)
+{
+	NODE *fn = p->n_left;
+	int shift = UPKFOFF(fn->n_rval);
+	int fsz = UPKFSZ(fn->n_rval);
+	int andval, tch = 0;
+
+	/* get instruction size */
+	switch (p->n_type) {
+	case CHAR: case UCHAR: tch = 'b'; break;
+	case SHORT: case USHORT: tch = 'w'; break;
+	case INT: case UNSIGNED: tch = 'l'; break;
+	default: comperr("bfasg");
+	}
+
+	/* put src into a temporary reg */
+	fprintf(stdout, "	mov%c ", tch);
+	adrput(stdout, getlr(p, 'R'));
+	fprintf(stdout, ",");
+	adrput(stdout, getlr(p, '1'));
+	fprintf(stdout, "\n");
+
+	/* AND away the bits from dest */
+	andval = ~(((1 << fsz) - 1) << shift);
+	fprintf(stdout, "	and%c $%d,", tch, andval);
+	adrput(stdout, fn->n_left);
+	fprintf(stdout, "\n");
+
+	/* AND away unwanted bits from src */
+	andval = ((1 << fsz) - 1);
+	fprintf(stdout, "	and%c $%d,", tch, andval);
+	adrput(stdout, getlr(p, '1'));
+	fprintf(stdout, "\n");
+
+	/* SHIFT left src number of bits */
+	if (shift) {
+		fprintf(stdout, "	sal%c $%d,", tch, shift);
+		adrput(stdout, getlr(p, '1'));
+		fprintf(stdout, "\n");
+	}
+
+	/* OR in src to dest */
+	fprintf(stdout, "	or%c ", tch);
+	adrput(stdout, getlr(p, '1'));
+	fprintf(stdout, ",");
+	adrput(stdout, fn->n_left);
+	fprintf(stdout, "\n");
+}
+#endif
+
+#if 0
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+	FILE *fp = stdout;
+
+	fprintf(fp, "	subl $%d,%%esp\n", p->n_stsize);
+	fprintf(fp, "	pushl $%d\n", p->n_stsize);
+	expand(p, 0, "	pushl AL\n");
+	expand(p, 0, "	leal 8(%esp),A1\n");
+	expand(p, 0, "	pushl A1\n");
+	fprintf(fp, "	call memcpy\n");
+	fprintf(fp, "	addl $12,%%esp\n");
+}
+#endif
+
+void
+zzzcode(NODE *p, int c)
+{
+	struct ldq *ld;
+
+	switch (c) {
+	case 'A': /* print out a skip ending if any numbers in queue */
+		if (ldq == NULL)
+			return;
+		printf(",skp\n.LP%d:	.word 0%o", ldq->lab, ldq->val);
+		if (ldq->name && *ldq->name)
+			printf("+%s", ldq->name);
+		printf("\n");
+		ldq = ldq->next;
+		break;
+
+	case 'B': /* print a label for later load */
+		ld = tmpalloc(sizeof(struct ldq));
+		ld->val = p->n_lval;
+		ld->name = p->n_name;
+		ld->lab = prolnum++;
+		ld->next = ldq;
+		ldq = ld;
+		printf(".LP%d-.", ld->lab);
+		break;
+
+	case 'C': /* fix reference to external variable via indirection */
+		zzzcode(p->n_left, 'B');
+		break;
+
+	case 'D': /* fix reference to external variable via indirection */
+		zzzcode(p, 'B');
+		break;
+
+	default:
+		comperr("zzzcode %c", c);
+	}
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+	return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+	int o = p->n_op;
+
+	if (o==NAME || o==REG || o==ICON || o==OREG ||
+	    (o==UMUL && shumul(p->n_left, SOREG)))
+		return(1);
+	return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+	int o = p->n_op;
+
+cerror("flshape");
+	if (o == OREG || o == REG || o == NAME)
+		return SRDIR; /* Direct match */
+	if (o == UMUL && shumul(p->n_left, SOREG))
+		return SROREG; /* Convert into oreg */
+	return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+	return 0;
+#if 0
+	int r;
+
+	if (p->n_op == STARG )
+		p = p->n_left;
+
+	switch (p->n_op) {
+	case REG:
+		return (!istreg(p->n_rval));
+
+	case OREG:
+		r = p->n_rval;
+		if (R2TEST(r)) {
+			if (istreg(R2UPK1(r)))
+				return(0);
+			r = R2UPK2(r);
+		}
+		return (!istreg(r));
+
+	case UMUL:
+		p = p->n_left;
+		return (p->n_op != UMUL && shtemp(p));
+	}
+
+	if (optype(p->n_op) != LTYPE)
+		return(0);
+	return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+	printf("$" CONFMT, val);
+}
+
+/*
+ * Conput should only be used by e2print on Nova.
+ */
+void
+conput(FILE *fp, NODE *p)
+{
+	int val = p->n_lval;
+
+	switch (p->n_op) {
+	case ICON:
+		if (p->n_name[0] != '\0') {
+			fprintf(fp, "%s", p->n_name);
+			if (val)
+				fprintf(fp, "+%d", val);
+		} else
+			fprintf(fp, "%d", val);
+		return;
+
+	default:
+		comperr("illegal conput, p %p", p);
+	}
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+	comperr("insput");
+}
+
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
+void
+upput(NODE *p, int size)
+{
+comperr("upput");
+#if 0
+	size /= SZCHAR;
+	switch (p->n_op) {
+	case REG:
+		fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
+		break;
+
+	case NAME:
+	case OREG:
+		p->n_lval += size;
+		adrput(stdout, p);
+		p->n_lval -= size;
+		break;
+	case ICON:
+		fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
+		break;
+	default:
+		comperr("upput bad op %d size %d", p->n_op, size);
+	}
+#endif
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+	/* output an address, with offsets, from p */
+
+	if (p->n_op == FLD)
+		p = p->n_left;
+
+	switch (p->n_op) {
+
+	case NAME:
+		if (p->n_name[0] != '\0')
+			fputs(p->n_name, io);
+		if (p->n_lval != 0)
+			fprintf(io, "+" CONFMT, p->n_lval);
+		return;
+
+	case OREG:
+		printf("%d,%s", (int)p->n_lval, rnames[p->n_rval]);
+		return;
+
+	case ICON:
+		/* addressable value of the constant */
+		fputc('$', io);
+		conput(io, p);
+		return;
+
+	case MOVE:
+	case REG:
+		switch (p->n_type) {
+		case LONGLONG:
+		case ULONGLONG:
+			fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
+			    rnames[p->n_rval][1], rnames[p->n_rval][2]);
+			break;
+		case SHORT:
+		case USHORT:
+			fprintf(io, "%%%s", &rnames[p->n_rval][2]);
+			break;
+		default:
+			fprintf(io, "%s", rnames[p->n_rval]);
+		}
+		return;
+
+	default:
+		comperr("illegal address, op %d, node %p", p->n_op, p);
+		return;
+
+	}
+}
+
+/*   printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+	comperr("cbgen");
+}
+
+void
+myreader(struct interpass *ipole)
+{
+	if (x2debug)
+		printip(ipole);
+}
+
+void
+mycanon(NODE *p)
+{
+}
+
+void
+myoptim(struct interpass *ip)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+	comperr("rmove");
+}
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ * Return true if we always can find a color.
+ */
+int
+COLORMAP(int c, int *r)
+{
+	int num;
+
+	switch (c) {
+	case CLASSA:
+		num = r[CLASSB] + r[CLASSA];
+		return num < 4;
+	case CLASSB:
+		num = r[CLASSB] + r[CLASSA];
+		return num < 2;
+	case CLASSC:
+		return r[CLASSC] < CREGCNT;
+	case CLASSD:
+		return r[CLASSD] < DREGCNT;
+	}
+	return 0; /* XXX gcc */
+}
+
+char *rnames[] = {
+	"0", "1", "2", "3",
+	"050", "051", "052", "053", "054", "055", "056", "057",
+	"060", "061", "062", "063", "064", "065", "066", "067",
+	"070", "071", "072", "073", "074", "075", "076", "077",
+	"041", "040"
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+	return CLASSA;
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+}
+
+/*
+ * Special shapes.
+ */
+int
+special(NODE *p, int shape)
+{
+	return SRNOPE;
+}
+
+/*
+ * Target-dependent command-line options.
+ */
+void
+mflags(char *str)
+{
+}
+/*
+ * Do something target-dependent for xasm arguments.
+ * Supposed to find target-specific constraints and rewrite them.
+ */
+int
+myxasm(struct interpass *ip, NODE *p)
+{
+	return 0;
+}
