summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Magnusson <ragge@cvs.openbsd.org>2008-01-24 18:47:07 +0000
committerAnders Magnusson <ragge@cvs.openbsd.org>2008-01-24 18:47:07 +0000
commitc82ba39d1b38fa096a175a3f76738285d73ab78c (patch)
tree65b61374e478b1a82c3961010d7b1df7f6edcede
parent763605a4912c725592ba8571c8460a71847b1375 (diff)
Work-in-progress for sparc64, by David Crawshaw.
-rw-r--r--usr.bin/pcc/sparc64/code.c149
-rw-r--r--usr.bin/pcc/sparc64/local.c282
-rw-r--r--usr.bin/pcc/sparc64/local2.c359
-rw-r--r--usr.bin/pcc/sparc64/macdefs.h206
-rw-r--r--usr.bin/pcc/sparc64/order.c97
-rw-r--r--usr.bin/pcc/sparc64/table.c632
6 files changed, 1725 insertions, 0 deletions
diff --git a/usr.bin/pcc/sparc64/code.c b/usr.bin/pcc/sparc64/code.c
new file mode 100644
index 00000000000..442077844b3
--- /dev/null
+++ b/usr.bin/pcc/sparc64/code.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+
+void
+defloc(struct symtab *sp)
+{
+ static char *loctbl[] = { "text", "data", "rodata" };
+ static int lastloc = -1;
+ TWORD t;
+ int s;
+
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+ if (s != lastloc)
+ printf("\n\t.section \".%s\"\n", loctbl[s]);
+ lastloc = s;
+ if (s == PROG)
+ return;
+ printf("\t.align 4\n");
+ if (sp->sclass == EXTDEF)
+ printf("\t.global %s\n", sp->soname);
+ if (sp->slevel == 0) {
+ printf("\t.type %s,#object\n", sp->soname);
+ printf("\t.size %s," CONFMT "\n", sp->soname,
+ tsize(sp->stype, sp->sdf, sp->ssue) / SZCHAR);
+ printf("%s:\n", sp->soname);
+ } else
+ printf(LABFMT ":\n", sp->soffset);
+}
+
+void
+efcode()
+{
+ /* XXX */
+}
+
+void
+bfcode(struct symtab **sp, int cnt)
+{
+ int i;
+ NODE *p, *q;
+ struct symtab *sym;
+
+ for (i=0; i < cnt && i < I7 - I0; i++) {
+ sym = sp[i];
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ q->n_rval = i + I0;
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+
+ if (i < cnt)
+ cerror("unprocessed arguments in bfcode"); /* TODO */
+}
+
+void
+bccode()
+{
+ SETOFF(autooff, SZINT);
+}
+
+void
+ejobcode(int flag)
+{
+}
+
+void
+bjobcode()
+{
+}
+
+static NODE *
+moveargs(NODE *p, int *regp)
+{
+ NODE *r, *q;
+
+ if (p->n_op == CM) {
+ p->n_left = moveargs(p->n_left, regp);
+ r = p->n_right;
+ } else {
+ r = p;
+ }
+
+ if (*regp > I7 && r->n_op != STARG)
+ cerror("reg > I7 in moveargs"); /* TODO */
+ else if (r->n_op == STARG)
+ cerror("op STARG in moveargs");
+ else if (r->n_type == DOUBLE || r->n_type == LDOUBLE)
+ cerror("FP in moveargs");
+ else if (r->n_type == FLOAT)
+ cerror("FP in moveargs");
+ else {
+ /* Argument can fit in O0...O7. */
+ q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
+ q->n_rval = (*regp)++;
+ r = buildtree(ASSIGN, q, r);
+ }
+
+ if (p->n_op == CM) {
+ p->n_right = r;
+ return p;
+ }
+
+ return r;
+}
+
+NODE *
+funcode(NODE *p)
+{
+ int reg = O0;
+ p->n_right = moveargs(p->n_right, &reg);
+ return p;
+}
+
+int
+fldal(unsigned int t)
+{
+ uerror("illegal field type");
+ return ALINT;
+}
+
+void
+fldty(struct symtab *p)
+{
+}
+
+int
+mygenswitch(int num, TWORD type, struct swents **p, int n)
+{
+ return 0;
+}
diff --git a/usr.bin/pcc/sparc64/local.c b/usr.bin/pcc/sparc64/local.c
new file mode 100644
index 00000000000..a1a002933db
--- /dev/null
+++ b/usr.bin/pcc/sparc64/local.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+
+NODE *
+clocal(NODE *p)
+{
+ struct symtab *sp;
+ int op;
+ NODE *r, *l;
+
+ op = p->n_op;
+ sp = p->n_sp;
+ l = p->n_left;
+ r = p->n_right;
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal in: %p, %s\n", p, copst(op));
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ switch (op) {
+
+ case NAME:
+ if (sp->sclass == PARAM || sp->sclass == AUTO) {
+ /*
+ * Use a fake structure reference to
+ * write out frame pointer offsets.
+ */
+ l = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
+ l->n_lval = 0;
+ l->n_rval = FP;
+ r = p;
+ p = stref(block(STREF, l, r, 0, 0, 0));
+ }
+ break;
+ case PCONV:
+ if (p->n_type > BTMASK && l->n_type > BTMASK) {
+ /* Remove unnecessary pointer conversions. */
+ l->n_type = p->n_type;
+ l->n_qual = p->n_qual;
+ l->n_df = p->n_df;
+ l->n_sue = p->n_sue;
+ nfree(p);
+ p = l;
+ }
+ break;
+
+ case SCONV:
+ if (l->n_op == NAME || l->n_op == UMUL || l->n_op == TEMP) {
+ if ((p->n_type & TMASK) == 0 &&
+ (l->n_type & TMASK) == 0 &&
+ btdims[p->n_type].suesize ==
+ btdims[l->n_type].suesize) {
+ /* XXX: skip if FP? */
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ }
+ break;
+ }
+
+ if (l->n_op != ICON)
+ break;
+
+ if (ISPTR(p->n_type)) {
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ switch (p->n_type) {
+ case BOOL: l->n_lval = (l->n_lval != 0); break;
+ case CHAR: l->n_lval = (char)l->n_lval; break;
+ case UCHAR: l->n_lval = l->n_lval & 0377; break;
+ case SHORT: l->n_lval = (short)l->n_lval; break;
+ case USHORT: l->n_lval = l->n_lval & 0177777; break;
+ case UNSIGNED:
+ case ULONG: l->n_lval = l->n_lval & 0xffffffff; break;
+ case LONG:
+ case INT: l->n_lval = (int)l->n_lval; break;
+ case ULONGLONG: l->n_lval = l->n_lval; break;
+ case LONGLONG: l->n_lval = (long long)l->n_lval; break;
+ case VOID:
+ break;
+ default:
+ cerror("sconv type unknown %d", p->n_type);
+ }
+
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+
+ case PMCONV:
+ case PVCONV:
+ if (r->n_op != ICON)
+ cerror("converting bad type");
+ nfree(p);
+ p = buildtree(op == PMCONV ? MUL : DIV, l, r);
+ break;
+
+ case FORCE:
+ /* Put attached value into the return register. */
+ p->n_op = ASSIGN;
+ p->n_right = p->n_left;
+ p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ p->n_left->n_rval = I0; /* XXX adjust for float/double */
+ break;
+ }
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal out: %p, %s\n", p, copst(op));
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ return p;
+}
+
+void
+myp2tree(NODE *p)
+{
+}
+
+int
+andable(NODE *p)
+{
+ return 1;
+}
+
+void
+cendarg()
+{
+ autooff = AUTOINIT;
+}
+
+int
+cisreg(TWORD t)
+{
+ /* SPARCv9 registers are all 64-bits wide. */
+ return 1;
+}
+
+NODE *
+offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ return bcon(off / SZCHAR);
+}
+
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+}
+
+void
+inwstring(struct symtab *sp)
+{
+}
+
+void
+instring(struct symtab *sp)
+{
+ char *s, *str;
+
+ defloc(sp);
+ str = sp->sname;
+
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; *s++) {
+ if (*s == '\\')
+ esccon(&s);
+ if (s - str > 60) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+void
+zbits(OFFSZ off, int fsz)
+{
+}
+
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+}
+
+void
+ninval(CONSZ off, int fsz, NODE *p)
+{
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: not a constant");
+ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(p->n_type) != INT)
+ cerror("ninval: not constant");
+
+ switch (DEUNSIGN(p->n_type)) {
+ case CHAR:
+ printf("\t.align 1\n");
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ break;
+ case SHORT:
+ printf("\t.align 2\n");
+ printf("\t.half %d\n", (int)p->n_lval &0xffff);
+ break;
+ case BOOL:
+ p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */
+ case INT:
+ printf("\t.align 4\n\t.long " CONFMT "\n", p->n_lval);
+ break;
+ case LONGLONG:
+ printf("\t.align 8\n\t.xword %lld\n", p->n_lval);
+ break;
+ /* TODO FP float and double */
+ }
+}
+
+char *
+exname(char *p)
+{
+ return p ? p : "";
+}
+
+TWORD
+ctype(TWORD type)
+{
+ return type;
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+void
+defzero(struct symtab *sp)
+{
+ int off = (tsize(sp->stype, sp->sdf, sp->ssue) + SZCHAR - 1) / SZCHAR;
+ printf("\t.comm ");
+ if (sp->slevel == 0)
+ printf("%s,%d\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",%d\n", sp->soffset, off);
+}
+
+int
+mypragma(char **ary)
+{
+ return 0;
+}
+
+void
+fixdef(struct symtab *sp)
+{
+}
diff --git a/usr.bin/pcc/sparc64/local2.c b/usr.bin/pcc/sparc64/local2.c
new file mode 100644
index 00000000000..179a7c78af5
--- /dev/null
+++ b/usr.bin/pcc/sparc64/local2.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass1.h"
+#include "pass2.h"
+
+/*
+ * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm
+ * means we can use a signed 13-bit constant (simm13). This gives us a
+ * shortcut for small constants, instead of loading them into a register.
+ * Special handling is required because 13 bits lies between SSCON and SCON.
+ */
+#define SIMM13(val) (val < 4096 && val > -4097)
+
+char *
+rnames[] = {
+ /* "\%g0", always zero, removed due to 31-element class limit */
+ "\%g1", "\%g2", "\%g3", "\%g4", "\%g5", "\%g6", "\%g7",
+ "\%o0", "\%o1", "\%o2", "\%o3", "\%o4", "\%o5", "\%o6", "\%o7",
+ "\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7",
+ "\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7",
+
+ "\%sp", "\%fp",
+
+ "\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7",
+ "\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15",
+ "\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23",
+ "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30"
+ /*, "\%f31" XXX removed due to 31-element class limit */
+};
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int i, stack;
+
+ /*
+ * SPARCv9 has a 2047 bit stack bias. Looking at output asm from gcc
+ * suggests this means we need a base 192 bit offset for %sp. Further
+ * steps need to be 8-byte aligned.
+ */
+ stack = 192 + p2maxautooff + (p2maxautooff % 8);
+
+ for (i=ipp->ipp_regs; i; i >>= 1)
+ if (i & 1)
+ stack += 8;
+
+ /* TODO printf("\t.proc %d\n"); */
+ printf("\t.global %s\n", ipp->ipp_name);
+ printf("\t.align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+ printf("\tsave %%sp,-%d,%%sp\n", stack);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ printf("\tret\n");
+ printf("\trestore\n");
+ printf("\t.type %s,#function\n", ipp->ipp_name);
+ printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name);
+}
+
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ case EQ: str = "brz"; break;
+ case NE: str = "brnz"; break;
+ case ULE:
+ case LE: str = "brlez"; break;
+ case ULT:
+ case LT: str = "brlz"; break;
+ case UGE:
+ case GE: str = "brgez"; break;
+ case UGT:
+ case GT: str = "brgz"; break;
+ case PLUS: str = "add"; break;
+ case MINUS: str = "sub"; break;
+ case AND: str = "and"; break;
+ case OR: str = "or"; break;
+ case ER: str = "xor"; break;
+ default:
+ comperr("unknown hopcode: %d (with %c)", o, f);
+ return;
+ }
+
+ printf("%s%c", str, f);
+}
+
+int
+tlen(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 unknown: %d");
+ return SZPOINT(p->n_type) / SZCHAR;
+ }
+}
+
+void
+zzzcode(NODE * p, int c)
+{
+ switch (c) {
+
+ case 'A': /* Load constant to register. */
+ if (!ISPTR(p->n_type) && SIMM13(p->n_lval))
+ expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n");
+ else {
+ expand(p, 0,
+ "\tsethi %h44(AL),A1\t\t! load const\n"
+ "\tor A1,%m44(AL),A1\n"
+ "\tsllx A1,12,A1\n"
+ "\tor A1,%l44(AL),A1\n");
+ }
+ break;
+ case 'B': /* Subtract const, store in temp. */
+ /*
+ * If we are dealing with a stack location, SPARCv9 has a
+ * stack offset of +2047 bits. This is mostly handled by
+ * notoff(), but when passing as an argument this op is used.
+ */
+ if (ISPTR(p->n_left->n_type) && p->n_left->n_rval == FP)
+ p->n_right->n_lval -= 2047;
+
+ if (SIMM13(p->n_right->n_lval))
+ expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const");
+ else {
+ expand(p, 0,
+ "\tsethi %h44(AR),%g1\t\t! subtract const\n"
+ "\tor %g1,%m44(AR),%g1\n"
+ "\tsllx %g1,12,%g1\n"
+ "\tor %g1,%l44(AR),%g1\n"
+ "\tsub AL,%g1,A1\n");
+ }
+ break;
+ default:
+ cerror("unknown zzzcode call: %c", c);
+
+ }
+}
+
+int
+rewfld(NODE * p)
+{
+ return (1);
+}
+
+int
+fldexpand(NODE *p, int cookie, char **cp)
+{
+ printf("XXX fldexpand called\n"); /* XXX */
+ return 1;
+}
+
+int
+flshape(NODE * p)
+{
+ return SRREG;
+}
+
+int
+shtemp(NODE * p)
+{
+ return 0;
+}
+
+
+void
+adrcon(CONSZ val)
+{
+}
+
+void
+conput(FILE * fp, NODE * p)
+{
+ if (p->n_op != ICON) {
+ comperr("conput got bad op: %s", copst(p->n_op));
+ return;
+ }
+
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (p->n_lval < 0) {
+ comperr("conput: negative offset (%lld) on label %s\n",
+ p->n_lval, p->n_name);
+ return;
+ }
+ if (p->n_lval)
+ fprintf(fp, "+%lld", p->n_lval);
+ } else
+ fprintf(fp, CONFMT, p->n_lval);
+}
+
+void
+insput(NODE * p)
+{
+ comperr("insput");
+}
+
+void
+upput(NODE *p, int size)
+{
+ comperr("upput");
+}
+
+void
+adrput(FILE * io, NODE * p)
+{
+ int64_t off;
+
+ if (p->n_op == FLD) {
+ printf("adrput a FLD\n");
+ p = p->n_left;
+ }
+
+ if (p->n_op == UMUL && p->n_right == 0)
+ p = p->n_left;
+
+ off = p->n_lval;
+
+ switch (p->n_op) {
+ case NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (off > 0)
+ fprintf(io, "+");
+ if (off != 0)
+ fprintf(io, CONFMT, off);
+ return;
+ case OREG:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ /* SPARCv9 stack bias adjustment. */
+ if (p->n_rval == FP)
+ off += 2047;
+ if (off > 0)
+ fprintf(io, "+");
+ if (off)
+ fprintf(io, "%lld", off);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ conput(io, p);
+ return;
+ case MOVE:
+ case REG:
+ fputs(rnames[p->n_rval], io);
+ return;
+
+ default:
+ comperr("bad address, %s, node %p", copst(p->n_op), p);
+ return;
+ }
+}
+
+void
+cbgen(int o, int lab)
+{
+}
+
+void
+myreader(struct interpass * ipole)
+{
+}
+
+void
+mycanon(NODE * p)
+{
+}
+
+void
+myoptim(struct interpass * ipole)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+ printf("\tmov %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]);
+}
+
+int
+gclass(TWORD t)
+{
+ return (t == FLOAT || t == DOUBLE || t == LDOUBLE) ? CLASSC : CLASSA;
+}
+
+void
+lastcall(NODE *p)
+{
+}
+
+int
+special(NODE *p, int shape)
+{
+ return SRNOPE;
+}
+
+void mflags(char *str)
+{
+}
+
+int
+COLORMAP(int c, int *r)
+{
+ int num=0;
+
+ switch (c) {
+ case CLASSA:
+ num += r[CLASSA];
+ return num < 32;
+ case CLASSB:
+ return 0;
+ case CLASSC:
+ num += r[CLASSC];
+ return num < 32;
+ default:
+ comperr("COLORMAP: unknown class");
+ return 0;
+ }
+}
diff --git a/usr.bin/pcc/sparc64/macdefs.h b/usr.bin/pcc/sparc64/macdefs.h
new file mode 100644
index 00000000000..3e392233e61
--- /dev/null
+++ b/usr.bin/pcc/sparc64/macdefs.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT (7*8) /* XXX */
+#define AUTOINIT (0)
+
+/* Type sizes */
+#define SZCHAR 8
+#define SZBOOL 32
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 64
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 64
+
+/* Type alignments */
+#define ALCHAR 8
+#define ALBOOL 32
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 64
+#define ALLDOUBLE 64
+#define ALLONG 32
+#define ALLONGLONG 64
+#define ALSHORT 16
+#define ALPOINT 32
+#define ALSTRUCT 32
+#define ALSTACK 64
+
+/* Min/max values. */
+#define MIN_CHAR -128
+#define MAX_CHAR 127
+#define MAX_UCHAR 255
+#define MIN_SHORT -32768
+#define MAX_SHORT 32767
+#define MAX_USHORT 65535
+#define MIN_INT -1
+#define MAX_INT 0x7fffffff
+#define MAX_UNSIGNED 0xffffffff
+#define MIN_LONG MIN_INT
+#define MAX_LONG MAX_INT
+#define MAX_ULONG MAX_UNSIGNED
+#define MIN_LONGLONG 0x8000000000000000LL
+#define MAX_LONGLONG 0x7fffffffffffffffLL
+#define MAX_ULONGLONG 0xffffffffffffffffULL
+
+#define BOOL_TYPE INT
+#define WCHAR_TYPE INT
+
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "%lld"
+#define LABFMT "L%d"
+#define STABLBL "LL%d"
+
+#define BACKAUTO /* Stack grows negatively for automatics. */
+#define BACKTEMP /* Stack grows negatively for temporaries. */
+
+#undef FIELDOPS
+#define RTOLBYTES
+
+#define ENUMSIZE(high,low) INT
+#define BYTEOFF(x) ((x)&03)
+#define BITOOR(x) (x)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
+
+
+/* Register names. */
+
+#define MAXREGS (31 + 2 + 31)
+#define NUMCLASS 3
+
+//define G0 -1
+#define G1 0
+#define G2 1
+#define G3 2
+#define G4 3
+#define G5 4
+#define G6 5
+#define G7 6
+#define O0 7
+#define O1 8
+#define O2 9
+#define O3 10
+#define O4 11
+#define O5 12
+#define O6 13
+#define O7 14
+#define L0 15
+#define L1 16
+#define L2 17
+#define L3 18
+#define L4 19
+#define L5 20
+#define L6 21
+#define L7 22
+#define I0 23
+#define I1 24
+#define I2 25
+#define I3 26
+#define I4 27
+#define I5 28
+#define I6 29
+#define I7 30
+
+#define SP 31
+#define FP 32
+/*
+#define F0 33
+#define F1 34
+#define F2 35
+#define F3 36
+#define F4 37
+#define F5 38
+#define F6 39
+#define F7 40
+#define F8 41
+#define F9 42
+#define F10 43
+#define F11 44
+#define F12 45
+#define F13 46
+#define F14 47
+#define F15 48
+#define F16 49
+#define F17 50
+#define F18 51
+#define F19 52
+#define F20 53
+#define F21 54
+#define F22 55
+#define F23 56
+#define F24 57
+#define F25 58
+#define F26 59
+#define F27 60
+#define F28 61
+#define F29 62
+#define F30 63
+*/
+
+#define FPREG FP
+
+#define RETREG(x) ((x)==DOUBLE || (x)==LDOUBLE || (x)==FLOAT ? 33 : O0)
+
+#define RSTATUS \
+ /* global */ \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ /* out */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* local */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* in */ \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ /* sp */ 0, \
+ /* fp */ 0, \
+ /* FP */ \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG /*, SBREG */
+
+#define ROVERLAP \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 } /*, { -1 } */
+
+#define GCLASS(x) (x < 32 ? CLASSA : (x < 34 ? CLASSB : CLASSC))
+#define PCLASS(p) (1 << gclass((p)->n_type))
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs XXX */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int XXX */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+
+int COLORMAP(int c, int *r);
diff --git a/usr.bin/pcc/sparc64/order.c b/usr.bin/pcc/sparc64/order.c
new file mode 100644
index 00000000000..271620937b0
--- /dev/null
+++ b/usr.bin/pcc/sparc64/order.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass2.h"
+
+int
+notoff(TWORD t, int r, CONSZ off, char *cp)
+{
+ return 0;
+}
+
+/*
+ * Turn a UMUL-referenced node into OREG.
+ */
+void
+offstar(NODE *p, int shape)
+{
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (p->n_op == PLUS || p->n_op == MINUS) {
+ if (p->n_right->n_op == ICON) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
+ }
+ (void)geninsn(p, INAREG);
+}
+
+void
+myormake(NODE *q)
+{
+}
+
+int
+shumul(NODE *p)
+{
+ return SOREG;
+}
+
+int
+setbin(NODE *p)
+{
+ return 0;
+}
+
+int
+setasg(NODE *p, int cookie)
+{
+ return 0;
+}
+
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+struct rspecial *
+nspecial(struct optab *q)
+{
+ return 0; /* XXX */
+}
+
+int
+setorder(NODE *p)
+{
+ return 0;
+}
+
+int *
+livecall(NODE *p)
+{
+ static int ret[] = { O0, O1, O2, O3, O4, O5, O6, O7, -1 };
+ return ret;
+}
+
+int
+acceptable(struct optab *op)
+{
+ return 1;
+}
diff --git a/usr.bin/pcc/sparc64/table.c b/usr.bin/pcc/sparc64/table.c
new file mode 100644
index 00000000000..104ef4d3937
--- /dev/null
+++ b/usr.bin/pcc/sparc64/table.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2008 David Crawshaw <david@zentus.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "pass2.h"
+
+#define TUWORD TUNSIGNED|TULONG
+#define TSWORD TINT|TLONG
+#define TWORD TUWORD|TSWORD
+
+struct optab table[] = {
+
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* empty */
+
+{ PCONV, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " ! convert between word and pointer\n", },
+
+/* Conversions. TODO: check zeroing on down conversions and signed/unsigned */
+
+{ SCONV, INAREG,
+ SOREG, TCHAR,
+ SAREG, TSWORD|TSHORT,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! int8->int16/int32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! int8 -> uint16/uint32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TUCHAR,
+ SAREG, TWORD|TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! int8 -> (u)int16/(u)int32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TCHAR,
+ SAREG, TLONGLONG,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! int8 -> int64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TUCHAR,
+ SAREG, TLONGLONG|TULONGLONG,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! uint8 -> (u)int64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! (u)int16 -> int8\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TUCHAR,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! (u)int16 -> uint8\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT,
+ SAREG, TSWORD,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! int16 -> int32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT,
+ SAREG, TUWORD,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! int16 -> uint32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TUSHORT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! uint16 -> int32\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT,
+ SAREG, TLONGLONG,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! int16 -> int64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSHORT,
+ SAREG, TULONGLONG,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! int16 -> uint64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TUSHORT,
+ SAREG, TLONGLONG|TULONGLONG,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! uint16 -> uint64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TWORD,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! int32 -> int8\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TWORD,
+ SAREG, TUCHAR,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! int32 -> uint8\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TWORD,
+ SAREG, TSHORT,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! int32 -> int16\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TWORD,
+ SAREG, TUSHORT,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! int32 -> uint16\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TSWORD,
+ SAREG, TLONGLONG|TULONGLONG,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! int32 -> (u)int64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TUWORD,
+ SAREG, TLONGLONG|TULONGLONG,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! int32 -> (u)int64\n"
+ " nop\n", },
+
+{ SCONV, INAREG,
+ SOREG, TLONGLONG|TULONGLONG,
+ SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ NAREG, RESC1,
+ " ldx [AL],A1 ! int64 -> (u)int8/16/32\n"
+ " nop\n", },
+
+/* XXX This op is catching all register-to-register conversions. Some of these
+ * need special handling. */
+
+{ SCONV, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RLEFT,
+ " \t\t! XXX in-register convert\n", },
+
+
+/* Multiplication and division */
+
+{ MUL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASR|NASL, RESC1,
+ " mulx AL,AR,AR ! multiply\n", },
+
+{ DIV, INAREG,
+ SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG,
+ SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG,
+ NAREG|NASR|NASL, RESC1,
+ " udivx AL,AR,AR ! unsigned division\n", },
+
+{ DIV, INAREG,
+ SAREG, TWORD|TSHORT|TCHAR|TLONGLONG,
+ SAREG, TWORD|TSHORT|TCHAR|TLONGLONG,
+ NAREG|NASR|NASL, RESC1,
+ " sdivx AL,AR,AR ! signed division\n", },
+
+ /* TODO MOD */
+
+{ PLUS, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESC1,
+ " add A1,AL,AR\n", },
+
+{ PLUS, INAREG,
+ SAREG, TANY,
+ SCCON, TWORD,
+ NAREG|NASL, RESC1,
+ " add AL,AR,A1 ! add constant to reg\n", },
+
+{ MINUS, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESC1,
+ " sub AL,AR,AR\n", },
+
+{ MINUS, INAREG,
+ SAREG, TANY,
+ SSCON, TANY,
+ NAREG|NASL, RESC1,
+ "ZB\n", },
+
+{ UMINUS, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " sub A1,AL,A1\n", },
+
+/* Shifts */
+
+{ RS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " sra AL,AR,AL ! shift right\n", },
+
+{ RS, INAREG,
+ SAREG, TLONGLONG|TULONGLONG,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " srax AL,AR,AL ! shift right\n", },
+
+{ LS, INAREG,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " sll AL,AR,AL ! shift left\n", },
+
+{ LS, INAREG,
+ SAREG, TLONGLONG|TULONGLONG,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " sllx AL,AR,AL ! shift left\n", },
+
+
+/* Assignments */
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TWORD,
+ SAREG, TWORD,
+ 0, RDEST,
+ " stw AR,[AL] ! store (u)int32\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " sth AR,[AL] ! store (u)int16\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ 0, RDEST,
+ " stb AR,[AL] ! store (u)int8\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TLONGLONG|TULONGLONG|TPOINT,
+ SAREG, TLONGLONG|TULONGLONG|TPOINT,
+ 0, RDEST,
+ " stx AR,[AL] ! store (u)int64\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TWORD,
+ SAREG, TWORD,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int32 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stw AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int16 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " sth AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int8 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stb AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TLONGLONG|TULONGLONG|TPOINT,
+ SAREG, TLONGLONG|TULONGLONG|TPOINT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store (u)int64 into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " stx AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RDEST,
+ " mov AL, AR ! register move\n", },
+
+/* Comparisons. */
+
+{ EQ, FORCC,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, RESCC,
+ " cmp AL,AR\n"
+ " be LC\n"
+ " nop\n", },
+
+{ NE, FORCC,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, RESCC,
+ " cmp AL,AR\n"
+ " bne LC\n"
+ " nop\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SZERO, TANY,
+ 0, RESCC,
+ " O AL,LC\n"
+ " nop\n", },
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub AL,AR,A1 ! oplog\n"
+ " O A1,LC\n"
+ " nop\n", },
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SCCON, TANY,
+ NAREG|NASL, RESCC,
+ " sub AL,AR,A1 ! oplog sccon\n"
+ " O A1,LC\n"
+ " nop\n", },
+
+
+/* Load constants to register. */
+
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TLONGLONG|TULONGLONG|TPOINT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const (u)int64 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldx [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TWORD,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const int32 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsw [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUWORD,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const uint32 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " lduw [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TSHORT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const int16 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsh [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUSHORT,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t ! load const uint16 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " lduh [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TCHAR,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t\t! load const int8 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldsb [A1+%l44(AL)],A1\n", },
+{ OPLTYPE, INAREG,
+ SCON, TANY,
+ SNAME, TUCHAR,
+ NAREG, RESC1,
+ " sethi %h44(AL),A1\t! load const uint8 to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldub [A1+%l44(AL)],A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON, TANY,
+ NAREG, RESC1,
+ "ZA" },
+
+
+/* Convert LTYPE to reg. */
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TCHAR,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! load int8 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TUCHAR,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! load uint8 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TSHORT,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! load int16 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TUSHORT,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! load uint16 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TWORD,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! load int32 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TWORD,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! load uint32 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SOREG, TLONGLONG|TULONGLONG|TPOINT,
+ NAREG, RESC1,
+ " ldx [AL],A1 ! load (u)int64 to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NAREG, RESC1,
+ " mov \%g0,A1\t ! load 0 to reg\n", },
+
+
+/* Jumps. */
+
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " call LL ! goto LL\n"
+ " nop\n", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL ! void CL()\n"
+ " nop\n", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call CL ! = CL()\n"
+ " nop\n", },
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL ! void CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call CL ! = CL(constant)\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = AL(args)\n"
+ " nop\n", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call AL ! void AL(args)\n"
+ " nop\n", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call AL ! (*AL)()\n"
+ " nop\n", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = (*AL)()\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG, RESC1,
+ " call AL ! = (*AL)(args)\n"
+ " nop\n", },
+
+
+/* Indirection. */
+
+{ OPSIMP, INAREG,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASR|NASL, RESC1,
+ " O AL,AR,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TLONGLONG|TULONGLONG|TPOINT,
+ SOREG, TLONGLONG|TULONGLONG|TPOINT,
+ NAREG, RESC1,
+ " ldx [AL],A1 ! (u)int64 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TWORD,
+ SOREG, TWORD,
+ NAREG, RESC1,
+ " ldsw [AL],A1 ! int32 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUWORD,
+ SOREG, TUWORD,
+ NAREG, RESC1,
+ " lduw [AL],A1 ! uint32 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TCHAR,
+ SOREG, TCHAR,
+ NAREG, RESC1,
+ " ldsb [AL],A1 ! int8 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUCHAR,
+ SOREG, TUCHAR,
+ NAREG, RESC1,
+ " ldub [AL],A1 ! uint8 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TSHORT,
+ SOREG, TSHORT,
+ NAREG, RESC1,
+ " ldsh [AL],A1 ! int16 load\n"
+ " nop\n", },
+{ UMUL, INAREG,
+ SANY, TUSHORT,
+ SOREG, TUSHORT,
+ NAREG, RESC1,
+ " lduh [AL],A1 ! uint16 load\n"
+ " nop\n", },
+
+{ FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE, "ERR: printing free op\n" },
+
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);