summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2007-11-16 08:36:24 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2007-11-16 08:36:24 +0000
commitf7d7a39b9fa388ad3592ca630db976b95437e570 (patch)
tree396b761b2dbee37ca4c53f3ce3859774263ada8f /usr.bin
parent2811f223c5884b622e45a2352c89b8654da77b35 (diff)
sync with repo and brink in hppa backend from mickey. afaik, it needs
some changes in the mi parts that are not yet committed
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/pcc/hppa/code.c229
-rw-r--r--usr.bin/pcc/hppa/local.c759
-rw-r--r--usr.bin/pcc/hppa/local2.c709
-rw-r--r--usr.bin/pcc/hppa/macdefs.h418
-rw-r--r--usr.bin/pcc/hppa/order.c203
-rw-r--r--usr.bin/pcc/hppa/table.c1014
6 files changed, 3332 insertions, 0 deletions
diff --git a/usr.bin/pcc/hppa/code.c b/usr.bin/pcc/hppa/code.c
new file mode 100644
index 00000000000..66300335515
--- /dev/null
+++ b/usr.bin/pcc/hppa/code.c
@@ -0,0 +1,229 @@
+/* $OpenBSD: code.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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 "pass1.h"
+
+/*
+ * cause the alignment to become a multiple of n
+ * never called for text segment.
+ */
+void
+defalign(int n)
+{
+ n /= SZCHAR;
+ if (n == 1)
+ return;
+ printf("\t.align %d\n", n);
+}
+
+/*
+ * define the current location as the name p->sname
+ * never called for text segment.
+ */
+void
+defnam(struct symtab *p)
+{
+ char *c = p->sname;
+
+#ifdef GCC_COMPAT
+ c = gcc_findname(p);
+#endif
+ if (p->sclass == EXTDEF)
+ printf("\t.export %s, data\n", c);
+ printf("\t.label %s\n", c);
+}
+
+
+/*
+ * code for the end of a function
+ * deals with struct return here
+ */
+void
+efcode()
+{
+ NODE *p, *q;
+ int sz;
+
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+ /* address of return struct is in eax */
+ /* create a call to memcpy() */
+ /* will get the result in %ret0 */
+ p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_rval = RET0;
+ q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ q->n_rval = FP;
+ q->n_lval = 8; /* return buffer offset */
+ p = block(CM, q, p, INT, 0, MKSUE(INT));
+ sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
+ p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT));
+ p->n_right->n_name = "";
+ p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_left->n_name = "memcpy";
+ p = clocal(p);
+ send_passt(IP_NODE, p);
+}
+
+/*
+ * code for the beginning of a function; 'a' is an array of
+ * indices in symtab for the arguments; n is the number
+ */
+void
+bfcode(struct symtab **a, int n)
+{
+ int i;
+
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+ /* Function returns struct, adjust arg offset */
+ for (i = 0; i < n; i++)
+ a[i]->soffset += SZPOINT(INT);
+}
+
+
+/*
+ * by now, the automatics and register variables are allocated
+ */
+void
+bccode()
+{
+ SETOFF(autooff, SZINT);
+}
+
+/* called just before final exit */
+/* flag is 1 if errors, 0 if none */
+void
+ejobcode(int errors)
+{
+ if (errors)
+ return;
+
+ printf("\t.end\n");
+}
+
+void
+bjobcode(void)
+{
+ printf("\t.import $global$, data\n");
+}
+
+/*
+ * Print character t at position i in one string, until t == -1.
+ * Locctr & label is already defined.
+ */
+void
+bycode(int t, int i)
+{
+ static int lastoctal = 0;
+
+ /* put byte i+1 in a string */
+
+ if (t < 0) {
+ if (i != 0)
+ puts("\"");
+ } else {
+ if (i == 0)
+ printf("\t.ascii \"");
+ if (t == '\\' || t == '"') {
+ lastoctal = 0;
+ putchar('\\');
+ putchar(t);
+ } else if (t < 040 || t >= 0177) {
+ lastoctal++;
+ printf("\\%o",t);
+ } else if (lastoctal && '0' <= t && t <= '9') {
+ lastoctal = 0;
+ printf("\"\n\t.ascii \"%c", t);
+ } else {
+ lastoctal = 0;
+ putchar(t);
+ }
+ }
+}
+
+/*
+ * n integer words of zeros
+ */
+void
+zecode(int n)
+{
+ printf("\t.block %d\n", n * (SZINT/SZCHAR));
+/* inoff += n * SZINT; */
+}
+
+/*
+ * return the alignment of field of type t
+ */
+int
+fldal(unsigned int t)
+{
+ uerror("illegal field type");
+ return(ALINT);
+}
+
+/* fix up type of field p */
+void
+fldty(struct symtab *p)
+{
+}
+
+/* p points to an array of structures, each consisting
+ * of a constant value and a label.
+ * The first is >=0 if there is a default label;
+ * its value is the label number
+ * The entries p[1] to p[n] are the nontrivial cases
+ * XXX - fix genswitch.
+ */
+void
+genswitch(int num, struct swents **p, int n)
+{
+ NODE *r;
+ int i;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ r = tempnode(num, INT, 0, MKSUE(INT));
+ r = buildtree(NE, r, bcon(p[i]->sval));
+ cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
+ }
+ if (p[0]->slab > 0)
+ branch(p[0]->slab);
+}
+/*
+ * Called with a function call with arguments as argument.
+ * This is done early in buildtree() and only done once.
+ */
+NODE *
+funcode(NODE *p)
+{
+ return p;
+}
diff --git a/usr.bin/pcc/hppa/local.c b/usr.bin/pcc/hppa/local.c
new file mode 100644
index 00000000000..f1b29522f87
--- /dev/null
+++ b/usr.bin/pcc/hppa/local.c
@@ -0,0 +1,759 @@
+/* $OpenBSD: local.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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 "pass1.h"
+#include "pass2.h"
+
+/* this file contains code which is dependent on the target machine */
+
+/* clocal() is called to do local transformations on
+ * an expression tree preparitory to its being
+ * written out in intermediate code.
+ *
+ * the major essential job is rewriting the
+ * automatic variables and arguments in terms of
+ * REG and OREG nodes
+ * conversion ops which are not necessary are also clobbered here
+ * in addition, any special features (such as rewriting
+ * exclusive or) are easily handled here as well
+ */
+NODE *
+clocal(NODE *p)
+{
+
+ register struct symtab *q;
+ register NODE *r, *l, *s;
+ register int o, m, rn;
+ TWORD t;
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ break; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ /* first four integral args are in regs */
+ rn = (q->soffset >> 5) - 8;
+ if (rn < 4) {
+ r = block(REG, NIL, NIL, p->n_type, 0, 0);
+ r->n_lval = 0;
+ switch (p->n_type) {
+ case FLOAT:
+ /* TODO */
+ break;
+ case DOUBLE:
+ case LDOUBLE:
+ /* TODO */
+ break;
+ case LONGLONG:
+ case ULONGLONG:
+ r->n_rval = AD1 - rn / 2;
+ break;
+ default:
+ r->n_rval = ARG0 - rn;
+ }
+ r->n_sue = p->n_sue;
+ p->n_sue = NULL;
+ nfree(p);
+ p = r;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case AUTO:
+ /* fake up a structure reference */
+ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
+ r->n_lval = 0;
+ r->n_rval = FPREG;
+ p = stref(block(STREF, r, p, 0, 0, 0));
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ case STATIC:
+ case EXTERN:
+ l = block(REG, NIL, NIL, INT, 0, 0);
+ l->n_lval = 0;
+ l->n_rval = R1;
+ l = block(ASSIGN, l, p, INT, 0, 0);
+ r = block(ICON, NIL, NIL, INT, 0, 0);
+ r->n_sp = p->n_sp;
+ r->n_lval = 0;
+ p = block(UMUL,
+ block(PLUS, l, r, INT, 0, 0),
+ NIL, p->n_type, p->n_df, MKSUE(p->n_type));
+ break;
+ }
+ break;
+
+ case ADDROF:
+ if (!ISFTN(p->n_left->n_type))
+ break;
+
+ t = p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ l = block(REG, NIL, NIL, INT, 0, 0);
+ l->n_lval = 0;
+ l->n_rval = R1;
+ l = block(ASSIGN, l, p, INT, 0, 0);
+ r = block(ICON, NIL, NIL, INT, 0, 0);
+ r->n_sp = p->n_sp;
+ r->n_lval = 0;
+ p = block(PLUS, l, r, t, 0, 0);
+ break;
+
+ case STCALL:
+ case CALL:
+ /* Fix function call arguments. On x86, just add funarg */
+ for (r = p->n_right; r->n_op == CM; r = r->n_left) {
+ if (r->n_right->n_op != STARG &&
+ r->n_right->n_op != FUNARG)
+ /* TODO put first four into regs */
+ r->n_right = block(FUNARG, r->n_right, NIL,
+ r->n_right->n_type, r->n_right->n_df,
+ r->n_right->n_sue);
+ }
+ if (r->n_op != STARG && r->n_op != FUNARG) {
+ l = talloc();
+ *l = *r;
+ r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type;
+ }
+ break;
+
+ case CBRANCH:
+ l = p->n_left;
+
+ /*
+ * Remove unneccessary conversion ops.
+ */
+ if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
+ if (coptype(l->n_op) != BITYPE)
+ break;
+ if (l->n_right->n_op == ICON) {
+ r = l->n_left->n_left;
+ if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
+ break;
+ /* Type must be correct */
+ t = r->n_type;
+ nfree(l->n_left);
+ l->n_left = r;
+ l->n_type = t;
+ l->n_right->n_type = t;
+ }
+ }
+ break;
+
+ case PCONV:
+ /* Remove redundant PCONV's. Be careful */
+ l = p->n_left;
+ if (l->n_op == ICON) {
+ l->n_lval = (unsigned)l->n_lval;
+ goto delp;
+ }
+ if (l->n_type < INT || l->n_type == LONGLONG ||
+ l->n_type == ULONGLONG) {
+ /* float etc? */
+ p->n_left = block(SCONV, l, NIL,
+ UNSIGNED, 0, MKSUE(UNSIGNED));
+ break;
+ }
+ /* if left is SCONV, cannot remove */
+ if (l->n_op == SCONV)
+ break;
+
+ /* avoid ADDROF TEMP */
+ if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
+ break;
+
+ /* if conversion to another pointer type, just remove */
+ if (p->n_type > BTMASK && l->n_type > BTMASK)
+ goto delp;
+ break;
+
+ delp: 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:
+ l = p->n_left;
+
+ if (p->n_type == l->n_type) {
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
+ btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
+ if (p->n_type != FLOAT && p->n_type != DOUBLE &&
+ l->n_type != FLOAT && l->n_type != DOUBLE &&
+ l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
+ if (l->n_op == UMUL || l->n_op == TEMP ||
+ l->n_op == NAME) {
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+ }
+ }
+ }
+
+ if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
+ coptype(l->n_op) == BITYPE) {
+ l->n_type = p->n_type;
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ o = l->n_op;
+ m = p->n_type;
+
+ if (o == ICON) {
+ CONSZ val = l->n_lval;
+
+ if (!ISPTR(m)) /* Pointers don't need to be conv'd */
+ switch (m) {
+ case BOOL:
+ l->n_lval = l->n_lval != 0;
+ break;
+ case CHAR:
+ l->n_lval = (char)val;
+ break;
+ case UCHAR:
+ l->n_lval = val & 0377;
+ break;
+ case SHORT:
+ l->n_lval = (short)val;
+ break;
+ case USHORT:
+ l->n_lval = val & 0177777;
+ break;
+ case ULONG:
+ case UNSIGNED:
+ l->n_lval = val & 0xffffffff;
+ break;
+ case ENUMTY:
+ case MOETY:
+ case LONG:
+ case INT:
+ l->n_lval = (int)val;
+ break;
+ case LONGLONG:
+ l->n_lval = (long long)val;
+ break;
+ case ULONGLONG:
+ l->n_lval = val;
+ break;
+ case VOID:
+ break;
+ case LDOUBLE:
+ case DOUBLE:
+ case FLOAT:
+ l->n_op = FCON;
+ l->n_dcon = val;
+ break;
+ default:
+ cerror("unknown type %d", m);
+ }
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return l;
+ }
+ if (DEUNSIGN(p->n_type) == SHORT &&
+ DEUNSIGN(l->n_type) == SHORT) {
+ nfree(p);
+ p = l;
+ }
+ if ((p->n_type == CHAR || p->n_type == UCHAR ||
+ p->n_type == SHORT || p->n_type == USHORT) &&
+ (l->n_type == FLOAT || l->n_type == DOUBLE ||
+ l->n_type == LDOUBLE)) {
+ p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left->n_type = INT;
+ break;
+ }
+ break;
+
+ case MOD:
+ case DIV:
+ if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ /* make it an int division by inserting conversions */
+ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
+ p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
+ p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
+ p->n_left->n_type = INT;
+ break;
+
+ case PMCONV:
+ case PVCONV:
+ if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
+ nfree(p);
+ return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
+
+ case LS:
+ case RS:
+ /* shift count must be in an int */
+ if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32)
+ break; /* do not do anything */
+ if (p->n_right->n_type != INT || p->n_right->n_lval > 32)
+ p->n_right = block(SCONV, p->n_right, NIL,
+ INT, 0, MKSUE(INT));
+ break;
+
+#if 0
+ case FLD:
+ /* already rewritten (in ASSIGN) */
+ if (p->n_left->n_op == TEMP)
+ break;
+
+ r = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue);
+ p->n_left = tcopy(r);
+ p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue);
+ break;
+#endif
+
+ case FORCE:
+ /* put return value in return reg */
+ p->n_op = ASSIGN;
+ p->n_right = p->n_left;
+ p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left->n_rval = p->n_left->n_type == BOOL ?
+ RETREG(CHAR) : RETREG(p->n_type);
+ if (p->n_right->n_op != FLD)
+ break;
+ break;
+
+ case ASSIGN:
+ if (p->n_left->n_op != FLD)
+ break;
+ l = p->n_left;
+ r = tempnode(0, l->n_type, l->n_df, l->n_sue);
+ p = block(COMOP,
+ block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue),
+ p, p->n_type, p->n_df, p->n_sue);
+ s = tcopy(l->n_left);
+ p = block(COMOP, p,
+ block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue),
+ p->n_type, p->n_df, p->n_sue);
+ l->n_left = tcopy(r);
+ break;
+ }
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal end: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ return(p);
+}
+
+void
+myp2tree(NODE *p)
+{
+}
+
+/*ARGSUSED*/
+int
+andable(NODE *p)
+{
+ return(1); /* all names can have & taken on them */
+}
+
+/*
+ * at the end of the arguments of a ftn, set the automatic offset
+ */
+void
+cendarg()
+{
+ autooff = AUTOINIT;
+}
+
+/*
+ * Return 1 if a variable of type type is OK to put in register.
+ */
+int
+cisreg(TWORD t)
+{
+ return 1;
+}
+
+/*
+ * return a node, for structure references, which is suitable for
+ * being added to a pointer of type t, in order to be off bits offset
+ * into a structure
+ * t, d, and s are the type, dimension offset, and sizeoffset
+ * For pdp10, return the type-specific index number which calculation
+ * is based on its size. For example, short a[3] would return 3.
+ * Be careful about only handling first-level pointers, the following
+ * indirections must be fullword.
+ */
+NODE *
+offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ register NODE *p;
+
+ if (xdebug)
+ printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
+ off, t, d, sue->suesize);
+
+ p = bcon(0);
+ p->n_lval = off/SZCHAR; /* Default */
+ return(p);
+}
+
+/*
+ * Allocate off bits on the stack. p is a tree that when evaluated
+ * is the multiply count for off, t is a storeable node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
+
+ /* sub the size from sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(PLUSEQ, sp, p));
+
+ /* save the address of sp */
+ sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ t->n_type = sp->n_type;
+ ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
+
+}
+
+#if 0
+/*
+ * Print out an integer constant of size size.
+ * can only be sizes <= SZINT.
+ */
+void
+indata(CONSZ val, int size)
+{
+ switch (size) {
+ case SZCHAR:
+ printf("\t.byte %d\n", (int)val & 0xff);
+ break;
+ case SZSHORT:
+ printf("\t.word %d\n", (int)val & 0xffff);
+ break;
+ case SZINT:
+ printf("\t.long %d\n", (int)val & 0xffffffff);
+ break;
+ default:
+ cerror("indata");
+ }
+}
+#endif
+
+/*
+ * Print out a string of characters.
+ * Assume that the assembler understands C-style escape
+ * sequences. Location is already set.
+ */
+void
+instring(char *str)
+{
+ char *s;
+
+ /* be kind to assemblers and avoid long strings */
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; ) {
+ if (*s++ == '\\') {
+ (void)esccon(&s);
+ }
+ if (s - str > 64) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+static int inbits, inval;
+
+/*
+ * set fsz bits in sequence to zero.
+ */
+void
+zbits(OFFSZ off, int fsz)
+{
+ int m;
+
+ if (idebug)
+ printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
+ if ((m = (inbits % SZCHAR))) {
+ m = SZCHAR - m;
+ if (fsz < m) {
+ inbits += fsz;
+ return;
+ } else {
+ fsz -= m;
+ printf("\t.byte %d\n", inval);
+ inval = inbits = 0;
+ }
+ }
+ if (fsz >= SZCHAR) {
+ printf("\t.zero %d\n", fsz/SZCHAR);
+ fsz -= (fsz/SZCHAR) * SZCHAR;
+ }
+ if (fsz) {
+ inval = 0;
+ inbits = fsz;
+ }
+}
+
+/*
+ * Initialize a bitfield.
+ */
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+ if (idebug)
+ printf("infld off %lld, fsz %d, val %lld inbits %d\n",
+ off, fsz, val, inbits);
+ val &= (1 << fsz)-1;
+ while (fsz + inbits >= SZCHAR) {
+ inval |= (val << inbits);
+ printf("\t.byte %d\n", inval & 255);
+ fsz -= (SZCHAR - inbits);
+ val >>= (SZCHAR - inbits);
+ inval = inbits = 0;
+ }
+ if (fsz) {
+ inval |= (val << inbits);
+ inbits += fsz;
+ }
+}
+
+/*
+ * print out a constant node, may be associated with a label.
+ * Do not free the node after use.
+ * off is bit offset from the beginning of the aggregate
+ * fsz is the number of bits this is referring to
+ *
+ * XXX this relies on the host fp numbers representation
+ */
+void
+ninval(CONSZ off, int fsz, NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+ struct symtab *q;
+ TWORD t;
+ int i;
+
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: init node not constant");
+
+ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
+ uerror("element not constant");
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ i = (p->n_lval >> 32);
+ p->n_lval &= 0xffffffff;
+ p->n_type = INT;
+ ninval(off, 32, p);
+ p->n_lval = i;
+ ninval(off+32, 32, p);
+ break;
+ case INT:
+ case UNSIGNED:
+ printf("\t.long 0x%x", (int)p->n_lval);
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+ q->sclass == ILABEL) {
+ printf("+" LABFMT, q->soffset);
+ } else
+ printf("+%s", exname(q->sname));
+ }
+ printf("\n");
+ break;
+ case SHORT:
+ case USHORT:
+ printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
+ break;
+ case BOOL:
+ if (p->n_lval > 1)
+ p->n_lval = p->n_lval != 0;
+ /* FALLTHROUGH */
+ case CHAR:
+ case UCHAR:
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ break;
+ case LDOUBLE:
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.long\t0x%x\n", u.i[0]);
+ break;
+ default:
+ cerror("ninval");
+ }
+}
+
+/* make a name look like an external name in the local machine */
+char *
+exname(char *p)
+{
+ if (p == NULL)
+ return "";
+ return p;
+}
+
+/*
+ * map types which are not defined on the local machine
+ */
+TWORD
+ctype(TWORD type)
+{
+ switch (BTYPE(type)) {
+ case LONG:
+ MODTYPE(type,INT);
+ break;
+
+ case ULONG:
+ MODTYPE(type,UNSIGNED);
+ }
+
+ return (type);
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+ printf("\t.call\n");
+}
+
+void
+extdec(struct symtab *q)
+{
+#ifdef GCC_COMPAT
+ printf("\t.import\t%s,data\n", gcc_findname(q));
+#else
+ printf("\t.import\t%s,data\n", exname(q->sname));
+#endif
+}
+
+/* make a common declaration for id, if reasonable */
+void
+commdec(struct symtab *q)
+{
+ int off;
+
+ off = tsize(q->stype, q->sdf, q->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+#ifdef GCC_COMPAT
+ printf("\t.label\t%s\n", gcc_findname(q));
+#else
+ printf("\t.label\t%s\n", exname(q->sname));
+#endif
+ printf("\t.comm\t%d\n", off);
+}
+
+/* make a local common declaration for id, if reasonable */
+void
+lcommdec(struct symtab *q)
+{
+ int off;
+
+ off = tsize(q->stype, q->sdf, q->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ if (q->slevel == 0)
+#ifdef GCC_COMPAT
+ printf("\t.lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf("\t.lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf("\t.lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf("\t.label\t" LABFMT "\n", label);
+}
+
+static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+ printf("\t.%s\n", loctbl[locc]);
+}
diff --git a/usr.bin/pcc/hppa/local2.c b/usr.bin/pcc/hppa/local2.c
new file mode 100644
index 00000000000..c3800e493f6
--- /dev/null
+++ b/usr.bin/pcc/hppa/local2.c
@@ -0,0 +1,709 @@
+/* $OpenBSD: local2.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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);
+
+static int stkpos;
+
+static const int rl[] =
+ { R1, R5, R7, R9, R11, R13, R15, R17, T4, T2, ARG3, ARG1, RET1 };
+static const int rh[] =
+ { R31, R4, R6, R8, R10, R12, R14, R16, T3, T1, ARG2, ARG0, RET0 };
+
+void
+deflab(int label)
+{
+ printf("\t.label\t" LABFMT "\n", label);
+}
+
+static int regoff[MAXREGS];
+static TWORD ftype;
+
+/*
+ * Print out the prolog assembler.
+ * addto and regoff are already calculated.
+ */
+static void
+prtprolog(struct interpass_prolog *ipp, int addto)
+{
+ int i;
+
+ printf("\tcopy\t%%r3,%%r1\n"
+ "\tcopy\t%%sp,%%r3\n"
+ "\tstw,ma\t%%r1,%d(%%sp)\n", addto);
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i)) {
+ if (i <= R31)
+ printf("\tstw\t%s,%d(%s)\n",
+ rnames[i], regoff[i], rnames[FPREG]);
+ else if (i < RETD0)
+ printf("\tstw\t%s,%d(%s)\n\tstw\t%s,%d(%s)\n",
+ rnames[rl[i - RD0]], regoff[i] + 0, rnames[FPREG],
+ rnames[rh[i - RD0]], regoff[i] + 4, rnames[FPREG]);
+ else if (i <= FR31)
+ ;
+ else
+ ;
+ }
+}
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int i, addto;
+
+ addto = 32;
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i)) {
+ regoff[i] = addto;
+ addto += SZINT/SZCHAR;
+ }
+ addto += p2maxautooff;
+ return (addto + 63) & ~63;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+
+ ftype = ipp->ipp_type;
+ printf("\t.align\t4\n");
+ if (ipp->ipp_vis)
+ printf("\t.export\t%s, code\n", ipp->ipp_name);
+ printf("\t.label\t%s\n\t.proc\n", ipp->ipp_name);
+
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+ printf("\t.callinfo frame=%d, save_rp, save_sp\n\t.entry\n", addto);
+ prtprolog(ipp, addto);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i;
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = 0; i < MAXREGS; i++)
+ if (TESTBIT(ipp->ipp_regs, i))
+ printf("\tldw\t%d(%s),%s\n",
+ regoff[i], rnames[FPREG], rnames[i]);
+
+ /* TODO restore sp,rp */
+ printf("\tbv\t%%r0(%%rp)\n\tnop\n"
+ "\t.exit\n\t.procend\n\t.size\t%s, .-%s\n",
+ ipp->ipp_name, ipp->ipp_name);
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ 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;
+ case EQ:
+ str = "=";
+ break;
+ case NE:
+ str = "<>";
+ break;
+ case LE:
+ str = "<";
+ break;
+ case LT:
+ str = "<=";
+ break;
+ case GE:
+ str = ">";
+ break;
+ case GT:
+ str = ">=";
+ break;
+ case ULE:
+ str = "<<";
+ break;
+ case ULT:
+ str = "<<=";
+ break;
+ case UGE:
+ str = ">>";
+ break;
+ case UGT:
+ str = ">>=";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+ printf("%s%c", str, f);
+}
+
+/*
+ * 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 FLOAT:
+ return(SZFLOAT/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;
+ }
+}
+
+static int
+argsiz(NODE *p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONGLONG || t == FLOAT || t > BTMASK)
+ return 4;
+ if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
+ return 8;
+ if (t == LDOUBLE)
+ return 8; /* quad is 16 */
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ int n;
+
+ switch (c) {
+
+ case 'C': /* after-call fixup */
+ n = p->n_qual;
+ if (n)
+ printf("\tldo\t-%d(%%sp),%%sp\n", n);
+ break;
+
+ case 'P': /* returning struct-call setup */
+ n = p->n_qual;
+ if (n)
+ printf("\tldo\t%d(%%sp),%%sp\n", n);
+ break;
+
+ case 'F': /* output extr/dep offset/len parts for bitfields */
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+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)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (isreg(p))
+ return SRDIR; /* Direct match */
+
+ 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)
+{
+ /* fix for L% and R% */
+ printf(CONFMT, val);
+}
+
+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, "RR'%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ fprintf(fp, "-$global$");
+ } 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)
+{
+
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ printf("%s", rnames[rh[p->n_rval - RD0]]);
+ break;
+
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+
+ case ICON:
+ case NAME:
+ if (p->n_name[0] != '\0') {
+ printf("LL'%s", p->n_name);
+ if (p->n_lval != 0)
+ printf("+" CONFMT, p->n_lval);
+ printf("-$global$");
+ } else
+ printf("L%%" CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+ int r;
+ /* output an address, with offsets, from p */
+
+ if (p->n_op == FLD)
+ p = p->n_left;
+
+ switch (p->n_op) {
+
+ case ICON:
+ case NAME:
+ if (p->n_name[0] != '\0') {
+ fprintf(io, "RR'%s", p->n_name);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ fprintf(io, "-$global$");
+ } else
+ fprintf(io, "R%%" CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+ if (p->n_name[0] != '\0') {
+ fprintf(io, "RR'%s", p->n_name);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ fprintf(io, "-$global$");
+ } else if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+ if (R2TEST(r)) {
+ fprintf(io, "%s(%s)", rnames[R2UPK1(r)],
+ rnames[R2UPK2(r)]);
+ } else
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case MOVE:
+ case REG:
+ if (RD0 <= p->n_rval && p->n_rval <= RETD0)
+ fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]);
+ else
+ fprintf(io, "%s", rnames[p->n_rval]);
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+/* not used */
+void
+cbgen(int o, int lab)
+{
+}
+
+static void
+fixcalls(NODE *p)
+{
+ /* Prepare for struct return by allocating bounce space on stack */
+ switch (p->n_op) {
+ case STCALL:
+ case USTCALL:
+ if (p->n_stsize+p2autooff > stkpos)
+ stkpos = p->n_stsize+p2autooff;
+ break;
+ }
+}
+
+void
+myreader(struct interpass *ipole)
+{
+ struct interpass *ip;
+
+ stkpos = p2autooff;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ walkf(ip->ip_node, fixcalls);
+ }
+ if (stkpos > p2autooff)
+ p2autooff = stkpos;
+ if (stkpos > p2maxautooff)
+ p2maxautooff = stkpos;
+ if (x2debug)
+ printip(ipole);
+}
+
+/*
+ * Remove some PCONVs after OREGs are created.
+ */
+static void
+pconv2(NODE *p)
+{
+ NODE *q;
+
+ if (p->n_op == PLUS) {
+ if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
+ if (p->n_right->n_op != ICON)
+ return;
+ if (p->n_left->n_op != PCONV)
+ return;
+ if (p->n_left->n_left->n_op != OREG)
+ return;
+ q = p->n_left->n_left;
+ nfree(p->n_left);
+ p->n_left = q;
+ /*
+ * This will be converted to another OREG later.
+ */
+ }
+ }
+}
+
+void
+mycanon(NODE *p)
+{
+ walkf(p, pconv2);
+}
+
+void
+myoptim(struct interpass *ip)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+ int sl, sh, dl, dh;
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ sl = rl[s-RD0];
+ sh = rh[s-RD0];
+ dl = rl[d-RD0];
+ dh = rh[d-RD0];
+
+ /* sanity checks, remove when satisfied */
+ if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 ||
+ memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0)
+ comperr("rmove source error");
+ if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 ||
+ memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0)
+ comperr("rmove dest error");
+#define SW(x,y) { int i = x; x = y; y = i; }
+ if (sl == dh || sh == dl) {
+ /* Swap if moving to itself */
+ SW(sl, sh);
+ SW(dl, dh);
+ }
+ if (sl != dl)
+ printf("\tcopy\t%s,%s\n", rnames[sl], rnames[dl]);
+ if (sh != dh)
+ printf("\tcopy\t%s,%s\n", rnames[sh], rnames[dh]);
+ break;
+ case FLOAT:
+ printf("\tfcpy,sgl\t%s,%s\n", rnames[s], rnames[d]);
+ break;
+ case DOUBLE:
+ case LDOUBLE:
+ printf("\tfcpy,dbl\t%s,%s\n", rnames[s], rnames[d]);
+ break;
+ default:
+ printf("\tcopy\t%s,%s\n", rnames[s], rnames[d]);
+ }
+}
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ */
+int
+COLORMAP(int c, int *r)
+{
+ int num;
+
+ switch (c) {
+ case CLASSA:
+ num = 2 * r[CLASSB];
+ num += r[CLASSA];
+ return num < 28;
+ case CLASSB:
+ num = r[CLASSA];
+ num += r[CLASSB] * 2;
+ return num < 28;
+ case CLASSC:
+ num = (r[CLASSD] > 8? 8 : r[CLASSD]) * 2;
+ num += r[CLASSC];
+ return num < 28;
+ case CLASSD:
+ num = (r[CLASSC] + 1) / 2;
+ num += r[CLASSD];
+ return num < 28;
+ }
+ return 0; /* XXX gcc */
+}
+
+const char * const rnames[MAXREGS] = {
+ "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9",
+ "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18",
+ "%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp",
+ "%ret0", "%ret1", "%sp", "%r31",
+ "%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7",
+ "%td2", "%td1", "%ad1", "%ad0", "%retd0",
+ "%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10",
+ "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18",
+ "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26",
+ "%fr27", "%fr28", "%fr29", "%fr30", "%fr31",
+ "%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r",
+ "%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r",
+ "%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r",
+ "%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r",
+ "%fr16l", "%fr16r", "%fr17l", "%fr17r",
+#ifdef __hppa64__
+ "%fr18l", "%fr18r", "%fr19l", "%fr19r",
+ "%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r",
+ "%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r",
+ "%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r",
+ "%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r",
+#endif
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ return CLASSB;
+ case FLOAT:
+ return CLASSC;
+ case DOUBLE:
+ case LDOUBLE:
+ return CLASSD;
+ default:
+ return CLASSA;
+ }
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+ NODE *op = p;
+ int size = 64;
+
+ p->n_qual = size;
+ if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
+ return;
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ size += argsiz(p->n_right);
+ size += argsiz(p);
+ op->n_qual = size; /* XXX */
+}
+
+/*
+ * Special shapes.
+ */
+int
+special(NODE *p, int shape)
+{
+ int o = p->n_op;
+
+ switch (shape) {
+ case SFUNCALL:
+ if (o == STCALL || o == USTCALL)
+ return SRREG;
+ break;
+ case SPICON:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval < -1024 || p->n_lval >= 1024)
+ break;
+ return SRDIR;
+ case SPCON:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval < -8192 || p->n_lval >= 8192)
+ break;
+ return SRDIR;
+ case SPNAME:
+ if (o != ICON || !p->n_name[0])
+ break;
+ return SRDIR;
+ }
+ return SRNOPE;
+}
diff --git a/usr.bin/pcc/hppa/macdefs.h b/usr.bin/pcc/hppa/macdefs.h
new file mode 100644
index 00000000000..b2addf2fef2
--- /dev/null
+++ b/usr.bin/pcc/hppa/macdefs.h
@@ -0,0 +1,418 @@
+/* $OpenBSD: macdefs.h,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ */
+#define makecc(val,i) (lastcon = (lastcon<<8)|((val<<24)>>24))
+
+#define ARGINIT (32*8) /* bits below fp where args start */
+#define AUTOINIT (4*8) /* bits above fp where locals start */
+
+/*
+ * storage sizes
+ */
+#define SZCHAR 8
+#define SZBOOL 8
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 64 /* or later 128 */
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 32
+
+/*
+ * alignment requirements
+ */
+#define ALCHAR 8
+#define ALBOOL 8
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 64
+#define ALLDOUBLE 64 /* 128 later */
+#define ALLONG 32
+#define ALLONGLONG 64
+#define ALSHORT 16
+#define ALPOINT 32
+#define ALSTRUCT 64
+#define ALSTACK 64
+
+/*
+ * type value limits
+ */
+#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 (-0x7fffffff-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 (-0x7fffffffffffffffLL-1)
+#define MAX_LONGLONG 0x7fffffffffffffffLL
+#define MAX_ULONGLONG 0xffffffffffffffffULL
+
+#undef CHAR_UNSIGNED
+#define BOOL_TYPE CHAR
+#define WCHAR_TYPE INT
+#define ENUMSIZE(high,low) INT
+
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "%lld" /* format for printing constants */
+#define LABFMT ".L%d" /* format for printing labels */
+#define STABLBL ".LL%d" /* format for stab (debugging) labels */
+
+#undef BACKAUTO /* stack grows upwards */
+#undef BACKTEMP /* stack grows upwards */
+
+#define MYP2TREE(p) myp2tree(p)
+
+#define FIELDOPS /* have bit field ops */
+#define LTORBYTES /* big endian */
+
+#define BYTEOFF(x) ((x)&03)
+#define wdal(k) (BYTEOFF(k)==0)
+#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 2 : 1)
+
+#define R1 0
+#define RP 1
+#define FP 2
+#define R4 3
+#define R5 4
+#define R6 5
+#define R7 6
+#define R8 7
+#define R9 8
+#define R10 9
+#define R11 10
+#define R12 11
+#define R13 12
+#define R14 13
+#define R15 14
+#define R16 15
+#define R17 16
+#define R18 17
+#define T4 18
+#define T3 19
+#define T2 20
+#define T1 21
+#define ARG3 22
+#define ARG2 23
+#define ARG1 24
+#define ARG0 25
+#define DP 26
+#define RET0 27
+#define RET1 28
+#define SP 29
+#define R31 30
+
+/* double regs overlay */
+#define RD0 31 /* r1:r31 */
+#define RD1 32 /* r5:r4 */
+#define RD2 33 /* r7:r6 */
+#define RD3 34 /* r9:r8 */
+#define RD4 35 /* r11:r10 */
+#define RD5 36 /* r13:r12 */
+#define RD6 37 /* r15:r14 */
+#define RD7 38 /* r17:r16 */
+#define TD2 39 /* t4:t3 */
+#define TD1 40 /* t2:t1 */
+#define AD2 41 /* arg3:arg2 */
+#define AD1 42 /* arg1:arg0 */
+#define RETD0 43 /* ret1:ret0 */
+
+/* FPU regs */
+#define FR0 44
+#define FR4 45
+#define FR5 46
+#define FR6 47
+#define FR7 48
+#define FR8 49
+#define FR9 50
+#define FR10 51
+#define FR11 52
+#define FR12 53
+#define FR13 54
+#define FR14 55
+#define FR15 56
+#define FR16 57
+#define FR17 58
+#define FR18 59
+#define FR19 60
+#define FR20 61
+#define FR21 62
+#define FR22 63
+#define FR23 64
+#define FR24 65
+#define FR25 66
+#define FR26 67
+#define FR27 68
+#define FR28 69
+#define FR29 70
+#define FR30 71
+#define FR31 72
+
+#define FR0L 73
+#define FR0R 74
+#define FR4L 75
+#define FR4R 76
+#define FR5L 77
+#define FR5R 78
+#define FR6L 79
+#define FR6R 80
+#define FR7L 81
+#define FR7R 82
+#define FR8L 83
+#define FR8R 84
+#define FR9L 85
+#define FR9R 86
+#define FR10L 87
+#define FR10R 88
+#define FR11L 89
+#define FR11R 90
+#define FR12L 91
+#define FR12R 92
+#define FR13L 93
+#define FR13R 94
+#define FR14L 95
+#define FR14R 96
+#define FR15L 97
+#define FR15R 98
+#define FR16L 99
+#define FR16R 100
+#define FR17L 101
+#define FR17R 102
+#ifdef __hppa64__
+#define FR18L 103
+#define FR18R 104
+#define FR19L 105
+#define FR19R 106
+#define FR20L 107
+#define FR20R 108
+#define FR21L 109
+#define FR21R 110
+#define FR22L 111
+#define FR22R 112
+#define FR23L 113
+#define FR23R 114
+#define FR24L 115
+#define FR24R 116
+#define FR25L 117
+#define FR25R 118
+#define FR26L 119
+#define FR26R 120
+#define FR27L 121
+#define FR27R 122
+#define FR28L 123
+#define FR28R 124
+#define FR29L 125
+#define FR29R 126
+#define FR30L 127
+#define FR30R 128
+#define FR31L 129
+#define FR31R 130
+
+#define MAXREGS 131
+#else
+#define MAXREGS 103
+#endif
+
+#define RSTATUS \
+ SAREG|TEMPREG, 0, 0, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ 0, SAREG|TEMPREG, SAREG|TEMPREG, 0, SAREG|TEMPREG, \
+ /* double overlays */ \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ /* double-precision floats */ \
+ 0, \
+ SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \
+ SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \
+ SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \
+ SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \
+ SDREG|PERMREG, SDREG|PERMREG, \
+ SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \
+ SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \
+ SDREG|TEMPREG, SDREG|TEMPREG, \
+ /* single-precision floats */ \
+ 0, 0, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG,
+#ifdef __hppa64__
+ SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG,
+#endif
+
+#define ROVERLAP \
+ { RD0, -1 }, { -1 }, { -1 }, \
+ { RD1, -1 }, { RD1, -1 }, \
+ { RD2, -1 }, { RD2, -1 }, \
+ { RD3, -1 }, { RD3, -1 }, \
+ { RD4, -1 }, { RD4, -1 }, \
+ { RD5, -1 }, { RD5, -1 }, \
+ { RD6, -1 }, { RD6, -1 }, \
+ { RD7, -1 }, { RD7, -1 }, \
+ { -1 }, \
+ { TD2, -1 }, { TD2, -1 }, \
+ { TD1, -1 }, { TD1, -1 }, \
+ { AD2, -1 }, { AD2, -1 }, \
+ { AD1, -1 }, { AD1, -1 }, \
+ { -1 }, \
+ { RETD0, -1 }, { RETD0, -1 }, \
+ { -1 }, { RD0, -1 }, \
+ { R1, R31, -1 }, \
+ { R4, R5, -1 }, \
+ { R6, R7, -1 }, \
+ { R8, R9, -1 }, \
+ { R10, R11, -1 }, \
+ { R12, R13, -1 }, \
+ { R14, R15, -1 }, \
+ { R16, R17, -1 }, \
+ { T4, T3, -1 }, \
+ { T2, T1, -1 }, \
+ { ARG3, ARG2, -1 }, \
+ { ARG1, ARG0, -1 }, \
+ { RET1, RET0, -1 }, \
+ { -1 }, \
+ { FR4L, FR4R, -1 }, \
+ { FR5L, FR5R, -1 }, \
+ { FR6L, FR6R, -1 }, \
+ { FR7L, FR7R, -1 }, \
+ { FR8L, FR8R, -1 }, \
+ { FR9L, FR9R, -1 }, \
+ { FR10L, FR10R, -1 }, \
+ { FR11L, FR11R, -1 }, \
+ { FR12L, FR12R, -1 }, \
+ { FR13L, FR13R, -1 }, \
+ { FR14L, FR14R, -1 }, \
+ { FR15L, FR15R, -1 }, \
+ { FR16L, FR16R, -1 }, \
+ { FR17L, FR17R, -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, \
+ { -1 }, { -1 }, \
+ { FR4, -1 }, { FR4, -1 }, \
+ { FR5, -1 }, { FR5, -1 }, \
+ { FR6, -1 }, { FR6, -1 }, \
+ { FR7, -1 }, { FR7, -1 }, \
+ { FR8, -1 }, { FR8, -1 }, \
+ { FR9, -1 }, { FR9, -1 }, \
+ { FR10, -1 }, { FR10, -1 }, \
+ { FR11, -1 }, { FR11, -1 }, \
+ { FR12, -1 }, { FR12, -1 }, \
+ { FR13, -1 }, { FR13, -1 }, \
+ { FR14, -1 }, { FR14, -1 }, \
+ { FR15, -1 }, { FR15, -1 }, \
+ { FR16, -1 }, { FR16, -1 }, \
+ { FR17, -1 }, { FR17, -1 },
+#ifdef __hppa64__
+ { FR18, -1 }, { FR18, -1 }, \
+ { FR19, -1 }, { FR19, -1 }, \
+ { FR20, -1 }, { FR20, -1 }, \
+ { FR21, -1 }, { FR21, -1 }, \
+ { FR22, -1 }, { FR22, -1 }, \
+ { FR23, -1 }, { FR23, -1 }, \
+ { FR24, -1 }, { FR24, -1 }, \
+ { FR25, -1 }, { FR25, -1 }, \
+ { FR26, -1 }, { FR26, -1 }, \
+ { FR27, -1 }, { FR27, -1 }, \
+ { FR28, -1 }, { FR28, -1 }, \
+ { FR29, -1 }, { FR29, -1 }, \
+ { FR30, -1 }, { FR30, -1 }, \
+ { FR31, -1 }, { FR31, -1 },
+#endif
+
+#define PCLASS(p) \
+ (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \
+ (p->n_type == FLOAT ? SCREG : \
+ (p->n_type == DOUBLE || p->n_type == LDOUBLE ? SDREG : SAREG)))
+
+#define NUMCLASS 4 /* highest number of reg classes used */
+
+int COLORMAP(int c, int *r);
+TOWRD gtype(int);
+#define PERMTYPE(x) ((x) < 31? INT : ((x) < 44? LONGLONG : ((x) < 73? LDOUBLE : FLOAT)))
+#define GCLASS(x) ((x) < 31? CLASSA : ((x) < 44? CLASSB : ((x) < 73? CLASSD : CLASSC)))
+#define DECRA(x,y) (((x) >> (y*8)) & 255) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 8) /* A1 */
+#define ENCRA2(x) ((x) << 16) /* A2 */
+#define ENCRA(x,y) ((x) << (8+y*8)) /* encode regs in int */
+#define RETREG(x) (x == LONGLONG || x == ULONGLONG ? RETD0 : \
+ x == FLOAT? FR4L : \
+ x == DOUBLE || x == LDOUBLE ? FR4 : RET0)
+
+#define FPREG FP /* frame pointer */
+#define STKREG SP /* stack pointer */
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+
+#define SFUNCALL (MAXSPECIAL+1) /* struct assign after function call */
+#define SPCON (MAXSPECIAL+2) /* smaller constant */
+#define SPICON (MAXSPECIAL+3) /* even smaller constant */
+#define SPNAME (MAXSPECIAL+4) /* ext symbol reference load/store */
diff --git a/usr.bin/pcc/hppa/order.c b/usr.bin/pcc/hppa/order.c
new file mode 100644
index 00000000000..c1ba92c913d
--- /dev/null
+++ b/usr.bin/pcc/hppa/order.c
@@ -0,0 +1,203 @@
+/* $OpenBSD: order.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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 <string.h>
+
+int canaddr(NODE *);
+
+/* is it legal to make an OREG or NAME entry which has an
+ * offset of off, (from a register of r), if the
+ * resulting thing had type t */
+int
+notoff(TWORD t, int r, CONSZ off, char *cp)
+{
+ return(0); /* YES */
+}
+
+/*
+ * Turn a UMUL-referenced node into OREG.
+ * Be careful about register classes, this is a place where classes change.
+ */
+void
+offstar(NODE *p, int shape)
+{
+ NODE *r;
+
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (isreg(p))
+ return; /* Is already OREG */
+
+ r = p->n_right;
+ if (p->n_op == PLUS || p->n_op == MINUS) {
+ if (r->n_op == ICON) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
+ }
+ (void)geninsn(p, INAREG);
+}
+
+/*
+ * Do the actual conversion of offstar-found OREGs into real OREGs.
+ */
+void
+myormake(NODE *q)
+{
+ NODE *p, *r;
+
+ if (x2debug)
+ printf("myormake(%p)\n", q);
+
+ p = q->n_left;
+ if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
+ r->n_right->n_op == ICON && r->n_right->n_lval == 2 &&
+ p->n_left->n_op == REG && r->n_left->n_op == REG) {
+ q->n_op = OREG;
+ q->n_lval = 0;
+ q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0);
+ tfree(p);
+ }
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p)
+{
+
+ if (x2debug)
+ printf("shumul(%p)\n", p);
+
+ /* Turns currently anything into OREG on hppa */
+ return SOREG;
+}
+
+/*
+ * Rewrite increment/decrement operation.
+ */
+int
+setincr(NODE *p)
+{
+ if (x2debug)
+ printf("setincr(%p)\n", p);
+
+ return(0);
+}
+
+/*
+ * Rewrite operations on binary operators (like +, -, etc...).
+ * Called as a result of table lookup.
+ */
+int
+setbin(NODE *p)
+{
+ if (x2debug)
+ printf("setbin(%p)\n", p);
+
+ return 0;
+}
+
+/* setup for assignment operator */
+int
+setasg(NODE *p, int cookie)
+{
+ if (x2debug)
+ printf("setasg(%p,%s)\n", p, prcook(cookie));
+
+ if (p->n_left->n_op == FLD && !isreg(p->n_left->n_left)) {
+ NODE *l, *r;
+ int reg;
+
+ geninsn(p->n_left->n_left, INAREG);
+
+ reg = DECRA(p->n_left->n_left->n_reg, 0);
+ l = tcopy(p->n_left->n_left);
+ p->n_left->n_left->n_op = REG;
+ p->n_left->n_left->n_rval = reg;
+ p->n_left->n_left->n_lval = 0;
+ r = tcopy(p->n_left->n_left);
+
+ geninsn(p->n_left, INAREG);
+ l = mkbinode(ASSIGN, l, r, l->n_type);
+ geninsn(l, INAREG);
+ return (1);
+ }
+
+ return (0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ if (x2debug)
+ printf("setuni(%p,%s)\n", p, prcook(cookie));
+
+ return 0;
+}
+
+/*
+ * Special handling of some instruction register allocation.
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ comperr("nspecial entry %d", q - table);
+ return 0; /* XXX gcc */
+}
+
+/*
+ * Set evaluation order of a binary node if it differs from default.
+ */
+int
+setorder(NODE *p)
+{
+ return 0; /* nothing differs on hppa */
+}
+/*
+ * Set registers "live" at function calls (like arguments in registers).
+ * This is for liveness analysis of registers.
+ */
+int *
+livecall(NODE *p)
+{
+ static int r[1] = { -1 }; /* Terminate with -1 */
+
+ return &r[0];
+}
+
diff --git a/usr.bin/pcc/hppa/table.c b/usr.bin/pcc/hppa/table.c
new file mode 100644
index 00000000000..965d8e56219
--- /dev/null
+++ b/usr.bin/pcc/hppa/table.c
@@ -0,0 +1,1014 @@
+/* $OpenBSD: table.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */
+
+/*
+ * Copyright (c) 2007 Michael Shalayeff
+ * Copyright (c) 2003 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"
+
+#define TLL TLONGLONG|TULONGLONG
+#define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
+#define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
+#define ANYFIXED ANYSIGNED|ANYUSIGNED
+#define TUWORD TUNSIGNED|TULONG
+#define TSWORD TINT|TLONG
+#define TWORD TUWORD|TSWORD
+#define THWORD TUSHORT|TSHORT
+#define TBYTE TUCHAR|TCHAR
+
+#define SHINT SAREG /* char, short and int */
+#define ININT INAREG
+#define SHLL SBREG /* shape for long long */
+#define INLL INBREG
+#define SHFL SCREG /* shape for float */
+#define INFL INCREG
+#define SHDBL SDREG /* shape for double */
+#define INDBL INDREG
+
+struct optab table[] = {
+/* First entry must be an empty entry */
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
+
+/* PCONVs are usually not necessary */
+{ PCONV, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ "", },
+/*
+ * A bunch conversions of integral<->integral types
+ * There are lots of them, first in table conversions to itself
+ * and then conversions from each type to the others.
+ */
+
+/* itself to itself, including pointers */
+
+/* convert int,short,char <-> int,short,char. */
+{ SCONV, ININT,
+ SHINT, TBYTE,
+ SHINT, TBYTE,
+ 0, RLEFT,
+ "", },
+
+{ SCONV, ININT,
+ SHINT, THWORD,
+ SHINT, THWORD,
+ 0, RLEFT,
+ "", },
+
+{ SCONV, ININT,
+ SHINT, TWORD,
+ SHINT, TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to int. */
+{ SCONV, ININT,
+ SHINT, TPOINT|TWORD,
+ SANY, TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert (u)longlong to (u)longlong. */
+{ SCONV, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to pointers. */
+{ SCONV, ININT,
+ SHINT, TPOINT,
+ SANY, TPOINT,
+ 0, RLEFT,
+ "", },
+
+/* convert double <-> ldouble. nothing to do here (or support quads later) */
+{ SCONV, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ "", },
+
+/* convert float -> double */
+{ SCONV, INFL,
+ SHFL, TFLOAT,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, 0,
+ "\tfcnvff,sgl,dbl AL,AR\n", },
+
+/* convert double -> float */
+{ SCONV, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHFL, TFLOAT,
+ 0, 0,
+ "\tfcnvff,dbl,sgl\tAL,AR\n", },
+
+/* convert int,short,char to (u)long long */
+{ SCONV, INLL,
+ SHINT, ANYSIGNED,
+ SANY, TLL,
+ NBREG, RESC1,
+ "\tcopy\tAL,A1\n"
+ "\textrs\tAL,0,1,U1\n", },
+
+/* convert unsigned int,short,char to (u)long long */
+{ SCONV, INLL,
+ SHINT, TWORD,
+ SANY, TLL,
+ NBREG, RESC1,
+ "\tcopy\tAL,A1\n"
+ "\tcopy\t%r0,U1\n", },
+
+/* convert int,short,char (in memory) to float */
+{ SCONV, INFL,
+ SOREG, ANYSIGNED,
+ SHFL, TFLOAT,
+ NCREG, RESC1,
+ "\tfldws\tAL,A1\n"
+ "\tfcnvxf,sgl,sgl\tA1,A1\n", },
+
+/* convert int,short,char (in memory) to double */
+{ SCONV, INDBL,
+ SOREG, TSWORD,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "\tfldws\tAL,A1\n"
+ "\tfcnvxf,sgl,dbl\tA1,A1\n", },
+
+/* convert (u)long (in memory) to double */
+{ SCONV, INDBL,
+ SOREG, TLL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "\tfldds\tAL,A1\n"
+ "\tfcnvxf,dbl,dbl\tA1,A1\n", },
+
+/* convert int,short,char (in register) to float */
+{ SCONV, INFL,
+ SHINT, TSWORD,
+ SHFL, TFLOAT,
+ NCREG, RESC1,
+ "\tstw,ma\tAL,4(%sp)\n"
+ "\tfldws,ma\t-4(%sp),A1\n"
+ "\tfcnvxf,sgl,sgl\tA1,A1\n", },
+
+/* convert int,short,char (in register) to double */
+{ SCONV, INDBL,
+ SHINT, TSWORD,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "\tstw,ma\tAL,4(%sp)\n"
+ "\tfldws,mb\t-4(%sp),AR\n"
+ "\tfcnvxf,sgl,dbl\tA1,A1\n", },
+
+/* convert (u)long (in register) to double */
+{ SCONV, INDBL,
+ SHLL, TLL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "\tldo\t8(%sp),%sp\n"
+ "\tstw\tAL,-8(%sp)\n"
+ "\tstw\tUL,-4(%sp)\n"
+ "\tfldds,mb\t-8(%sp),A1\n"
+ "\tfcnvxf,dbl,dbl\tA1,A1\n", },
+
+/* convert char to (unsigned) short/int. */
+{ SCONV, ININT,
+ SAREG, TCHAR,
+ SAREG, THWORD|TWORD,
+ NASL|NAREG, RESC1,
+ "\textrs\tAL,31,8,A1\n", },
+
+/* convert unsigned char to (unsigned) short/int. */
+{ SCONV, ININT,
+ SAREG, TUCHAR,
+ SAREG, THWORD|TWORD,
+ NASL|NAREG, RESC1,
+ "\textru\tAL,31,8,A1\n", },
+
+/* convert char to (unsigned) long long. */
+{ SCONV, INLL,
+ SAREG, TCHAR,
+ SBREG, TLL,
+ NBSL|NBREG, RESC1,
+ "\textrs\tAL,31,8,A1\n\textrs\tA1,0,1,U1", },
+
+/* convert unsigned char to (unsigned) long long. */
+{ SCONV, INLL,
+ SAREG, TUCHAR,
+ SBREG, TLL,
+ NBSL|NBREG, RESC1,
+ "\textru\tAL,31,8,A1\n\tcopy\t%r0,U1", },
+
+/* convert short to (unsigned) int. */
+{ SCONV, ININT,
+ SAREG, TSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ "\textrs\tAL,31,16,A1\n", },
+
+/* convert unsigned short to (unsigned) int. */
+{ SCONV, ININT,
+ SAREG, TUSHORT,
+ SAREG, THWORD,
+ NASL|NAREG, RESC1,
+ "\textru\tAL,31,16,A1\n", },
+
+/* convert short to (unsigned) long long. */
+{ SCONV, INLL,
+ SAREG, TSHORT,
+ SBREG, TLL,
+ NBSL|NBREG, RESC1,
+ "\textrs\tAL,31,16,A1\n\textrs\tA1,0,1,U1", },
+
+/* convert unsigned short to (unsigned) long long. */
+{ SCONV, INLL,
+ SAREG, TUSHORT,
+ SBREG, TLL,
+ NBSL|NBREG, RESC1,
+ "\textru\tAL,31,16,A1\n\tcopy\t%r0,U1", },
+
+/* convert int,short,char (in memory) to int,short,char */
+{ SCONV, ININT,
+ SOREG, TBYTE,
+ SHINT, TBYTE|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tldb\tAL,A1\n", },
+
+{ SCONV, ININT,
+ SOREG, THWORD,
+ SHINT, THWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tldh\tAL,A1\n", },
+
+{ SCONV, ININT,
+ SOREG, TWORD,
+ SHINT, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tldw\tAL,A1\n", },
+
+/* convert (u)long long (in register) to int,short,char */
+{ SCONV, ININT,
+ SHLL, TLL,
+ SHINT, ANYFIXED,
+ NAREG|NASL, RESC1,
+ "\tcopy\tAL,A1\n", },
+
+/* convert (u)long (in memory) to int,short,char */
+{ SCONV, ININT,
+ SOREG, TLL,
+ SHINT, ANYFIXED,
+ NAREG|NASL, RESC1,
+ "\tldw\tAL,A1\n", },
+
+/* convert float (in register) to (u)int */
+{ SCONV, ININT,
+ SHFL, TFLOAT,
+ SHINT, TWORD,
+ NAREG, RESC1,
+ "\tfcnvfxt,sgl,sgl\tAL,AL\n"
+ "\tfstws,ma\tAL,4(%sp)\n"
+ "\tldw,mb\t-1(%sp),A1\n", },
+
+/* convert double (in register) to (u)int */
+{ SCONV, ININT,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHINT, TWORD,
+ NCREG|NCSL|NAREG, RESC2,
+ "\tfcnvfxt,dbl,sgl\tAL,A1\n"
+ "\tfstws,ma\tA1,4(%sp)\n"
+ "\tldw,mb\t-1(%sp),A2\n", },
+
+/* convert float (in register) to (u)long */
+{ SCONV, INLL,
+ SHFL, TFLOAT,
+ SHLL, TLL,
+ NDREG|NDSL|NBREG, RESC2,
+ "\tfcnvfxt,sgl,dbl\tAL,A1\n"
+ "\tfstds,ma\tA1,8(%sp)\n"
+ "\tldw\t-8(%sp),A2\n"
+ "\tldw\t-4(%sp),U2\n"
+ "\tldo\t-8(%sp),%sp)\n", },
+
+/* convert double (in register) to (u)long */
+{ SCONV, INLL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHLL, TLL,
+ NBREG, RESC1,
+ "\tfcnvfxt,dbl,dbl\tAL,AL\n"
+ "\tfstds,ma\tAL,8(%sp)\n"
+ "\tldw\t-8(%sp),A1\n"
+ "\tldw\t-4(%sp),U1\n"
+ "\tldo\t-8(%sp),%sp)\n", },
+
+/*
+ * Subroutine calls.
+ */
+
+{ CALL, ININT,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ UCALL, ININT,
+ SOREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ "ZP\tble\tAL\n"
+ "\tcopy\t%r1,rp\nZC", },
+
+{ CALL, INLL,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ UCALL, INLL,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ CALL, INFL,
+ SAREG, TANY,
+ SHFL, TFLOAT,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ UCALL, INFL,
+ SAREG, TANY,
+ SHFL, TFLOAT,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ CALL, INDBL,
+ SAREG, TANY,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+{ UCALL, INFL,
+ SAREG, TANY,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, 0,
+ "ZP\tblr\t%r0, %rp\n"
+ "\tbv,n\t%r0(AL)\n"
+ "\tnop\nZC", },
+
+/*
+ * The next rules handle all binop-style operators.
+ */
+/* TODO fix char/short overflows */
+
+{ PLUS, INLL,
+ SHLL, TLL,
+ SPICON, TANY,
+ NBREG|NBSL, RESC1,
+ "\taddi\tAL,AR,A1\n"
+ "\taddc\tUL,%r0,U1\n", },
+
+{ PLUS, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG|NBSL|NBSR, RESC1,
+ "\tadd\tAL,AR,A1\n"
+ "\taddc\tUL,UR,U1\n", },
+
+{ PLUS, INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG|NCSL|NCSR, RESC1,
+ "\tfadd,sgl\tAL,AR,A1\n", },
+
+{ PLUS, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL|NDSR, RESC1,
+ "\tfadd,dbl\tAL,AR,A1\n", },
+
+{ PLUS, ININT,
+ SHINT, ANYFIXED|TPOINT,
+ SONE, TANY,
+ NAREG|NASL, RESC1,
+ "\tldo\t1(AL),A1\n", },
+
+{ PLUS, ININT,
+ SHINT, ANYFIXED|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ "\tldo\tCR(AL),A1\n", },
+
+{ MINUS, INLL,
+ SHLL, TLL,
+ SPICON, TANY,
+ NBREG|NBSL|NBSR, RESC1,
+ "\tsubi\tAL,AR,A1\n"
+ "\tsubb\tUL,%r0,U1\n", },
+
+{ PLUS, ININT,
+ SHINT, TANY|TPOINT,
+ SPNAME, TANY,
+ NAREG|NASL, RESC1,
+ "\tldo\tAR(AL),A1\n", },
+
+{ MINUS, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG|NBSL|NBSR, RESC1,
+ "\tsub\tAL,AR,A1\n"
+ "\tsubb\tUL,UR,U1\n", },
+
+{ MINUS, INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG|NCSL|NCSR, RESC1,
+ "\tfsub,sgl\tAL,AR,A1\n", },
+
+{ MINUS, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL|NDSR, RESC1,
+ "\tfsub,dbl\tAL,AR,A1\n", },
+
+{ MINUS, ININT,
+ SHINT, ANYFIXED|TPOINT,
+ SONE, TANY,
+ NAREG|NASL, RESC1,
+ "\tldo\t-1(AL),A1\n", },
+
+{ MINUS, ININT,
+ SHINT, ANYFIXED|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ "\tldo\t-CR(AL),A1\n", },
+
+/* Simple reg->reg ops */
+{ OPSIMP, ININT,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tO\tAL,AR,A1\n", },
+
+{ OPSIMP, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG|NBSL|NBSR, RESC1,
+ "\tO\tAL,AR,A1\n"
+ "\tO\tUL,UR,U1\n", },
+
+/*
+ * The next rules handle all shift operators.
+ */
+/* (u)longlong left shift is emulated */
+{ LS, INLL,
+ SHLL|SCON, TLL,
+ SHINT|SCON, TINT,
+ NSPECIAL|NBREG|NBSL|NBSR, RESC1,
+ "ZO", },
+
+{ LS, ININT,
+ SHINT, ANYFIXED,
+ SCON, ANYFIXED,
+ NAREG|NASL, RESC1,
+ "\tzdep\tAL,31-AR,32-AR,A1\n", },
+
+{ LS, ININT,
+ SHINT, ANYFIXED,
+ SHINT, ANYFIXED,
+ NAREG|NASR, RESC1,
+ "\tsubi\t31,AR,A1\n"
+ "\tmtsar\tA1\n"
+ "\tzvdep\tAL,32,A1\n", },
+
+{ RS, INLL,
+ SHLL, TLONGLONG,
+ SCON, ANYFIXED,
+ NBREG|NBSL, RESC1,
+ "\tshd\tUL,AL,31-AR,A1\n"
+ "\textrs\tUL,31-AR,32,U1\n", },
+
+{ RS, INLL,
+ SHLL, TULONGLONG,
+ SCON, ANYFIXED,
+ NBREG|NBSL, RESC1,
+ "\tshd\tUL,AL,AR,A1\n"
+ "\textru\tUL,31-AR,32,U1\n", },
+
+/* (u)longlong right shift is emulated */
+{ RS, INLL,
+ SHLL|SCON, TLL,
+ SHINT|SCON, TINT,
+ NSPECIAL|NBREG|NBSL|NBSR, RESC1,
+ "ZO", },
+
+{ RS, ININT,
+ SHINT, ANYSIGNED,
+ SCON, ANYFIXED,
+ NAREG|NASL, RESC1,
+ "\textrs\tAL,31-AR,32,A1\n", },
+
+{ RS, ININT,
+ SHINT, ANYUSIGNED,
+ SCON, ANYFIXED,
+ NAREG|NASL, RESC1,
+ "\textru\tAL,31-AR,32,A1\n", },
+
+/* TODO the following should be split into mtsar and actual shift parts */
+{ RS, ININT,
+ SHINT, ANYSIGNED,
+ SHINT, ANYFIXED,
+ NAREG|NASR, RESC1,
+ "\tsubi\t31,AR,A1\n"
+ "\tmtsar\tA1\n"
+ "\tvextrs\tAL,32,A1\n", },
+
+{ RS, ININT,
+ SHINT, ANYUSIGNED,
+ SHINT, ANYFIXED,
+ NAREG|NASR, RESC1,
+ "\tsubi\t31,AR,A1\n"
+ "\tmtsar\tA1\n"
+ "\tvextru\tAL,32,A1\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SPCON, TANY,
+ 0, RDEST,
+ "\tldi\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TBYTE,
+ SHINT, TBYTE,
+ 0, RDEST,
+ "\tstb\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, THWORD,
+ SHINT, THWORD,
+ 0, RDEST,
+ "\tsth\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TWORD|TPOINT,
+ SHINT, TWORD|TPOINT,
+ 0, RDEST,
+ "\tstw\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SOREG, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ "\tstw\tAR,AL\n"
+ "\tstw\tUR,UL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SHINT, TBYTE,
+ SOREG, TBYTE,
+ 0, RDEST,
+ "\tldb\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SHINT, THWORD,
+ SOREG, THWORD,
+ 0, RDEST,
+ "\tldh\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SHINT, TWORD|TPOINT,
+ SOREG, TWORD|TPOINT,
+ 0, RDEST,
+ "\tldw\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SOREG, TLL,
+ 0, RDEST,
+ "\tldw\tAR,AL\n"
+ "\tldw\tUR,UL\n", },
+
+{ ASSIGN, FOREFF|ININT,
+ SHINT, TWORD|TPOINT,
+ SHINT, TWORD|TPOINT,
+ 0, RDEST,
+ "\tcopy\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|ININT,
+ SHINT, ANYFIXED,
+ SHINT, ANYFIXED,
+ 0, RDEST,
+ "\tcopy\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|ININT,
+ SFLD, TANY,
+ SPICON, TANY,
+ 0, RDEST,
+ "\tdepi\tAR,31-H,S,AL\n", },
+
+{ ASSIGN, FOREFF|ININT,
+ SFLD, TANY,
+ SHINT, TANY,
+ 0, RDEST,
+ "\tdep\tAR,31-H,S,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ "\tcopy\tAR,AL\n"
+ "\tcopy\tUR,UL\n", },
+
+{ ASSIGN, FOREFF|INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ 0, RDEST,
+ "\tfcpy,sgl\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "\tfcpy,dbl\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INFL,
+ SHFL, TFLOAT,
+ SOREG, TFLOAT,
+ 0, RDEST,
+ "\tfldws\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SOREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "\tfldds\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INFL,
+ SOREG, TFLOAT,
+ SHFL, TFLOAT,
+ 0, RDEST,
+ "\tfstws\tAR,AL\n", },
+
+{ ASSIGN, FOREFF|INDBL,
+ SOREG, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "\tfstds\tAR,AL\n", },
+
+/*
+ * DIV/MOD/MUL
+ */
+
+{ DIV, ININT,
+ SHINT, TWORD,
+ SHINT, TWORD,
+ NAREG, RESC1,
+ "ZO", },
+
+{ DIV, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG, RESC1,
+ "ZO", },
+
+{ DIV, INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG|NCSL|NCSR, RESC1,
+ "\tfdiv,sgl\tAL,AR,A1\n", },
+
+{ DIV, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL|NDSR, RESC1,
+ "\tfdiv,dbl\tAL,AR,A1\n", },
+
+{ MOD, ININT,
+ SHINT, TWORD,
+ SHINT, TWORD,
+ NAREG, RESC1,
+ "ZO", },
+
+{ MOD, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG, RESC1,
+ "ZO", },
+
+{ MUL, ININT,
+ SHINT, TWORD,
+ SHINT, TWORD,
+ NAREG, RESC1,
+ "ZO", },
+
+{ MUL, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG, RESC1,
+ "ZO", },
+
+{ MUL, INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG|NCSL|NCSR, RESC1,
+ "\tfmul,sgl\tAL,AR,A1\n", },
+
+{ MUL, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL|NDSR, RESC1,
+ "\tfmul,dbl\tAL,AR,A1\n", },
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INLL,
+ SANY, TANY,
+ SOREG, TLL,
+ NBREG, RESC1,
+ "\tldw\tAL,A1\n"
+ "\tldw\tUL,U1\n", },
+
+{ UMUL, ININT,
+ SANY, TPOINT|TWORD,
+ SOREG, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ "\tldw\tAL,A1\n", },
+
+{ UMUL, ININT,
+ SANY, TANY,
+ SOREG, THWORD,
+ NAREG|NASL, RESC1,
+ "\tldh\tAL,A1\n", },
+
+{ UMUL, ININT,
+ SANY, TANY,
+ SOREG, TBYTE,
+ NAREG|NASL, RESC1,
+ "\tldb\tAL,A1\n", },
+
+{ UMUL, INDBL,
+ SANY, TANY,
+ SOREG, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ "\tfldds\tAL,A1\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NCREG|NCSL, RESC1,
+ "\tfldws\tAL,A1\n", },
+
+/*
+ * Logical/branching operators
+ */
+{ OPLOG, FORCC,
+ SHLL, TLL,
+ SHLL, TLL,
+ 0, 0,
+ "ZD", },
+
+{ OPLOG, FORCC,
+ SHINT, TWORD|TPOINT,
+ SPICON, TWORD|TPOINT,
+ 0, 0,
+ "\tcomib,O\tAR,AL,LC\n", },
+
+{ OPLOG, FORCC,
+ SHINT, TWORD|TPOINT,
+ SHINT, TWORD|TPOINT,
+ 0, 0,
+ "\tcomb,O\tAR,AL,LC\n", },
+
+{ OPLOG, FORCC,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ 0, RESCC,
+ "\tfcmp,sgl,!O\tAR,AL\n"
+ "\tftest\n"
+ "\tb\tLC\n"
+ "\tnop", },
+
+{ OPLOG, FORCC,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ 0, RESCC,
+ "\tfcmp,dbl,!O\tAR,AL\n"
+ "\tftest\n"
+ "\tb\tLC\n"
+ "\tnop", },
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ "\tb\tLL\n\tnop\n", },
+
+#ifdef GCC_COMPAT
+{ GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ "\tbv\t%r0(AL)\n\tnop\n", },
+#endif
+
+
+/*
+ * Convert LTYPE to reg.
+ */
+
+{ OPLTYPE, INAREG,
+ SAREG, TANY,
+ SNAME, TANY,
+ 0, RDEST,
+ "\taddil\tUR,gp\n", },
+
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SOREG, TLL,
+ NBREG|NBSL, RESC1,
+ "\tldw\tAL,A1\n"
+ "\tldw\tUL,U1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tldw\tAL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "\tcopy\tAL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SPCON, ANYFIXED,
+ NAREG, RESC1,
+ "\tldi\tAR,A1\n", },
+
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SPCON, TLL,
+ NAREG, RESC1,
+ "\tldi\tAR,A1\n"
+ "\tcopy\t%r0,U1\n", },
+
+{ OPLTYPE, ININT,
+ SANY, TANY,
+ SCON, TWORD|TPOINT,
+ NAREG, RESC1,
+ "\tldil\tUR,A1\n"
+ "\tldo\tAR(A1),A1\n", },
+
+{ OPLTYPE, INCREG,
+ SANY, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG, RESC1,
+ "\tfldws\tAL,A1\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "\tfldds\tAL,A1\n", },
+
+/*
+ * Negate a word.
+ */
+{ UMINUS, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ NBREG|NBSL, RESC1,
+ "\tsub\t%r0,AL,A1\n"
+ "\tsubb\t%r0,UL,A1\n", },
+
+{ UMINUS, ININT,
+ SHINT, TWORD,
+ SHINT, TWORD,
+ NAREG|NASL, RESC1,
+ "\tsub\t%r0,AL,A1\n", },
+
+{ UMINUS, INFL,
+ SHFL, TFLOAT,
+ SHFL, TFLOAT,
+ NCREG|NCSL, RESC1,
+ "\tfsub,sgl\t%fr0,AL,A1\n", },
+
+{ UMINUS, INDBL,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ SHDBL, TDOUBLE|TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ "\tfsub,dbl\t%fr0,AL,A1\n", },
+
+{ COMPL, INLL,
+ SHLL, TLL,
+ SANY, TANY,
+ NBREG|NBSL, RESC1,
+ "\tuaddcm\t%r0,AL,A1\n"
+ "\tuaddcm\t%r0,UL,U1\n", },
+
+{ COMPL, ININT,
+ SHINT, ANYFIXED,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ "\tuaddcm\t%r0,AL,A1\n", },
+
+/*
+ * Arguments to functions.
+ */
+/* TODO */
+
+
+
+{ STARG, FOREFF,
+ SAREG|SOREG|SNAME|SCON, TANY,
+ SANY, TSTRUCT,
+ NSPECIAL|NAREG, 0,
+ "ZF", },
+
+/*
+ * struct field ops
+ */
+{ FLD, ININT,
+ SHINT, TANY,
+ SFLD, ANYSIGNED,
+ NAREG|NASL, RESC1,
+ "\textrs\tAL,31-H,S,A1\n", },
+
+{ FLD, ININT,
+ SHINT, TANY,
+ SFLD, ANYUSIGNED,
+ NAREG|NASL, RESC1,
+ "\textru\tAL,31-H,S,A1\n", },
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+{ UMUL, DF( UMUL ), },
+
+{ ASSIGN, DF(ASSIGN), },
+
+{ STASG, DF(STASG), },
+
+{ FLD, DF(FLD), },
+
+{ OPLEAF, DF(NAME), },
+
+/* { INIT, DF(INIT), }, */
+
+{ OPUNARY, DF(UMINUS), },
+
+{ OPANY, DF(BITYPE), },
+
+{ FREE, FREE,
+ FREE, FREE,
+ FREE, FREE,
+ FREE, FREE,
+ "HELP; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);