summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2007-09-15 18:12:38 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2007-09-15 18:12:38 +0000
commit288752b760425fddc6fe00d317697ef966764b4c (patch)
tree6bee0a7eedda0f3e0b663d60edb6ee68e7cbe197
parentedb2678b922125cc3a94923d29e556e735c9b7e7 (diff)
Import ragge's version of PCC into our tree, so we can hack on it more
easy. ok deraadt@ miod@
-rw-r--r--usr.bin/pcc/Makefile.in32
-rw-r--r--usr.bin/pcc/arch/m16c/TODO1
-rw-r--r--usr.bin/pcc/arch/m16c/code.c376
-rw-r--r--usr.bin/pcc/arch/m16c/local.c487
-rw-r--r--usr.bin/pcc/arch/m16c/local2.c639
-rw-r--r--usr.bin/pcc/arch/m16c/macdefs.h205
-rw-r--r--usr.bin/pcc/arch/m16c/order.c600
-rw-r--r--usr.bin/pcc/arch/m16c/table.c595
-rw-r--r--usr.bin/pcc/arch/mips/TODO7
-rw-r--r--usr.bin/pcc/arch/mips/code.c239
-rw-r--r--usr.bin/pcc/arch/mips/local.c533
-rw-r--r--usr.bin/pcc/arch/mips/local2.c774
-rw-r--r--usr.bin/pcc/arch/mips/macdefs.h227
-rw-r--r--usr.bin/pcc/arch/mips/order.c350
-rw-r--r--usr.bin/pcc/arch/mips/table.c776
-rw-r--r--usr.bin/pcc/arch/nova/README120
-rw-r--r--usr.bin/pcc/arch/nova/code.c212
-rw-r--r--usr.bin/pcc/arch/nova/local.c618
-rw-r--r--usr.bin/pcc/arch/nova/local2.c563
-rw-r--r--usr.bin/pcc/arch/nova/macdefs.h195
-rw-r--r--usr.bin/pcc/arch/nova/order.c164
-rw-r--r--usr.bin/pcc/arch/nova/table.c1514
-rw-r--r--usr.bin/pcc/arch/pdp10/code.c167
-rw-r--r--usr.bin/pcc/arch/pdp10/local.c782
-rw-r--r--usr.bin/pcc/arch/pdp10/local2.c1237
-rw-r--r--usr.bin/pcc/arch/pdp10/macdefs.h148
-rw-r--r--usr.bin/pcc/arch/pdp10/order.c187
-rw-r--r--usr.bin/pcc/arch/pdp10/table.c1153
-rw-r--r--usr.bin/pcc/arch/vax/code.c452
-rw-r--r--usr.bin/pcc/arch/vax/local.c528
-rw-r--r--usr.bin/pcc/arch/vax/local2.c923
-rw-r--r--usr.bin/pcc/arch/vax/macdefs.h155
-rw-r--r--usr.bin/pcc/arch/vax/order.c533
-rw-r--r--usr.bin/pcc/arch/vax/table.c652
-rw-r--r--usr.bin/pcc/arch/x86/code.c213
-rw-r--r--usr.bin/pcc/arch/x86/local.c743
-rw-r--r--usr.bin/pcc/arch/x86/local2.c1051
-rw-r--r--usr.bin/pcc/arch/x86/macdefs.h301
-rw-r--r--usr.bin/pcc/arch/x86/order.c287
-rw-r--r--usr.bin/pcc/arch/x86/table.c1453
-rw-r--r--usr.bin/pcc/cc/Makefile.in38
-rw-r--r--usr.bin/pcc/cc/cc/Makefile.in44
-rw-r--r--usr.bin/pcc/cc/cc/cc.1179
-rw-r--r--usr.bin/pcc/cc/cc/cc.c701
-rw-r--r--usr.bin/pcc/cc/ccom/Makefile.in107
-rw-r--r--usr.bin/pcc/cc/ccom/ccom.1148
-rw-r--r--usr.bin/pcc/cc/ccom/cgram.y1399
-rw-r--r--usr.bin/pcc/cc/ccom/gcc_compat.c126
-rw-r--r--usr.bin/pcc/cc/ccom/init.c951
-rw-r--r--usr.bin/pcc/cc/ccom/inline.c209
-rw-r--r--usr.bin/pcc/cc/ccom/main.c313
-rw-r--r--usr.bin/pcc/cc/ccom/optim.c355
-rw-r--r--usr.bin/pcc/cc/ccom/pass1.h394
-rw-r--r--usr.bin/pcc/cc/ccom/pftn.c2549
-rw-r--r--usr.bin/pcc/cc/ccom/scan.l465
-rw-r--r--usr.bin/pcc/cc/ccom/stabs.c374
-rw-r--r--usr.bin/pcc/cc/ccom/symtabs.c356
-rw-r--r--usr.bin/pcc/cc/ccom/trees.c2447
-rw-r--r--usr.bin/pcc/cc/cpp/Makefile.in79
-rw-r--r--usr.bin/pcc/cc/cpp/cpp.c1447
-rw-r--r--usr.bin/pcc/cc/cpp/cpp.h120
-rw-r--r--usr.bin/pcc/cc/cpp/cpy.y166
-rw-r--r--usr.bin/pcc/cc/cpp/scanner.l808
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res17
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res226
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res316
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res45
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res54
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res66
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res75
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res88
-rw-r--r--usr.bin/pcc/cc/cpp/tests/res95
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test16
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test225
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test315
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test44
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test53
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test65
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test74
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test87
-rw-r--r--usr.bin/pcc/cc/cpp/tests/test94
-rw-r--r--usr.bin/pcc/cc/cpp/token.c495
-rw-r--r--usr.bin/pcc/config.guess1463
-rw-r--r--usr.bin/pcc/config.h.in155
-rw-r--r--usr.bin/pcc/config.sub1555
-rw-r--r--usr.bin/pcc/configure5655
-rw-r--r--usr.bin/pcc/configure.ac102
-rw-r--r--usr.bin/pcc/f77/Makefile.in36
-rw-r--r--usr.bin/pcc/f77/f77/Makefile.in42
-rw-r--r--usr.bin/pcc/f77/fcom/Makefile.in95
-rw-r--r--usr.bin/pcc/install-sh294
-rw-r--r--usr.bin/pcc/mip/common.c631
-rw-r--r--usr.bin/pcc/mip/manifest.h316
-rw-r--r--usr.bin/pcc/mip/match.c995
-rw-r--r--usr.bin/pcc/mip/mkext.c318
-rw-r--r--usr.bin/pcc/mip/node.h194
-rw-r--r--usr.bin/pcc/mip/optim2.c882
-rw-r--r--usr.bin/pcc/mip/pass2.h418
-rw-r--r--usr.bin/pcc/mip/protos.h83
-rw-r--r--usr.bin/pcc/mip/reader.c1098
-rw-r--r--usr.bin/pcc/mip/regs.c2244
-rw-r--r--usr.bin/pcc/os/dragonfly/ccconfig.h47
-rw-r--r--usr.bin/pcc/os/linux/ccconfig.h49
-rw-r--r--usr.bin/pcc/os/netbsd/ccconfig.h47
-rw-r--r--usr.bin/pcc/os/netbsd/f77config.h54
-rw-r--r--usr.bin/pcc/os/none/ccconfig.h50
-rw-r--r--usr.bin/pcc/os/openbsd/ccconfig.h47
-rw-r--r--usr.bin/pcc/os/openbsd/f77config.h46
108 files changed, 51533 insertions, 0 deletions
diff --git a/usr.bin/pcc/Makefile.in b/usr.bin/pcc/Makefile.in
new file mode 100644
index 00000000000..a5780ed6a92
--- /dev/null
+++ b/usr.bin/pcc/Makefile.in
@@ -0,0 +1,32 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:23 otto Exp $
+#
+# Makefile.in for top-level of pcc.
+#
+
+@SET_MAKE@
+CC=@CC@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+CPPFLAGS=@CPPFLAGS@
+YACC=@YACC@
+LEX=@LEX@
+
+SUBDIR=cc
+
+all: ${SUBDIR}
+
+install:
+ cd cc && ${MAKE} install
+
+clean:
+ cd cc && ${MAKE} clean
+
+distclean:
+ cd cc && ${MAKE} distclean
+ /bin/rm -rf Makefile config.log stamp-h1 config.status \
+ configure.lineno config.h autom4te.cache
+
+${SUBDIR}: nonexistant
+ cd $@ && $(MAKE) all $(MFLAGS)
+
+nonexistant:
diff --git a/usr.bin/pcc/arch/m16c/TODO b/usr.bin/pcc/arch/m16c/TODO
new file mode 100644
index 00000000000..5ef0ba4b478
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/TODO
@@ -0,0 +1 @@
+* Mul/Div does not work. \ No newline at end of file
diff --git a/usr.bin/pcc/arch/m16c/code.c b/usr.bin/pcc/arch/m16c/code.c
new file mode 100644
index 00000000000..536a5eb1435
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/code.c
@@ -0,0 +1,376 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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
+ */
+void
+defalign(int n)
+{
+#if 0
+ char *s;
+
+ n /= SZCHAR;
+ if (lastloc == PROG || n == 1)
+ return;
+ s = (isinlining ? permalloc(40) : tmpalloc(40));
+ sprintf(s, ".align %d", n);
+ send_passt(IP_ASM, s);
+#endif
+}
+
+/*
+ * define the current location as the name p->sname
+ */
+void
+defnam(struct symtab *p)
+{
+ char *c = p->sname;
+
+#ifdef GCC_COMPAT
+ c = gcc_findname(p);
+#endif
+ if (p->sclass == EXTDEF)
+ printf(" PUBLIC %s\n", c);
+ printf("%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 eax */
+ p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_rval = R0;
+ q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ q->n_rval = FB;
+ 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";
+ send_passt(IP_NODE, p);
+}
+
+/*
+ * helper for bfcode() to put register arguments on stack.
+ */
+static void
+argmove(struct symtab *s, int regno)
+{
+ NODE *p, *r;
+
+ s->sclass = AUTO;
+ s->soffset = NOOFFSET;
+ oalloc(s, &autooff);
+ spname = s;
+ p = buildtree(NAME, NIL, NIL);
+ r = bcon(0);
+ r->n_op = REG;
+ r->n_rval = regno;
+ r->n_type = p->n_type;
+ r->n_sue = p->n_sue;
+ r->n_df = p->n_df;
+ ecode(buildtree(ASSIGN, p, r));
+}
+
+/*
+ * code for the beginning of a function; a is an array of
+ * indices in symtab for the arguments; n is the number
+ * On m16k, space is allocated on stack for register arguments,
+ * arguments are moved to the stack and symtab is updated accordingly.
+ */
+void
+bfcode(struct symtab **a, int n)
+{
+ struct symtab *s;
+ int i, r0l, r0h, a0, r2, sz, hasch, stk;
+ int argoff = ARGINIT;
+
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ /* Function returns struct, adjust arg offset */
+ for (i = 0; i < n; i++)
+ a[i]->soffset += SZPOINT(INT);
+ }
+ /* first check if there are 1-byte parameters */
+ for (hasch = i = 0; i < n && i < 6; i++)
+ if (DEUNSIGN(a[i]->stype) == CHAR)
+ hasch = 1;
+
+ stk = r0l = r0h = a0 = r2 = 0;
+ for (i = 0; i < n; i++) {
+ s = a[i];
+ sz = tsize(s->stype, s->sdf, s->ssue);
+ if (ISPTR(s->stype) && ISFTN(DECREF(s->stype)))
+ sz = SZLONG; /* function pointers are always 32 */
+ if (stk == 0)
+ switch (sz) {
+ case SZCHAR:
+ if (r0l) {
+ if (r0h)
+ break;
+ argmove(s, 1);
+ r0h = 1;
+ } else {
+ argmove(s, 0);
+ r0l = 1;
+ }
+ continue;
+
+ case SZINT:
+ if (s->stype > BTMASK) {
+ /* is a pointer */
+ if (a0) {
+ if (r0l || hasch) {
+ if (r2)
+ break;
+ argmove(s, R2);
+ r2 = 1;
+ } else {
+ argmove(s, R0);
+ r0l = r0h = 1;
+ }
+ } else {
+ argmove(s, A0);
+ a0 = 1;
+ }
+ } else if (r0l || hasch) {
+ if (r2) {
+ if (a0)
+ break;
+ argmove(s, A0);
+ a0 = 1;
+ } else {
+ argmove(s, R2);
+ r2 = 1;
+ }
+ } else {
+ argmove(s, R0);
+ r0l = r0h = 1;
+ }
+ continue;
+ case SZLONG:
+ if (r0l||r0h||r2)
+ break;
+ argmove(s, R0);
+ r0l = r0h = r2 = 1;
+ continue;
+
+ default:
+ break;
+ }
+ stk = 1;
+ s->soffset = argoff;
+ argoff += sz;
+ }
+}
+
+/*
+ * Add a symbol to an internal list printed out at the end.
+ */
+void addsym(struct symtab *);
+static struct symlst {
+ struct symlst *next;
+ struct symtab *sp;
+} *sympole;
+
+void
+addsym(struct symtab *q)
+{
+ struct symlst *w = sympole;
+
+ if (q == NULL)
+ return;
+
+ while (w) {
+ if (q == w->sp)
+ return; /* exists */
+ w = w->next;
+ }
+ w = permalloc(sizeof(struct symlst));
+ w->sp = q;
+ w->next = sympole;
+ sympole = w;
+}
+
+/*
+ * by now, the automatics and register variables are allocated
+ */
+void
+bccode()
+{
+}
+
+struct caps {
+ char *cap, *stat;
+} caps[] = {
+ { "__64bit_doubles", "Disabled" },
+ { "__calling_convention", "Normal" },
+ { "__constant_data", "near" },
+ { "__data_alignment", "2" },
+ { "__data_model", "near" },
+ { "__processor", "M16C" },
+ { "__rt_version", "1" },
+ { "__variable_data", "near" },
+ { NULL, NULL },
+};
+/*
+ * Called before parsing begins.
+ */
+void
+bjobcode()
+{
+ struct caps *c;
+
+ printf(" NAME gurka.c\n"); /* Don't have the name */
+ for (c = caps; c->cap; c++)
+ printf(" RTMODEL \"%s\", \"%s\"\n", c->cap, c->stat);
+ //printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n");
+}
+
+/* called just before final exit */
+/* flag is 1 if errors, 0 if none */
+void
+ejobcode(int flag )
+{
+ struct symlst *w = sympole;
+
+ for (w = sympole; w; w = w->next) {
+ if (w->sp->sclass != EXTERN)
+ continue;
+ printf(" EXTERN %s\n", w->sp->sname);
+ }
+
+ printf(" END\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(" .zero %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(struct swents **p, int n)
+{
+ uerror("switch() statements unsopported");
+#if 0
+ int i;
+ char *s;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ s = (isinlining ? permalloc(40) : tmpalloc(40));
+ sprintf(s, " cmpl $%lld,%%eax", p[i]->sval);
+ send_passt(IP_ASM, s);
+ s = (isinlining ? permalloc(40) : tmpalloc(40));
+ sprintf(s, " je " LABFMT, p[i]->slab);
+ send_passt(IP_ASM, s);
+ }
+ if (p[0]->slab > 0)
+ branch(p[0]->slab);
+#endif
+}
diff --git a/usr.bin/pcc/arch/m16c/local.c b/usr.bin/pcc/arch/m16c/local.c
new file mode 100644
index 00000000000..ddc6276d36a
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/local.c
@@ -0,0 +1,487 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:26 otto Exp $ */
+/*
+ * 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"
+
+/* this file contains code which is dependent on the target machine */
+
+NODE *
+clocal(NODE *p)
+{
+ /* this 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 */
+
+ struct symtab *q;
+ NODE *l, *r;
+ int o;
+ TWORD ml;
+
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ 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 STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ 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 PCONV:
+ ml = p->n_left->n_type;
+ l = p->n_left;
+ if ((ml == CHAR || ml == UCHAR) && l->n_op != ICON)
+ break;
+ 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 (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT) {
+ nfree(p);
+ return l;
+ }
+ if (l->n_op == ICON) {
+ CONSZ val = l->n_lval;
+ switch (p->n_type) {
+ case CHAR:
+ l->n_lval = (char)val;
+ break;
+ case UCHAR:
+ l->n_lval = val & 0377;
+ break;
+ case SHORT:
+ case INT:
+ l->n_lval = (short)val;
+ break;
+ case USHORT:
+ case UNSIGNED:
+ l->n_lval = val & 0177777;
+ break;
+ case ULONG:
+ case ULONGLONG:
+ l->n_lval = val & 0xffffffff;
+ break;
+ case LONG:
+ case LONGLONG:
+ l->n_lval = (int)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", p->n_type);
+ }
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ break;
+
+
+ }
+
+ return(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;
+}
+
+/*
+ * is an automatic variable of type t OK for a register variable
+ */
+int
+cisreg(TWORD t)
+{
+ if (t == INT || t == UNSIGNED || t == CHAR || t == UCHAR ||
+ ISPTR(t))
+ return(1);
+ return 0; /* XXX - fix reg assignment in pftn.c */
+}
+
+/*
+ * 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 NAME node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ if ((off % SZINT) == 0)
+ p = buildtree(MUL, p, bcon(off/SZINT));
+ else if ((off % SZSHORT) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZSHORT));
+ p = buildtree(PLUS, p, bcon(1));
+ p = buildtree(RS, p, bcon(1));
+ } else if ((off % SZCHAR) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZCHAR));
+ p = buildtree(PLUS, p, bcon(3));
+ p = buildtree(RS, p, bcon(2));
+ } else
+ cerror("roundsp");
+
+ /* 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! */
+
+ /* add the size to sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, 0);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(PLUSEQ, sp, p));
+}
+
+/*
+ * print out a constant node
+ * mat be associated with a label
+ */
+void
+ninval(NODE *p)
+{
+ struct symtab *q;
+ TWORD t;
+
+ p = p->n_left;
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ inval(p->n_lval & 0xffffffff);
+ inval(p->n_lval >> 32);
+ break;
+ case LONG:
+ case ULONG:
+ 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;
+ default:
+ fwalk(p, eprint, 0);
+ cerror("ninval");
+ }
+}
+
+/*
+ * print out an integer.
+ */
+void
+inval(CONSZ word)
+{
+ word &= 0xffffffff;
+ printf(" .long 0x%llx\n", word);
+}
+
+/* output code to initialize a floating point value */
+/* the proper alignment has been obtained */
+void
+finval(NODE *p)
+{
+ switch (p->n_type) {
+ case LDOUBLE:
+ printf("\t.tfloat\t0t%.20Le\n", p->n_dcon);
+ break;
+ case DOUBLE:
+ printf("\t.dfloat\t0d%.20e\n", (double)p->n_dcon);
+ break;
+ case FLOAT:
+ printf("\t.ffloat\t0f%.20e\n", (float)p->n_dcon);
+ break;
+ }
+}
+
+/* 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 SHORT:
+ MODTYPE(type,INT);
+ break;
+
+ case USHORT:
+ MODTYPE(type,UNSIGNED);
+ break;
+
+ case LONGLONG:
+ MODTYPE(type,LONG);
+ break;
+
+ case ULONGLONG:
+ MODTYPE(type,ULONG);
+ break;
+
+ case LDOUBLE:
+ MODTYPE(type,DOUBLE);
+ break;
+ }
+ return (type);
+}
+
+/* curid is a variable which is defined but
+ * is not initialized (and not a function );
+ * This routine returns the storage class for an uninitialized declaration
+ */
+int
+noinit()
+{
+ return(EXTERN);
+}
+
+/*
+ * Extern variable not necessary common.
+ */
+void
+extdec(struct symtab *q)
+{
+ extern void addsym(struct symtab *);
+ addsym(q);
+}
+
+/*
+ * Call to a function
+ */
+void
+calldec(NODE *p, NODE *r)
+{
+ struct symtab *q = p->n_sp;
+ extern void addsym(struct symtab *);
+ addsym(q);
+}
+
+/* make a common declaration for id, if reasonable */
+void
+commdec(struct symtab *q)
+{
+ int off;
+ char *c = q->sname;
+
+ off = tsize(q->stype, q->sdf, q->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+
+#ifdef GCC_COMPAT
+ c = gcc_findname(q);
+#endif
+ printf(" PUBLIC %s\n", c);
+ /* XXX - NOROOT??? */
+ printf(" RSEG DATA16_Z:NEARDATA:SORT:NOROOT(1)\n");
+ printf("%s:\n", c);
+ printf(" DS8 %d\n", off);
+ printf(" REQUIRE __data16_zero\n");
+}
+
+/* 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(" .lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+}
+
+/*
+ * special handling before tree is written out.
+ */
+void
+myp2tree(NODE *p)
+{
+ union dimfun *df;
+ union arglist *al;
+ NODE *q;
+ int i;
+
+ switch (p->n_op) {
+ case MOD:
+ case DIV:
+ if (p->n_type == LONG || p->n_type == ULONG) {
+ /* Swap arguments for hardops() later */
+ q = p->n_left;
+ p->n_left = p->n_right;
+ p->n_right = q;
+ }
+ break;
+
+ case CALL:
+ case STCALL:
+ /*
+ * inform pass2 about varargs.
+ * store first variadic argument number in n_stalign
+ * in the CM node.
+ */
+ if (p->n_right->n_op != CM)
+ break; /* nothing to care about */
+ df = p->n_left->n_df;
+ if (df && (al = df->dfun)) {
+ for (i = 0; i < 6; i++, al++) {
+ if (al->type == TELLIPSIS || al->type == TNULL)
+ break;
+ }
+ p->n_right->n_stalign = al->type == TELLIPSIS ? i : 0;
+ } else
+ p->n_right->n_stalign = 0;
+ break;
+ }
+
+}
diff --git a/usr.bin/pcc/arch/m16c/local2.c b/usr.bin/pcc/arch/m16c/local2.c
new file mode 100644
index 00000000000..09f7e6f1204
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/local2.c
@@ -0,0 +1,639 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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>
+
+void acon(NODE *p);
+int argsize(NODE *p);
+void genargs(NODE *p);
+
+static int ftlab1, ftlab2;
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static TWORD ftype;
+static int addto;
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ ftype = ipp->ipp_type;
+
+#if 0
+ if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR)
+ comperr("fix prologue register savings", ipp->ipp_regs);
+#endif
+
+ printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n");
+ if (ipp->ipp_vis)
+ printf(" PUBLIC %s\n", ipp->ipp_name);
+ printf("%s:\n", ipp->ipp_name);
+
+#if 0
+ if (xsaveip) {
+ /* Optimizer running, save space on stack */
+ addto = (p2maxautooff - AUTOINIT)/SZCHAR;
+ printf(" enter #%d\n", addto);
+ } else {
+#endif
+
+ /* non-optimized code, jump to epilogue for code generation */
+ ftlab1 = getlab();
+ ftlab2 = getlab();
+ printf(" jmp.w " LABFMT "\n", ftlab1);
+ deflab(ftlab2);
+}
+
+/*
+ * End of block.
+ */
+void
+eoftn(struct interpass_prolog *ipp)
+{
+#if 0
+ if (ipp->ipp_regs != MINRVAR)
+ comperr("fix eoftn register savings %x", ipp->ipp_regs);
+#endif
+
+ // if (xsaveip == 0)
+ addto = (p2maxautooff - AUTOINIT)/SZCHAR;
+
+ /* return from function code */
+ //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary?
+
+ /* If retval is a pointer and not a function pointer, put in A0 */
+ if (ISPTR(DECREF(ipp->ipp_type)) &&
+ !ISFTN(DECREF(DECREF(ipp->ipp_type))))
+ printf(" mov.w r0,a0\n");
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ comperr("fix struct return in eoftn");
+ } else
+ printf(" exitd\n");
+
+ /* Prolog code */
+ // if (xsaveip == 0) {
+ deflab(ftlab1);
+ printf(" enter #%d\n", addto);
+ printf(" jmp.w " LABFMT "\n", ftlab2);
+ //}
+}
+
+/*
+ * 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;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+ printf("%s.%c", str, f);
+}
+
+char *
+rnames[] = { /* keyed to register number tokens */
+ "r0", "r2", "r1", "r3", "a0", "a1", "fb", "sp", "r0h", "r0l",
+ "r1h", "r1l",
+};
+
+/*
+ * Return the size (in bytes) of some types.
+ */
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case INT:
+ case UNSIGNED:
+ case FLOAT:
+ return 2;
+
+ case DOUBLE:
+ case LONG:
+ case ULONG:
+ return 4;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type)/SZCHAR;
+ }
+}
+
+/*
+ * Emit code to compare two longlong numbers.
+ */
+static void
+twollcomp(NODE *p)
+{
+ int o = p->n_op;
+ int s = getlab();
+ int e = p->n_label;
+ int cb1, cb2;
+
+ if (o >= ULE)
+ o -= (ULE-LE);
+ switch (o) {
+ case NE:
+ cb1 = 0;
+ cb2 = NE;
+ break;
+ case EQ:
+ cb1 = NE;
+ cb2 = 0;
+ break;
+ case LE:
+ case LT:
+ cb1 = GT;
+ cb2 = LT;
+ break;
+ case GE:
+ case GT:
+ cb1 = LT;
+ cb2 = GT;
+ break;
+
+ default:
+ cb1 = cb2 = 0; /* XXX gcc */
+ }
+ if (p->n_op >= ULE)
+ cb1 += 4, cb2 += 4;
+ expand(p, 0, " cmp.w UR,UL\n");
+ if (cb1) cbgen(cb1, s);
+ if (cb2) cbgen(cb2, e);
+ expand(p, 0, " cmp.w AR,AL\n");
+ cbgen(p->n_op, e);
+ deflab(s);
+}
+
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *l;
+
+ switch (c) {
+ case 'A': /* print negative shift constant */
+ p = getlr(p, 'R');
+ if (p->n_op != ICON)
+ comperr("ZA bad use");
+ p->n_lval = -p->n_lval;
+ adrput(stdout, p);
+ p->n_lval = -p->n_lval;
+ break;
+
+ case 'B':
+ if (p->n_rval)
+ printf(" add.b #%d,%s\n",
+ p->n_rval, rnames[STKREG]);
+ break;
+
+ case 'C': /* Print label address */
+ p = p->n_left;
+ if (p->n_lval)
+ printf(LABFMT, (int)p->n_lval);
+ else
+ printf("%s", p->n_name);
+ break;
+
+ case 'D': /* copy function pointers */
+ l = p->n_left;
+ printf("\tmov.w #HWRD(%s),%s\n\tmov.w #LWRD(%s),%s\n",
+ p->n_right->n_name, rnames[l->n_rval+1],
+ p->n_right->n_name, rnames[l->n_rval]);
+ break;
+
+ case 'E': /* double-reg printout */
+ /* XXX - always r0r2 here */
+ printf("%s%s", rnames[R0], rnames[R2]);
+ break;
+
+ case 'F': /* long comparisions */
+ twollcomp(p);
+ break;
+
+ case 'G':
+ printf("R0R2");
+ break;
+
+ case 'H': /* push 32-bit address (for functions) */
+ printf("\tpush.w #HWRD(%s)\n\tpush.w #LWRD(%s)\n",
+ p->n_left->n_name, p->n_left->n_name);
+ break;
+
+ case 'I': /* push 32-bit address (for functions) */
+ l = p->n_left;
+ printf("\tpush.w %d[%s]\n\tpush.w %d[%s]\n",
+ (int)l->n_lval, rnames[l->n_rval],
+ (int)l->n_lval+2, rnames[l->n_rval]);
+ break;
+
+ default:
+ comperr("bad zzzcode %c", c);
+ }
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left) == SRDIR))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+}
+
+void
+adrcon(CONSZ val)
+{
+ 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, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput");
+ }
+}
+
+/*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 /= SZINT;
+ switch (p->n_op) {
+ case REG:
+ fputs(rnames[p->n_rval + 1], stdout);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, "#" CONFMT, p->n_lval >> 16);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+ /* output an address, with offsets, from p */
+
+ if (p->n_op == FLD)
+ p = p->n_left;
+
+ switch (p->n_op) {
+
+ case NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+ fprintf(io, "[%s]", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ fputc('#', io);
+ conput(io, p);
+ return;
+
+ case MOVE:
+ case REG:
+ /*if (DEUNSIGN(p->n_type) == CHAR) {
+ fprintf(io, "R%c%c", p->n_rval < 2 ? '0' : '1',
+ (p->n_rval & 1) ? 'H' : 'L');
+ } else*/
+ fprintf(io, "%s", rnames[p->n_rval]);
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+static char *
+ccbranches[] = {
+ "jeq", /* jumpe */
+ "jne", /* jumpn */
+ "jle", /* jumple */
+ "jlt", /* jumpl */
+ "jge", /* jumpge */
+ "jgt", /* jumpg */
+ "jleu", /* jumple (jlequ) */
+ "jltu", /* jumpl (jlssu) */
+ "jgeu", /* jumpge (jgequ) */
+ "jgtu", /* jumpg (jgtru) */
+};
+
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+ if (o < EQ || o > UGT)
+ comperr("bad conditional branch: %s", opst[o]);
+ printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
+}
+
+#if 0
+void
+mygenregs(NODE *p)
+{
+
+ if (p->n_op == MINUS && p->n_type == DOUBLE &&
+ (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) {
+ p->n_su |= DORIGHT;
+ }
+ /* Must walk down correct node first for logops to work */
+ if (p->n_op != CBRANCH)
+ return;
+ p = p->n_left;
+ if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG))
+ return;
+ p->n_su &= ~DORIGHT;
+
+}
+#endif
+
+struct hardops hardops[] = {
+ { PLUS, FLOAT, "?F_ADD_L04" },
+ { MUL, LONG, "?L_MUL_L03" },
+ { MUL, ULONG, "?L_MUL_L03" },
+ { DIV, LONG, "?SL_DIV_L03" },
+ { DIV, ULONG, "?UL_DIV_L03" },
+ { MOD, LONG, "?SL_MOD_L03" },
+ { MOD, ULONG, "?UL_MOD_L03" },
+ { RS, LONGLONG, "__ashrdi3" },
+ { RS, ULONGLONG, "__lshrdi3" },
+ { LS, LONGLONG, "__ashldi3" },
+ { LS, ULONGLONG, "__ashldi3" },
+ { 0 },
+};
+
+int
+special(NODE *p, int shape)
+{
+ switch (shape) {
+ case SFTN:
+ if (ISPTR(p->n_type) && ISFTN(DECREF(p->n_type))) {
+ if (p->n_op == NAME || p->n_op == OREG)
+ return SRDIR;
+ else
+ return SRREG;
+ }
+ break;
+ }
+ return SRNOPE;
+}
+
+void
+myreader(NODE *p)
+{
+ NODE *q, *r, *s, *right;
+
+ if (optype(p->n_op) == LTYPE)
+ return;
+ if (optype(p->n_op) != UTYPE)
+ myreader(p->n_right);
+ myreader(p->n_left);
+
+ switch (p->n_op) {
+ case PLUS:
+ case MINUS:
+ if (p->n_type != LONG && p->n_type != ULONG)
+ break;
+ if (p->n_right->n_op == NAME || p->n_right->n_op == OREG)
+ break;
+ /* Must convert right into OREG */
+ right = p->n_right;
+ q = mklnode(OREG, BITOOR(freetemp(szty(right->n_type))),
+ FPREG, right->n_type);
+ s = mkbinode(ASSIGN, q, right, right->n_type);
+ r = talloc();
+ *r = *q;
+ p->n_right = r;
+ pass2_compile(ipnode(s));
+ break;
+ }
+}
+
+
+void
+rmove(int s, int d, TWORD t)
+{
+ switch (t) {
+ case CHAR:
+ case UCHAR:
+ printf(" mov.b %s,%s\n", rnames[s], rnames[d]);
+ break;
+ default:
+ printf(" mov.w %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 = r[CLASSA];
+ num += r[CLASSC];
+ return num < 4;
+ case CLASSB:
+ num = r[CLASSB];
+ return num < 2;
+ case CLASSC:
+ num = 2*r[CLASSA];
+ num += r[CLASSC];
+ return num < 4;
+ }
+ return 0; /* XXX gcc */
+}
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ if (t == CHAR || t == UCHAR)
+ return CLASSC;
+
+ if(ISPTR(t))
+ return CLASSB;
+
+ return CLASSA;
+}
+
+static int sizen;
+
+/* XXX: Fix this. */
+static int
+argsiz(NODE *p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONGLONG || t > MAXTYPES)
+ return 4;
+ if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
+ return 8;
+ if (t == LDOUBLE)
+ return 12;
+ if (t == STRTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
+
+/*
+ * Calculate argument sizes.
+ * XXX: Fix this.
+ */
+void
+lastcall(NODE *p)
+{
+ sizen = 0;
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ sizen += argsiz(p->n_right);
+ sizen += argsiz(p);
+}
diff --git a/usr.bin/pcc/arch/m16c/macdefs.h b/usr.bin/pcc/arch/m16c/macdefs.h
new file mode 100644
index 00000000000..010a2464b55
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/macdefs.h
@@ -0,0 +1,205 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<8)>>8);
+
+#define ARGINIT 40 /* # bits above fp where arguments start */
+#define AUTOINIT 0 /* # bits below fp where automatics start */
+
+/*
+ * Convert (multi-)character constant to integer.
+ * Assume: If only one value; store at left side (char size), otherwise
+ * treat it as an integer.
+ */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZINT 16
+#define SZFLOAT 16
+#define SZDOUBLE 16
+#define SZLDOUBLE 16
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 32
+/* pointers are of different sizes on m16c */
+#define SZPOINT(t) (ISFTN(DECREF(t)) ? 32 : 16)
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALINT 16
+#define ALFLOAT 16
+#define ALDOUBLE 16
+#define ALLDOUBLE 16
+#define ALLONG 16
+#define ALLONGLONG 16
+#define ALSHORT 16
+#define ALPOINT 16
+#define ALSTRUCT 16
+#define ALSTACK 16
+
+/*
+ * 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 -32768
+#define MAX_INT 32767
+#define MAX_UNSIGNED 65535
+#define MIN_LONG -2147483648
+#define MAX_LONG 2147483647
+#define MAX_ULONG 4294967295UL
+#define MIN_LONGLONG -2147483648
+#define MAX_LONGLONG 2147483647
+#define MAX_ULONGLONG 4294967295UL
+
+/* Default char is unsigned */
+#undef CHAR_UNSIGNED
+
+/*
+ * Use large-enough types.
+ */
+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 BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+//#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+/* Definitions mostly used in pass2 */
+
+#define BYTEOFF(x) 1
+#define BITOOR(x) ((x)/SZCHAR) /* bit offset to oreg offset */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+#define genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == LONG || (t) == ULONG || \
+ (ISPTR(t) && ISFTN(DECREF(t)))) ? 2 : 1)
+
+/*
+ * m16c register classes:
+ * A - 16-bit data registers R0-R3
+ * B - 16-bit address registers A0-A1
+ * C - 8-bit data registers R0H, R0L, R1H, R1L
+ */
+
+#define R0 0
+#define R2 1
+#define R1 2
+#define R3 3
+
+#define A0 4
+#define A1 5
+#define FB 6
+#define SP 7
+
+#define R0H 8
+#define R0L 9
+#define R1H 10
+#define R1L 11
+
+#define NUMCLASS 4 /* Number of register classes */
+
+#define RETREG(x) (x == CHAR || x == UCHAR ? R0L : R0)
+
+#define FPREG FB /* frame pointer */
+#define STKREG SP /* stack pointer */
+
+#if 0
+#define REGSZ 8 /* Number of registers */
+#define MINRVAR R1 /* first register variable */
+#define MAXRVAR R2 /* last register variable */
+#endif
+
+#define MAXREGS 12 /* 12 registers */
+
+#define RSTATUS \
+ SAREG|TEMPREG, SAREG|PERMREG, SAREG|TEMPREG, SAREG|PERMREG, \
+ SBREG|TEMPREG, SBREG|PERMREG, 0, 0, SCREG, SCREG, SCREG, SCREG,
+
+#define ROVERLAP \
+ {R0H, R0L, -1},\
+ {-1},\
+ {R1H, R1L, -1},\
+ {-1},\
+\
+ {-1},\
+ {-1},\
+\
+ {-1},\
+ {-1},\
+\
+ {R0, -1},\
+ {R0, -1},\
+ {R1, -1},\
+ {R1, -1},
+
+#define PCLASS(p) (p->n_type <= UCHAR ? SCREG : ISPTR(p->n_type) ? SBREG:SAREG)
+
+int COLORMAP(int c, int *r);
+#define GCLASS(x) (x < 4 ? CLASSA : x < 6 ? CLASSB : x < 12 ? CLASSC : CLASSD)
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 6) /* A1 */
+#define ENCRA2(x) ((x) << 12) /* A2 */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+
+#define MYADDEDGE(x, t)
+#define MYREADER(p) myreader(p)
+#define MYP2TREE(p) myp2tree(p)
+
+#if 0
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+#endif
+
+#ifndef NEW_READER
+//#define TAILCALL
+#endif
+#define SFTN (SPECIAL|6)
diff --git a/usr.bin/pcc/arch/m16c/order.c b/usr.bin/pcc/arch/m16c/order.c
new file mode 100644
index 00000000000..4c648c01ef0
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/order.c
@@ -0,0 +1,600 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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 <strings.h>
+
+int canaddr(NODE *);
+
+/*
+ * should the assignment op p be stored,
+ * given that it lies as the right operand of o
+ * (or the left, if o==UNARY MUL)
+ */
+/*
+void
+stoasg(NODE *p, int o)
+{
+ if (x2debug)
+ printf("stoasg(%p, %o)\n", p, o);
+}
+*/
+/* should we delay the INCR or DECR operation p */
+int
+deltest(NODE *p)
+{
+ return 0;
+}
+
+/*
+ * Check if p can be autoincremented.
+ * XXX - nothing can be autoincremented for now.
+ */
+int
+autoincr(NODE *p)
+{
+ return 0;
+}
+
+/* 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.
+ */
+int
+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 ){
+ geninsn(p->n_left, INBREG);
+ p->n_su = -1;
+ return 1;
+ }
+ }
+ geninsn(p, INBREG);
+ return 0;
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p)
+{
+// NODE *l = p->n_left;
+
+#ifdef PCC_DEBUG
+ if (x2debug) {
+ printf("shumul(%p)\n", p);
+ fwalk(p, e2print, 0);
+ }
+#endif
+
+ /* Can only generate OREG of BREGs (or FB) */
+ if (p->n_op == REG && (isbreg(p->n_rval) || p->n_rval == FB))
+ return SOREG;
+#if 0
+ if ((p->n_op == PLUS || p->n_op == MINUS) &&
+ (l->n_op == REG && (isbreg(l->n_rval) || l->n_rval == FB)) &&
+ p->n_right->n_op == ICON)
+ return SOREG;
+ return 0;
+#else
+ return SOREG;
+#endif
+}
+
+/*
+ * 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)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+#if 0
+/*
+ * register allocation for instructions with special preferences.
+ */
+regcode
+regalloc(NODE *p, struct optab *q, int wantreg)
+{
+ regcode regc;
+
+ if (q->op == DIV || q->op == MOD) {
+ /*
+ * 16-bit div.
+ */
+ if (regblk[R0] & 1 || regblk[R2] & 1)
+ comperr("regalloc: needed regs inuse, node %p", p);
+ if (p->n_su & DORIGHT) {
+ regc = alloregs(p->n_right, A0);
+ if (REGNUM(regc) != A0) {
+ p->n_right = movenode(p->n_right, A0);
+ if ((p->n_su & RMASK) == ROREG) {
+ p->n_su &= ~RMASK;
+ p->n_su |= RREG;
+ p->n_right->n_su &= ~LMASK;
+ p->n_right->n_su |= LOREG;
+ }
+ freeregs(regc);
+ regblk[A0] |= 1;
+ }
+ }
+ regc = alloregs(p->n_left, R0);
+ if (REGNUM(regc) != R0) {
+ p->n_left = movenode(p->n_left, R0);
+ freeregs(regc);
+ regblk[R0] |= 1;
+ }
+ if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
+ regc = alloregs(p->n_right, A0);
+ if (REGNUM(regc) != A0) {
+ p->n_right = movenode(p->n_right, A0);
+ if ((p->n_su & RMASK) == ROREG) {
+ p->n_su &= ~RMASK;
+ p->n_su |= RREG;
+ p->n_right->n_su &= ~LMASK;
+ p->n_right->n_su |= LOREG;
+ }
+ }
+ }
+ regblk[A0] &= ~1;
+ regblk[R0] &= ~1;
+ regblk[R2] &= ~1;
+ if (q->op == DIV) {
+ MKREGC(regc, R0, 1);
+ regblk[R0] |= 1;
+ } else {
+ MKREGC(regc, R2, 1);
+ regblk[R2] |= 1;
+ }
+ } else
+ comperr("regalloc");
+ p->n_rall = REGNUM(regc);
+ return regc;
+}
+#endif
+
+/*
+ * Special handling of some instruction register allocation.
+ * - left is the register that left node wants.
+ * - right is the register that right node wants.
+ * - res is in which register the result will end up.
+ * - mask is registers that will be clobbered.
+ *
+ * XXX - Fix this function
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ switch (q->op) {
+
+ case DIV:
+ case MOD:
+ if(q->ltype & (TINT|TSHORT)){
+ static struct rspecial s[] = {
+ { NRES, R0 }, { NRES, R2}, { 0 } };
+ return s;
+ }
+ /*
+ else if(q->ltype & TCHAR) {
+ static struct rspecial s[] = {
+ { NRES, R0L }, { NRES, R0H}, { 0 } };
+ return s;
+ }*/
+ break;
+
+ case MUL:
+ /*
+ if(q->ltype & (TINT|TSHORT)){
+ static struct rspecial s[] = {
+ { NRES, R0 }, { NRES, R2}, { 0 } };
+ return s;
+ }*/
+ comperr("multiplication not implemented");
+ break;
+
+ default:
+ break;
+ }
+ comperr("nspecial entry %d", q - table);
+ return 0; /* XXX gcc */
+}
+
+
+/*
+ * Splitup a function call and give away its arguments first.
+ * Calling convention used ("normal" in IAR syntax) is:
+ * - 1-byte parameters in R0L if possible, otherwise in R0H.
+ * - 2-byte pointers in A0.
+ * - 2-byte non-pointers in R0 if no byte-size arguments are found in
+ * in the first 6 bytes of parameters, otherwise R2 or at last A0.
+ * - 4-byte parameters in R2R0.
+ */
+void
+gencall(NODE *p, NODE *prev)
+{
+ NODE *n = 0; /* XXX gcc */
+ static int storearg(NODE *);
+ int o = p->n_op;
+ int ty = optype(o);
+
+ if (ty == LTYPE)
+ return;
+
+ switch (o) {
+ case CALL:
+ /* swap arguments on some hardop-converted insns */
+ /* Normal call, just push args and be done with it */
+ p->n_op = UCALL;
+//printf("call\n");
+ /* Check if left can be evaluated directly */
+ if (p->n_left->n_op == UMUL) {
+ TWORD t = p->n_left->n_type;
+ int k = BITOOR(freetemp(szty(t)));
+ NODE *n = mklnode(OREG, k, FB, t);
+ NODE *q = tcopy(n);
+ pass2_compile(ipnode(mkbinode(ASSIGN, n, p->n_left,t)));
+ p->n_left = q;
+ }
+ gencall(p->n_left, p);
+ p->n_rval = storearg(p->n_right);
+//printf("end call\n");
+ break;
+
+ case UFORTCALL:
+ case FORTCALL:
+ comperr("FORTCALL");
+
+ case USTCALL:
+ case STCALL:
+ /*
+ * Structure return. Look at the node above
+ * to decide about buffer address:
+ * - FUNARG, allocate space on stack, don't remove.
+ * - nothing, allocate space on stack and remove.
+ * - STASG, get the address of the left side as arg.
+ * - FORCE, this ends up in a return, get supplied addr.
+ * (this is not pretty, but what to do?)
+ */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ /* Create nodes to generate stack space */
+ n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT),
+ mkbinode(MINUS, mklnode(REG, 0, STKREG, INT),
+ mklnode(ICON, p->n_stsize, 0, INT), INT), INT);
+//printf("stsize %d\n", p->n_stsize);
+ pass2_compile(ipnode(n));
+ } else if (prev->n_op == STASG) {
+ n = prev->n_left;
+ if (n->n_op == UMUL)
+ n = nfree(n);
+ else if (n->n_op == NAME) {
+ n->n_op = ICON; /* Constant reference */
+ n->n_type = INCREF(n->n_type);
+ } else
+ comperr("gencall stasg");
+ } else if (prev->n_op == FORCE) {
+ ; /* do nothing here */
+ } else {
+ comperr("gencall bad op %d", prev->n_op);
+ }
+
+ /* Deal with standard arguments */
+ gencall(p->n_left, p);
+ if (o == STCALL) {
+ p->n_op = USTCALL;
+ p->n_rval = storearg(p->n_right);
+ } else
+ p->n_rval = 0;
+ /* push return struct address */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ n = mklnode(REG, 0, STKREG, INT);
+ if (p->n_rval)
+ n = mkbinode(PLUS, n,
+ mklnode(ICON, p->n_rval, 0, INT), INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ if (prev == NULL)
+ p->n_rval += p->n_stsize/4;
+ } else if (prev->n_op == FORCE) {
+ /* return value for this function */
+ n = mklnode(OREG, 8, FPREG, INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ p->n_rval++;
+ } else {
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ n = p;
+ *prev = *p;
+ nfree(n);
+ }
+//printf("end stcall\n");
+ break;
+
+ default:
+ if (ty != UTYPE)
+ gencall(p->n_right, p);
+ gencall(p->n_left, p);
+ break;
+ }
+}
+
+/*
+ * Create separate node trees for function arguments.
+ * This is partly ticky, the strange calling convention
+ * may cause a bunch of code reorganization here.
+ */
+static int
+storearg(NODE *p)
+{
+ NODE *n, *q, **narry;
+ int nch, k, i, nn, rary[4];
+ int r0l, r0h, r2, a0, stk, sz;
+ TWORD t;
+ int maxrargs = 0;
+
+ if (p->n_op == CM)
+ maxrargs = p->n_stalign;
+
+ /* count the arguments */
+ for (i = 1, q = p; q->n_op == CM; q = q->n_left)
+ i++;
+ nn = i;
+
+ /* allocate array to store arguments */
+ narry = tmpalloc(sizeof(NODE *)*nn);
+
+ /* enter nodes into array */
+ for (q = p; q->n_op == CM; q = q->n_left)
+ narry[--i] = q->n_right;
+ narry[--i] = q;
+
+ /* free CM nodes */
+ for (q = p; q->n_op == CM; ) {
+ n = q->n_left;
+ nfree(q);
+ q = n;
+ }
+
+ /* count char args */
+ r0l = r0h = r2 = a0 = 0;
+ for (sz = nch = i = 0; i < nn && i < 6; i++) {
+ TWORD t = narry[i]->n_type;
+ if (sz >= 6)
+ break;
+ if (t == CHAR || t == UCHAR) {
+ nch++;
+ sz++;
+ } else if ((t >= SHORT && t <= UNSIGNED) ||
+ t > BTMASK || t == FLOAT) {
+ sz += 2;
+ } else /* long, double */
+ sz += 4;
+
+ }
+
+ /*
+ * Now the tricky part. The parameters that should be on stack
+ * must be found and pushed first, then the register parameters.
+ * For the latter, be sure that evaluating them do not use any
+ * registers where argument values already are inserted.
+ * XXX - function pointers?
+ * XXX foo(long a, char b) ???
+ */
+ for (stk = 0; stk < 4; stk++) {
+ TWORD t;
+
+ if (stk == nn)
+ break;
+ t = narry[stk]->n_type;
+ if (ISFTN(DECREF(t)))
+ t = LONG;
+ switch (t) {
+ case CHAR: case UCHAR:
+ if (r0l) {
+ if (r0h)
+ break;
+ rary[stk] = R2; /* char talk for 'R0H' */
+ r0h = 1;
+ } else {
+ rary[stk] = R0;
+ r0l = 1;
+ }
+ continue;
+
+ case INT: case UNSIGNED:
+ if (r0l || nch) {
+ if (r2) {
+ if (a0)
+ break;
+ rary[stk] = A0;
+ a0 = 1;
+ } else {
+ rary[stk] = R2;
+ r2 = 1;
+ }
+ } else {
+ rary[stk] = R0;
+ r0l = r0h = 1;
+ }
+ continue;
+
+ case LONG: case ULONG:
+ if (r0l || r2)
+ break;
+ rary[stk] = R0;
+ r0l = r0h = r2 = 1;
+ continue;
+
+ default:
+ if (ISPTR(narry[stk]->n_type) &&
+ !ISFTN(DECREF(narry[stk]->n_type))) {
+ if (a0) {
+ if (r0l || nch) {
+ if (r2)
+ break;
+ rary[stk] = R2;
+ r2 = 1;
+ } else {
+ rary[stk] = R0;
+ r0l = r0h = 1;
+ }
+ } else {
+ rary[stk] = A0;
+ a0 = 1;
+ }
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+
+ /*
+ * The arguments that must be on stack are stk->nn args.
+ * Argument 0->stk-1 should be put in the rary[] register.
+ */
+ for (sz = 0, i = nn-1; i >= stk; i--) { /* first stack args */
+ NODE nod;
+ pass2_compile(ipnode(mkunode(FUNARG,
+ narry[i], 0, narry[i]->n_type)));
+ nod.n_type = narry[i]->n_type;
+ sz += tlen(&nod);
+ }
+ /* if param cannot be addressed directly, evaluate and put on stack */
+ for (i = 0; i < stk; i++) {
+
+ if (canaddr(narry[i]))
+ continue;
+ t = narry[i]->n_type;
+ k = BITOOR(freetemp(szty(t)));
+ n = mklnode(OREG, k, FB, t);
+ q = tcopy(n);
+ pass2_compile(ipnode(mkbinode(ASSIGN, n, narry[i], t)));
+ narry[i] = q;
+ }
+ /* move args to registers */
+ for (i = 0; i < stk; i++) {
+ t = narry[i]->n_type;
+ pass2_compile(ipnode(mkbinode(ASSIGN,
+ mklnode(REG, 0, rary[i], t), narry[i], t)));
+ }
+ return sz;
+}
+
+/*
+ * Tell if a register can hold a specific datatype.
+ */
+#if 0
+int
+mayuse(int reg, TWORD type)
+{
+ return 1; /* Everything is OK */
+}
+#endif
+
+#ifdef TAILCALL
+void
+mktailopt(struct interpass *ip1, struct interpass *ip2)
+{
+ extern int earlylab;
+ extern char *cftname;
+ char *fn;
+ NODE *p;
+
+ p = ip1->ip_node->n_left->n_left;
+ if (p->n_op == ICON) {
+ fn = p->n_name;
+ /* calling ourselves */
+ p = ip1->ip_node->n_left;
+ if (p->n_op == CALL) {
+ if (storearg(p->n_right))
+ comperr("too many args: fix mktailopt");
+ p->n_op = UCALL;
+ }
+ tfree(ip1->ip_node);
+ p = ip2->ip_node->n_left;
+ if (strcmp(fn, cftname)) {
+ /* Not us, must generate fake prologue */
+ ip1->type = IP_ASM;
+ ip1->ip_asm = "mov.w FB,SP\n\tpop.w FB";
+ pass2_compile(ip1);
+ p->n_lval = p->n_rval = 0;
+ p->n_name = fn;
+ } else
+ p->n_lval = earlylab;
+ } else {
+ pass2_compile(ip1);
+ }
+ pass2_compile(ip2);
+}
+#endif
diff --git a/usr.bin/pcc/arch/m16c/table.c b/usr.bin/pcc/arch/m16c/table.c
new file mode 100644
index 00000000000..879a41334c7
--- /dev/null
+++ b/usr.bin/pcc/arch/m16c/table.c
@@ -0,0 +1,595 @@
+#include "pass2.h"
+
+# define ANYSIGNED TINT|TLONG|TCHAR
+# define ANYUSIGNED TUNSIGNED|TULONG|TUCHAR
+# define ANYFIXED ANYSIGNED|ANYUSIGNED
+# define TL TLONG|TULONG
+# define TWORD TUNSIGNED|TINT
+# define TCH TCHAR|TUCHAR
+
+struct optab table[] = {
+/* First entry must be an empty entry */
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
+
+/* (signed) char -> int/pointer */
+{ SCONV, INAREG,
+ SCREG, TCHAR,
+ SANY, TINT|TPOINT,
+ NAREG, RESC1,
+ " mov.b AL, A1\n\texts.b A1\n", },
+
+/* (unsigned) char -> int/pointer */
+{ SCONV, INAREG,
+ SCREG, TUCHAR,
+ SANY, TINT|TPOINT,
+ NAREG, RESC1,
+ " mov.b AL, A1\n", },
+
+/* unsigned char -> long */
+{ SCONV, INAREG,
+ SCREG, TUCHAR,
+ SANY, TL,
+ NAREG|NASL, RESC1,
+ " mov.b AL, A1\n mov.w #0,U1\n", },
+
+/* int or pointer -> (unsigned) long */
+{ SCONV, INAREG,
+ SAREG|SNAME, TWORD|TPOINT,
+ SANY, TL,
+ NAREG|NASL, RESC1,
+ " mov.w AL,A1\n mov.w #0,U1\n", },
+
+/* char -> (signed) long */
+{ SCONV, INAREG,
+ SAREG|SNAME, TCHAR,
+ SANY, TLONG,
+ NAREG|NASL, RESC1,
+ " exts.b AL\n exts.w AL\n", },
+
+/* long -> ulong */
+{ SCONV, INAREG,
+ SAREG, TL,
+ SANY, TL,
+ 0, RLEFT,
+ "", },
+
+/* long -> int or pointer */
+{ SCONV, INAREG,
+ SAREG|SOREG|SNAME, TL,
+ SANY, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " mov.w AL,A1\n", },
+
+/* int -> char */
+{ SCONV, INCREG,
+ SAREG, TWORD,
+ SANY, TCH,
+ NCREG, RESC1,
+ " mov.b AL, A1\n", },
+
+/* int -> long */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SANY, TLONG,
+ NAREG|NASL, RESC1,
+ " exts.w AL", },
+
+/* long -> char */
+{ SCONV, INAREG,
+ SAREG, TL,
+ SANY, TCH,
+ NAREG|NASL, RESC1,
+ "", },
+
+{ SCONV, INAREG,
+ SAREG, TPOINT,
+ SANY, TWORD,
+ 0, RLEFT,
+ "", },
+
+{ PLUS, INAREG|FOREFF,
+ SAREG, TL,
+ SCON|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " add.w AR,AL\n adc.w UR,UL\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG, TL,
+ SCON|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " sub.w AR,AL\n sbb.w UR,UL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TL,
+ SAREG|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " and.w AR,AL\n and.w UR,UL\n", },
+
+{ ER, INAREG|FOREFF,
+ SAREG, TL,
+ SAREG|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " xor.w AR,AL\n xor.w UR,UL\n", },
+
+{ OR, INAREG|FOREFF,
+ SAREG, TL,
+ SAREG|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " xor.w AR,AL\n xor.w UR,UL\n", },
+
+{ COMPL, INAREG|FOREFF,
+ SAREG, TL,
+ SAREG|SNAME|SOREG, TL,
+ 0, RLEFT,
+ " not.w AR,AL\n not.w UR,UL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+/* XXX - Is this rule really correct? Having a SAREG shape seems kind of
+ strange. Doesn't work. Gives a areg as A1. */
+#if 0
+{ OPSIMP, INBREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ NBREG, RESC1,
+ " ++Ow AR,A1\n", },
+#endif
+
+{ OPSIMP, INBREG,
+ SBREG, TWORD|TPOINT,
+ SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCREG|FOREFF,
+ SCREG, TCH,
+ SCREG|SNAME|SOREG|SCON, TCH,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+/* XXX - Do these work? check nspecial in order.c */
+/* signed integer division */
+{ DIV, INAREG,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ /*2*NAREG|NASL|*/NSPECIAL, RLEFT,
+ " div.w AR\n mov.w r0,AL\n", },
+ // " xor.w r2\n div.w AR\n", },
+
+
+/* signed integer/char division - separate entry for FOREFF */
+{ DIV, FOREFF,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ 0, 0,
+ "", },
+
+#if 0
+/* signed char division */
+{ DIV, INCREG,
+ SCREG, TCHAR,
+ SCREG|SNAME|SOREG, TCH,
+ 2*NCREG|NCSL|NSPECIAL, RLEFT,
+ " div.b AR\n\tmov.b r0l,AL\n", },
+ // " xor.w r2\n div.w AR\n", },
+#endif
+
+/* signed integer modulus, equal to above */
+{ MOD, INAREG,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ /*2*NAREG|NASL|*/NSPECIAL, RLEFT,
+ " div.w AR\n\tmov r2,AL\n", },
+
+/* signed integer modulus - separate entry for FOREFF */
+{ MOD, FOREFF,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ 0, 0,
+ "", },
+
+/* signed integer multiplication */
+{ MUL, INAREG,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ 2*NAREG|NASL|NSPECIAL, RESC1,
+ " mul.w AL,AR\n", },
+
+{ MUL, FOREFF,
+ SAREG, TINT,
+ SAREG|SNAME|SOREG, TWORD,
+ 0, 0,
+ "", },
+
+#if 0
+{ LS, INAREG,
+ SAREG, TWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " shl.w AR,AL\n", },
+#endif
+
+{ LS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ 0, RLEFT,
+ " push.b r1h\n"
+ " mov.b AR,r1h\n"
+ " shl.w r1h,AL\n"
+ " pop.b r1h\n", },
+
+{ LS, INAREG,
+ SAREG, TL,
+ SAREG, TWORD,
+ 0, RLEFT,
+ " push.b r1h\n"
+ " mov.b AR,r1h\n"
+ " shl.l r1h,ZG\n"
+ " pop.b r1h\n", },
+
+{ RS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ 0, RLEFT,
+ " push.b r1h\n"
+ " mov.b AR,r1h\n"
+ " neg.b r1h\n"
+ " shl.w r1h,AL\n"
+ " pop.b r1h\n", },
+
+{ RS, INAREG,
+ SAREG, TL,
+ SAREG, TWORD,
+ 0, RLEFT,
+ " push.b r1h\n"
+ " mov.b AR,r1h\n"
+ " neg.b r1h\n"
+ " shl.l r1h,ZG\n"
+ " pop.b r1h\n", },
+
+#if 0
+{ RS, INAREG,
+ SAREG, TUNSIGNED,
+ SCON, TANY,
+ 0, RLEFT,
+ " shl ZA,AL\n", },
+
+{ RS, INAREG,
+ SAREG, TINT,
+ SCON, TANY,
+ 0, RLEFT,
+ " sha ZA,AL\n", },
+#endif
+
+{ OPLOG, FORCC,
+ SAREG|SBREG|SOREG|SNAME, TL,
+ SAREG|SBREG|SOREG|SNAME, TL,
+ 0, 0,
+ "ZF", },
+
+{ OPLOG, FORCC,
+ SBREG|SOREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RESCC,
+ " cmp.w AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT,
+ SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT,
+ 0, RESCC,
+ " cmp.w AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCREG|SOREG|SNAME, TCH,
+ SCREG|SOREG|SNAME, TCH,
+ 0, RESCC,
+ " cmp.b AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCREG|SOREG|SNAME, TCH,
+ SCREG|SOREG|SNAME, TCH,
+ 0, RESCC,
+ " cmp.b AR,AL\n", },
+
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp.w ZC\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON|SNAME|SOREG|SAREG, TL|TFTN,
+ NAREG, RESC1,
+ " mov.w AR,A1\n mov.w UR,U1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON|SNAME|SOREG|SAREG|SBREG, TWORD|TPOINT,
+ NAREG, RESC1,
+ " mov.w AR,A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SBREG|SCON|SNAME|SOREG|SAREG, TWORD|TPOINT,
+ NBREG, RESC1,
+ " mov.w AR,A1\n", },
+ /*
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON|SNAME|SOREG, TCH,
+ NAREG, RESC1,
+ " mov.b AR, A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SCON|SNAME|SOREG, TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " mov.b AR,A1\n", },
+ */
+
+{ OPLTYPE, INCREG,
+ SANY, TANY,
+ SCON|SNAME|SOREG, TCHAR|TUCHAR,
+ NCREG, RESC1,
+ " mov.b AR,A1\n", },
+
+{ COMPL, INAREG,
+ SAREG, TWORD,
+ SANY, TANY,
+ 0, RLEFT,
+ " not.w AL\n", },
+
+{ COMPL, INCREG,
+ SCREG, TCH,
+ SANY, TANY,
+ 0, RLEFT,
+ " not.b AL\n", },
+
+/* Push function address */
+{ FUNARG, FOREFF,
+ SCON, TFTN,
+ SANY, TANY,
+ 0, RNULL,
+ "ZH", },
+
+{ FUNARG, FOREFF,
+ SOREG, TFTN,
+ SANY, TANY,
+ 0, RNULL,
+ "ZI", },
+
+{ FUNARG, FOREFF,
+ SNAME|SAREG, TL|TFTN,
+ SANY, TANY,
+ 0, RNULL,
+ " push.w UL\n push.w AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SANY, TANY,
+ 0, RNULL,
+ " push.w AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, RNULL,
+ " push.b AL\n", },
+
+/* Match function pointers first */
+#if 0
+{ ASSIGN, FOREFF,
+ SFTN, TWORD|TPOINT,
+ SFTN, TWORD|TPOINT,
+ NAREG, 0,
+ "ZD", },
+#endif
+
+{ ASSIGN, INAREG,
+ SAREG, TFTN,
+ SCON, TFTN,
+ 0, RLEFT,
+ "ZD", },
+
+{ ASSIGN, INBREG,
+ SBREG, TFTN,
+ SCON, TFTN,
+ 0, RLEFT,
+ "ZD", },
+
+{ ASSIGN, INAREG,
+ SAREG, TFTN,
+ SBREG|SAREG|SOREG|SNAME, TFTN,
+ 0, RLEFT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, INBREG,
+ SBREG, TFTN,
+ SBREG|SAREG|SOREG|SNAME, TFTN,
+ 0, RLEFT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, INAREG,
+ SBREG|SAREG|SOREG|SNAME, TFTN,
+ SAREG, TFTN,
+ 0, RRIGHT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, INBREG,
+ SBREG|SAREG|SOREG|SNAME, TFTN,
+ SBREG, TFTN,
+ 0, RRIGHT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+/* a reg -> a reg */
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, INAREG,
+ SBREG|SAREG|SOREG|SNAME, TL,
+ SAREG, TL,
+ 0, RRIGHT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, INBREG,
+ SBREG|SAREG|SOREG|SNAME, TL,
+ SBREG, TL,
+ 0, RRIGHT,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, FOREFF,
+ SBREG|SAREG|SOREG|SNAME, TL,
+ SCON|SBREG|SAREG|SOREG|SNAME, TL,
+ 0, 0,
+ " mov.w AR,AL\n mov.w UR,UL\n", },
+
+{ ASSIGN, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, RLEFT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, INBREG|FOREFF,
+ SBREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, RLEFT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, 0,
+ " mov.w AR,AL\n", },
+
+/* char, oreg/name -> c reg */
+{ ASSIGN, FOREFF|INCREG,
+ SCREG, TCHAR|TUCHAR,
+ SOREG|SNAME|SCON, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " mov.b AR,AL\n", },
+
+/* int, oreg/name -> a reg */
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SOREG|SNAME, TWORD|TPOINT,
+ 0, RLEFT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TWORD|TPOINT,
+ SOREG|SNAME, TWORD|TPOINT,
+ 0, RLEFT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RRIGHT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG|SNAME, TWORD|TPOINT,
+ SBREG, TWORD|TPOINT,
+ 0, RRIGHT,
+ " mov.w AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SOREG|SNAME, TCHAR|TUCHAR,
+ SCREG, TCHAR|TUCHAR,
+ 0, RRIGHT,
+ " mov.b AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SCREG, TCHAR|TUCHAR,
+ SCREG, TCHAR|TUCHAR,
+ 0, RRIGHT,
+ " mov.b AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TWORD|TPOINT,
+ SBREG, TWORD|TPOINT,
+ 0, RRIGHT,
+ " mov.w AR,AL\n", },
+
+ /*
+{ MOVE, FOREFF|INAREG,
+ SAREG|SBREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ NAREG, RESC1,
+ " mov.w AL, AR\n", },
+ */
+
+{ UMUL, INAREG,
+ SBREG, TPOINT|TWORD,
+ SANY, TFTN,
+ NAREG, RESC1,
+ " mov.w [AL],A1\n mov.w 2[AL],U1\n", },
+
+{ UMUL, INAREG,
+ SBREG, TPOINT|TWORD,
+ SANY, TPOINT|TWORD,
+ NAREG, RESC1,
+ " mov.w [AL],A1\n", },
+
+{ UMUL, INBREG,
+ SBREG, TPOINT|TWORD,
+ SANY, TPOINT|TWORD,
+ NBREG|NBSL, RESC1,
+ " mov.w [AL],A1\n", },
+
+{ UMUL, INAREG,
+ SBREG, TCHAR|TUCHAR|TPTRTO,
+ SANY, TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " mov.b [AL], A1\n", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " jsr.w CL\nZB", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG, RESC1,
+ " jsr.w CL\nZB", },
+
+{ UCALL, INAREG,
+ SNAME|SOREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " jsri.a AL\nZB", },
+
+{ UCALL, FOREFF,
+ SNAME|SOREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " jsri.a AL\nZB", },
+
+{ UCALL, INAREG,
+ SBREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " jsri.a [AL]\nZB", },
+
+{ UCALL, FOREFF,
+ SBREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " jsri.a [AL]\nZB", },
+
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
+
diff --git a/usr.bin/pcc/arch/mips/TODO b/usr.bin/pcc/arch/mips/TODO
new file mode 100644
index 00000000000..63b5f67c34a
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/TODO
@@ -0,0 +1,7 @@
+* Look at long long support for the new register allocator.
+
+* Add floating point support.
+
+* Add support for struct/union arguments and return values.
+
+* See if the workaround for the function arguments can be removed/rewritten.
diff --git a/usr.bin/pcc/arch/mips/code.c b/usr.bin/pcc/arch/mips/code.c
new file mode 100644
index 00000000000..397210ece14
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/code.c
@@ -0,0 +1,239 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+# include "pass1.h"
+# include "manifest.h"
+
+/* Offset to arguments passed to a function. */
+int passedargoff;
+
+/*
+ * 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(" .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(" .globl %s\n", c);
+ printf("%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;
+}
+
+/*
+ * helper for bfcode() to put register arguments on stack.
+ */
+static void
+argmove(struct symtab *s, int regno)
+{
+ NODE *p, *r;
+
+ s->sclass = PARAM;
+ s->soffset = NOOFFSET;
+
+ oalloc(s, &passedargoff);
+
+ spname = s;
+ p = buildtree(NAME, NIL, NIL);
+ r = bcon(0);
+ r->n_op = REG;
+ r->n_rval = regno;
+ r->n_type = p->n_type;
+ r->n_sue = p->n_sue;
+ r->n_df = p->n_df;
+ ecode(buildtree(ASSIGN, p, r));
+}
+
+/*
+ * 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, m;
+
+ /* Passed arguments start 64 bits above the framepointer. */
+ passedargoff = 64;
+
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ /* Function returns struct, adjust arg offset */
+ for (i = 0; i < n; i++)
+ a[i]->soffset += SZPOINT(INT);
+ }
+
+ m = n <= 4 ? n : 4;
+
+ for(i = 0; i < m; i++) {
+ /*
+ if(a[i]->stype == LONGLONG || a[i]->stype == ULONGLONG) {
+ printf("longlong\n");
+ argmove(a[i], A0+i);
+
+ if(i+1 < 4) {
+ argmove(a[i], A0+i+1);
+ }
+
+ i++;
+ } else*/
+ argmove(a[i], A0+i);
+
+ }
+}
+
+
+/*
+ * 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 flag )
+{
+}
+
+void
+bjobcode()
+{
+}
+
+/*
+ * 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(" .zero %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(struct swents **p, int n)
+{
+}
diff --git a/usr.bin/pcc/arch/mips/local.c b/usr.bin/pcc/arch/mips/local.c
new file mode 100644
index 00000000000..33baa4e8cd2
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/local.c
@@ -0,0 +1,533 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+# include "pass1.h"
+
+/* this file contains code which is dependent on the target machine */
+
+NODE *
+clocal(NODE *p)
+{
+ /* this 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 */
+
+ register struct symtab *q;
+ register NODE *r, *l;
+ register int o;
+ register int m, ml;
+ TWORD t;
+
+//printf("in:\n");
+//fwalk(p, eprint, 0);
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ 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 STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ break;
+
+ case FUNARG:
+ /* Args smaller than int are given as int */
+ if (p->n_type != CHAR && p->n_type != UCHAR &&
+ p->n_type != SHORT && p->n_type != USHORT)
+ break;
+ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
+ p->n_type = INT;
+ p->n_sue = MKSUE(INT);
+ p->n_rval = SZINT;
+ 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;
+ }
+#if 0
+ else if (l->n_right->n_op == SCONV &&
+ l->n_left->n_type == l->n_right->n_type) {
+ r = l->n_left->n_left;
+ nfree(l->n_left);
+ l->n_left = r;
+ r = l->n_right->n_left;
+ nfree(l->n_right);
+ l->n_right = r;
+ }
+#endif
+ }
+ break;
+
+ case PCONV:
+ ml = p->n_left->n_type;
+ l = p->n_left;
+ if ((ml == CHAR || ml == UCHAR || ml == SHORT || ml == USHORT)
+ && l->n_op != ICON)
+ break;
+ 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);
+ return l;
+ }
+
+ 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 == NAME || l->n_op == UMUL) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ }
+ }
+
+#if 0
+ if ((p->n_type == INT || p->n_type == UNSIGNED) &&
+ ISPTR(l->n_type)) {
+ nfree(p);
+ return l;
+ }
+#endif
+
+ 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 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;
+ nfree(p);
+ return l;
+ }
+ if (DEUNSIGN(p->n_type) == SHORT &&
+ DEUNSIGN(l->n_type) == SHORT) {
+ nfree(p);
+ p = l;
+ }
+ 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 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, 0,
+ MKSUE(INT));
+ p->n_left->n_rval = RETREG;
+ break;
+ }
+//printf("ut:\n");
+//fwalk(p, eprint, 0);
+
+
+ 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;
+}
+
+/*
+ * is an automatic variable of type t OK for a register variable
+ */
+int
+cisreg(TWORD t)
+{
+ if (t == INT || t == UNSIGNED || t == LONG || t == ULONG)
+ return(1);
+ return 0; /* XXX - fix reg assignment in pftn.c */
+}
+
+/*
+ * 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 NAME node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ if ((off % SZINT) == 0)
+ p = buildtree(MUL, p, bcon(off/SZINT));
+ else if ((off % SZSHORT) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZSHORT));
+ p = buildtree(PLUS, p, bcon(1));
+ p = buildtree(RS, p, bcon(1));
+ } else if ((off % SZCHAR) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZCHAR));
+ p = buildtree(PLUS, p, bcon(3));
+ p = buildtree(RS, p, bcon(2));
+ } else
+ cerror("roundsp");
+
+ /* 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! */
+
+ /* add the size to sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, 0);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(PLUSEQ, sp, p));
+}
+
+/*
+ * print out a constant node
+ * mat be associated with a label
+ */
+void
+ninval(NODE *p)
+{
+ struct symtab *q;
+ TWORD t;
+
+ p = p->n_left;
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ inval(p->n_lval & 0xffffffff);
+ inval(p->n_lval >> 32);
+ 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;
+ default:
+ cerror("ninval");
+ }
+}
+
+/*
+ * print out an integer.
+ */
+void
+inval(CONSZ word)
+{
+ word &= 0xffffffff;
+ printf(" .long 0x%llx\n", word);
+}
+
+/* output code to initialize a floating point value */
+/* the proper alignment has been obtained */
+void
+finval(NODE *p)
+{
+ switch (p->n_type) {
+ case LDOUBLE:
+ printf("\t.tfloat\t0t%.20Le\n", p->n_dcon);
+ break;
+ case DOUBLE:
+ printf("\t.dfloat\t0d%.20e\n", (double)p->n_dcon);
+ break;
+ case FLOAT:
+ printf("\t.ffloat\t0f%.20e\n", (float)p->n_dcon);
+ break;
+ }
+}
+
+/* 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);
+}
+
+/* curid is a variable which is defined but
+ * is not initialized (and not a function );
+ * This routine returns the storage class for an uninitialized declaration
+ */
+int
+noinit()
+{
+ return(EXTERN);
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+/* 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(" .comm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .comm %s,0%o\n", exname(q->sname), off);
+#endif
+}
+
+/* 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(" .lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+ printf(" .%s\n", loctbl[locc]);
+}
diff --git a/usr.bin/pcc/arch/mips/local2.c b/usr.bin/pcc/arch/mips/local2.c
new file mode 100644
index 00000000000..37fa54f13fb
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/local2.c
@@ -0,0 +1,774 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+# include "pass2.h"
+# include <ctype.h>
+
+void acon(NODE *p);
+int argsize(NODE *p);
+void genargs(NODE *p);
+static void sconv(NODE *p);
+void branchfunc(NODE *p);
+void offchg(NODE *p);
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int regoff[32];
+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, j;
+
+ printf(" addi $sp, $sp, -%d\n", addto + 8);
+ printf(" sw $ra, %d($sp)\n", addto + 4);
+ printf(" sw $fp, %d($sp)\n", addto);
+ printf(" addi $fp, $sp, %d\n", addto);
+
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
+ if (i & 1)
+ fprintf(stdout, " sw %s, -%d(%s)\n",
+ rnames[j], regoff[j], rnames[FPREG]);
+}
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int i, j, addto;
+
+ addto = p2maxautooff;
+ if (addto >= AUTOINIT)
+ addto -= AUTOINIT;
+ addto /= SZCHAR;
+
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1) {
+ addto += SZINT/SZCHAR;
+ regoff[j] = addto;
+ }
+ }
+
+ return addto;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+
+ ftype = ipp->ipp_type;
+ if (ipp->ipp_vis)
+ printf(" .globl %s\n", ipp->ipp_name);
+ printf(" .align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+ prtprolog(ipp, addto);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i, j;
+ int addto;
+
+ addto = offcalc(ipp);
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1)
+ fprintf(stdout, " lw %s, -%d(%s)\n",
+ rnames[j], regoff[j], rnames[FPREG]);
+ }
+
+ printf(" lw $ra, %d($sp)\n", addto + 4);
+ printf(" lw $fp, %d($sp)\n", addto);
+ printf(" addi $sp, $sp, %d\n", addto + 8);
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ /* XXX - implement struct return support. */
+ } else {
+ printf(" jr $ra\n nop\n");
+ }
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ case PLUS:
+ str = "addu";
+ break;
+ case MINUS:
+ str = "subu";
+ break;
+ case AND:
+ str = "and";
+ break;
+ case OR:
+ str = "or";
+ break;
+ case ER:
+ str = "xor";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+
+ printf("%s%c", str, f);
+}
+
+char *
+rnames[] = { /* keyed to register number tokens */
+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8",
+ "$t9", "$v0", "$v1", "$zero", "$at", "$a0", "$a1", "$a2", "$a3",
+ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", "$k0",
+ "$k1", "$gp", "$sp", "$fp", "$ra",
+};
+
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(SZSHORT/SZCHAR);
+
+ case DOUBLE:
+ return(SZDOUBLE/SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ return(SZINT/SZCHAR);
+
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG/SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type)/SZCHAR;
+ }
+}
+
+
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+ FILE *fp = stdout;
+
+ if (p->n_left->n_op == REG && p->n_left->n_type == PTR+STRTY)
+ return; /* already on stack */
+
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *r;
+
+ switch (c) {
+ case 'A': /* Set the right offset for SCON OREG to REG */
+ offchg(p);
+ break;
+
+ case 'B':
+ /*
+ * Function arguments
+ */
+
+ break;
+
+ case 'C': /* remove arguments from stack after subroutine call */
+ printf(" addi %s, %s, %d\n",
+ rnames[STKREG], rnames[STKREG], (p->n_rval + 4) * 4);
+ break;
+
+ case 'H': /* Fix correct order of sub from stack */
+ /* Check which leg was evaluated first */
+ if ((p->n_su & DORIGHT) == 0)
+ putchar('r');
+ break;
+
+ case 'I': /* high part of init constant */
+ if (p->n_name[0] != '\0')
+ comperr("named highword");
+ fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff);
+ break;
+
+ case 'Q': /* Branch instructions */
+ branchfunc(p);
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+/* set up temporary registers */
+void
+setregs()
+{
+ /* 12 free regs on the mips (0-9, temporary and 10-11 is v0 and v1). */
+ fregs = 12;
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+#if 0
+ int r;
+
+ if (p->n_op == STARG )
+ p = p->n_left;
+
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
+
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return(0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
+
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
+
+ if (optype(p->n_op) != LTYPE)
+ return(0);
+ return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+ printf(CONFMT, val);
+}
+
+void
+conput(FILE *fp, NODE *p)
+{
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput");
+ }
+}
+
+/*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:
+ fputs(rnames[p->n_rval + 1], stdout);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+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 NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+
+ if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ //fputc('$', io);
+ conput(io, p);
+ return;
+
+ case MOVE:
+ case REG:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+/* This function changes the offset of a OREG when doing a type cast. */
+void
+offchg(NODE *p)
+{
+
+ if (p->n_op != SCONV) {
+ comperr("illegal offchg");
+ }
+
+#ifndef RTOLBYTES
+ /* change the offset depending on source and target types */
+ switch(p->n_left->n_type) {
+ case SHORT:
+ case USHORT:
+ if (p->n_type == CHAR || p->n_type == UCHAR) {
+ p->n_left->n_lval += 1;
+ }
+ break;
+
+ case UNSIGNED:
+ case ULONG:
+ case INT:
+ case LONG:
+ if (p->n_type == CHAR || p->n_type == UCHAR) {
+ p->n_left->n_lval += 3;
+ } else if (p->n_type == SHORT || p->n_type == USHORT) {
+ p->n_left->n_lval += 2;
+ }
+ break;
+
+ /* This code is not tested!
+ case LONGLONG:
+ case ULONGLONG:
+ if (p->n_type == CHAR || p->n_type == UCHAR) {
+ p->n_lval += 7;
+ } else if (p->n_type == SHORT || p->n_type == USHORT) {
+ p->n_lval += 6;
+ } else if (p->n_type == UNSIGNED || p->n_type == ULONG ||
+ p->n_type == INT || p->n_type == LONG) {
+
+ p->n_lval += 4;
+ }
+ break;
+ */
+ }
+#endif
+
+ /* print the code for the OREG */
+ if (p->n_left->n_lval) {
+ printf("%d", (int)p->n_left->n_lval);
+ }
+
+ printf("(%s)", rnames[p->n_left->n_rval]);
+
+}
+
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+}
+
+void branchfunc(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o < EQ || o > GT)
+ cerror("bad binary conditional branch: %s", opst[o]);
+
+ switch(o) {
+ case EQ:
+ printf("beq ");
+ adrput(stdout, getlr(p, 'L'));
+ printf(", ");
+ adrput(stdout, getlr(p, 'R'));
+ printf(", ");
+ break;
+ case NE:
+ printf("bne ");
+ adrput(stdout, getlr(p, 'L'));
+ printf(", ");
+ adrput(stdout, getlr(p, 'R'));
+ printf(", ");
+ break;
+ case LE:
+ expand(p, 0, "blez A1, ");
+ break;
+ case LT:
+ expand(p, 0, "bltz A1, ");
+ break;
+ case GE:
+ expand(p, 0, "bgez A1, ");
+ break;
+ case GT:
+ expand(p, 0, "bgez A1, ");
+ break;
+ }
+ printf(".L%d\n", p->n_label);
+ printf(" nop\n");
+}
+
+#if 0
+/*
+ * Do some local optimizations that must be done after optim is called.
+ */
+static void
+optim2(NODE *p)
+{
+ int op = p->n_op;
+ int m, ml;
+ NODE *l;
+
+ /* Remove redundant PCONV's */
+ if (op == PCONV) {
+ l = p->n_left;
+ m = BTYPE(p->n_type);
+ ml = BTYPE(l->n_type);
+ if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT ||
+ m == DOUBLE || m == STRTY || m == UNIONTY || m == ENUMTY ||
+ m == UNSIGNED || m == ULONG || m == ULONGLONG) &&
+ (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT ||
+ ml == DOUBLE || ml == STRTY || ml == UNIONTY ||
+ ml == ENUMTY || ml == UNSIGNED || ml == ULONG ||
+ ml == ULONGLONG) && ISPTR(l->n_type)) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ } else
+ if (ISPTR(DECREF(p->n_type)) &&
+ (l->n_type == INCREF(STRTY))) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ } else
+ if (ISPTR(DECREF(l->n_type)) &&
+ (p->n_type == INCREF(INT) ||
+ p->n_type == INCREF(STRTY) ||
+ p->n_type == INCREF(UNSIGNED))) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ }
+
+ }
+ /* Add constands, similar to the one in optim() */
+ if (op == PLUS && p->n_right->n_op == ICON) {
+ l = p->n_left;
+ if (l->n_op == PLUS && l->n_right->n_op == ICON &&
+ (p->n_right->n_name[0] == '\0' ||
+ l->n_right->n_name[0] == '\0')) {
+ l->n_right->n_lval += p->n_right->n_lval;
+ if (l->n_right->n_name[0] == '\0')
+ l->n_right->n_name = p->n_right->n_name;
+ nfree(p->n_right);
+ *p = *l;
+ nfree(l);
+ }
+ }
+
+ /* Convert "PTR undef" (void *) to "PTR uchar" */
+ /* XXX - should be done in MI code */
+ if (BTYPE(p->n_type) == VOID)
+ p->n_type = (p->n_type & ~BTMASK) | UCHAR;
+}
+#endif
+
+static void
+myhardops(NODE *p)
+{
+ int ty = optype(p->n_op);
+ NODE *l, *r, *q;
+
+ if (ty == UTYPE)
+ return myhardops(p->n_left);
+ if (ty != BITYPE)
+ return;
+ myhardops(p->n_right);
+ if (p->n_op != STASG)
+ return;
+
+ /*
+ * If the structure size to copy is less than 32 byte, let it
+ * be and generate move instructions later. Otherwise convert it
+ * to memcpy() calls, unless it has a STCALL function as its
+ * right node, in which case it is untouched.
+ * STCALL returns are handled special.
+ */
+ if (p->n_right->n_op == STCALL || p->n_right->n_op == USTCALL)
+ return;
+ l = p->n_left;
+ if (l->n_op == UMUL)
+ l = nfree(l);
+ else if (l->n_op == NAME) {
+ l->n_op = ICON; /* Constant reference */
+ l->n_type = INCREF(l->n_type);
+ } else
+ comperr("myhardops");
+ r = p->n_right;
+ q = mkbinode(CM, l, r, 0);
+ q = mkbinode(CM, q, mklnode(ICON, p->n_stsize, 0, INT), 0);
+ p->n_op = CALL;
+ p->n_right = q;
+ p->n_left = mklnode(ICON, 0, 0, 0);
+ p->n_left->n_name = "memcpy";
+}
+
+void
+myreader(NODE *p)
+{
+ int e2print(NODE *p, int down, int *a, int *b);
+ // walkf(p, optim2);
+ myhardops(p);
+ if (x2debug) {
+ printf("myreader final tree:\n");
+ fwalk(p, e2print, 0);
+ }
+}
+
+/*
+ * 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
+mygenregs(NODE *p)
+{
+ if (p->n_op == MINUS && p->n_type == DOUBLE &&
+ (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) {
+ p->n_su |= DORIGHT;
+ }
+ /* Must walk down correct node first for logops to work */
+ if (p->n_op != CBRANCH)
+ return;
+ p = p->n_left;
+ if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG))
+ return;
+ p->n_su &= ~DORIGHT;
+}
+
+/*
+ * Remove last goto.
+ */
+void
+myoptim(struct interpass *ip)
+{
+#if 0
+ while (ip->sqelem.sqe_next->type != IP_EPILOG)
+ ip = ip->sqelem.sqe_next;
+ if (ip->type != IP_NODE || ip->ip_node->n_op != GOTO)
+ comperr("myoptim");
+ tfree(ip->ip_node);
+ *ip = *ip->sqelem.sqe_next;
+#endif
+}
+
+struct hardops hardops[] = {
+ { MUL, LONGLONG, "__muldi3" },
+ { MUL, ULONGLONG, "__muldi3" },
+ { DIV, LONGLONG, "__divdi3" },
+ { DIV, ULONGLONG, "__udivdi3" },
+ { MOD, LONGLONG, "__moddi3" },
+ { MOD, ULONGLONG, "__umoddi3" },
+ { RS, LONGLONG, "__ashrdi3" },
+ { RS, ULONGLONG, "__lshrdi3" },
+ { LS, LONGLONG, "__ashldi3" },
+ { LS, ULONGLONG, "__ashldi3" },
+#if 0
+ { STASG, PTR+STRTY, "memcpy" },
+ { STASG, PTR+UNIONTY, "memcpy" },
+#endif
+ { 0 },
+};
+
+void
+rmove(int s, int d, TWORD t)
+{
+ printf(" move %s, %s\n", rnames[d], rnames[s]);
+}
+
+
+
diff --git a/usr.bin/pcc/arch/mips/macdefs.h b/usr.bin/pcc/arch/mips/macdefs.h
new file mode 100644
index 00000000000..87534a64660
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/macdefs.h
@@ -0,0 +1,227 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ * Assume: If only one value; store at left side (char size), otherwise
+ * treat it as an integer.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT 64 /* # bits above fp where arguments start */
+#define AUTOINIT 0 /* # bits below fp where automatics start */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 96
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 32
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 32
+#define ALLDOUBLE 32
+#define ALLONG 32
+#define ALLONGLONG 32
+#define ALSHORT 16
+#define ALPOINT 32
+#define ALSTRUCT 32
+#define ALSTACK 32
+
+/*
+ * 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
+
+/* Default char is unsigned */
+#undef CHAR_UNSIGNED
+
+/*
+ * Use large-enough types.
+ */
+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 */
+#ifdef FORTRAN
+#define XL 8
+#define FLABELFMT "%s:\n"
+#define USETEXT ".text"
+#define USECONST ".data\t0" /* XXX - fix */
+#define USEBSS ".data\t1" /* XXX - fix */
+#define USEINIT ".data\t2" /* XXX - fix */
+#define MAXREGVAR 3 /* XXX - fix */
+#define BLANKCOMMON "_BLNK_"
+#define MSKIREG (M(TYSHORT)|M(TYLONG))
+#define TYIREG TYLONG
+#define FSZLENG FSZLONG
+#define FUDGEOFFSET 1
+#define AUTOREG EBP
+#define ARGREG EBP
+#define ARGOFFSET 4
+#endif
+
+#define BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+/* Definitions mostly used in pass2 */
+
+#define BYTEOFF(x) ((x)&03)
+#define wdal(k) (BYTEOFF(k)==0)
+#define BITOOR(x) ((x)/SZCHAR) /* bit offset to oreg offset */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+#define genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
+
+/*
+ * Register names. These must match rnames[] and rstatus[] in local2.c.
+ * The crazy order of the registers are due to the current register
+ * allocations strategy and should be fixed.
+ */
+#define T0 0
+#define T1 1
+#define T2 2
+#define T3 3
+#define T4 4
+#define T5 5
+#define T6 6
+#define T7 7
+#define T8 8
+#define T9 9
+
+#define V0 10
+#define V1 11
+
+#define ZERO 12
+#define AT 13
+
+#define A0 14
+#define A1 15
+#define A2 16
+#define A3 17
+
+#define S0 18
+#define S1 19
+#define S2 20
+#define S3 21
+#define S4 22
+#define S5 23
+#define S6 24
+#define S7 25
+
+#define K0 26
+#define K1 27
+
+#define GP 28
+#define SP 29
+#define FP 30
+#define RA 31
+
+#define RETREG V0 /* Return register */
+#define REGSZ 32 /* number of registers */
+#define FPREG FP /* frame pointer */
+#define STKREG SP /* stack pointer */
+#define MINRVAR S0 /* first register variable */
+#define MAXRVAR S7 /* last register variable */
+
+#define NREGREG (MAXRVAR-MINRVAR+1)
+
+/*
+ * Register types are described by bitmasks.
+ */
+#define AREGS (REGBIT(T0)|REGBIT(T1)|REGBIT(T2)|REGBIT(T3)| \
+ REGBIT(T4)|REGBIT(T5)|REGBIT(T6)|REGBIT(T7)|REGBIT(T8)|REGBIT(T9)|\
+ REGBIT(V0)|REGBIT(V1)|REGBIT(A0)|REGBIT(A1)|REGBIT(A2)|REGBIT(A3)|\
+ REGBIT(S0)|REGBIT(S1)|REGBIT(S2)|REGBIT(S3)|REGBIT(S4)|REGBIT(S5)|\
+ REGBIT(S6)|REGBIT(S7))
+#define TAREGS (REGBIT(T0)|REGBIT(T1)|REGBIT(T2)|REGBIT(T3)|REGBIT(T4)|\
+ REGBIT(T5)|REGBIT(T6)|REGBIT(T7)|REGBIT(T8)|REGBIT(T9)|\
+ REGBIT(V0)|REGBIT(V1))
+
+/* For floating point? */
+#define BREGS 0xff00
+#define TBREGS BREGS
+
+//#define MYADDEDGE(x, t) if (t < INT) { AddEdge(x, ESI); AddEdge(x, EDI); }
+#define MYADDEDGE(x, t)
+#define PCLASS(p) SAREG
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+
+#define special(a, b) SRNOPE
diff --git a/usr.bin/pcc/arch/mips/order.c b/usr.bin/pcc/arch/mips/order.c
new file mode 100644
index 00000000000..2173d8db624
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/order.c
@@ -0,0 +1,350 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:27 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+# include "pass2.h"
+
+int canaddr(NODE *);
+
+/* should we delay the INCR or DECR operation p */
+int
+deltest(NODE *p)
+{
+ return 0;
+}
+
+/*
+ * Check if p can be autoincremented.
+ * XXX - nothing can be autoincremented for now.
+ */
+int
+autoincr(NODE *p)
+{
+ return 0;
+}
+
+/* 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.
+ */
+int
+offstar(NODE *p)
+{
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if( p->n_op == PLUS || p->n_op == MINUS ){
+ if( p->n_right->n_op == ICON ){
+ geninsn(p->n_left, INTAREG|INAREG);
+ p->n_su = -1;
+ return 1;
+ }
+ }
+ geninsn(p, INTAREG|INAREG);
+ return 0;
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p)
+{
+
+ if (x2debug)
+ printf("shumul(%p)\n", p);
+
+ /* Always turn it into OREG on x86 */
+ 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)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+/*
+ * Special handling of some instruction register allocation.
+ * - left is the register that left node wants.
+ * - right is the register that right node wants.
+ * - res is in which register the result will end up.
+ * - mask is registers that will be clobbered.
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ static int v0[] = { V0, -1 };
+ static int v0v1[] = { V0, V1, -1 };
+
+ static struct rspecial ucall = { v0, 0, v0v1, v0 };
+
+ switch (q->op) {
+
+ default:
+ comperr("nspecial entry %d", q - table);
+ }
+ return 0; /* XXX gcc */
+}
+
+/*
+ * Splitup a function call and give away its arguments first.
+ */
+void
+gencall(NODE *p, NODE *prev)
+{
+ NODE *n = 0; /* XXX gcc */
+ static int storearg(NODE *);
+ int o = p->n_op;
+ int ty = optype(o);
+
+ if (ty == LTYPE)
+ return;
+
+ switch (o) {
+ case CALL:
+ /* Normal call, just push args and be done with it */
+ p->n_op = UCALL;
+
+ gencall(p->n_left, p);
+ p->n_rval = storearg(p->n_right);
+
+ break;
+
+ case UFORTCALL:
+ case FORTCALL:
+ comperr("FORTCALL");
+
+ case USTCALL:
+ case STCALL:
+ /*
+ * Structure return. Look at the node above
+ * to decide about buffer address:
+ * - FUNARG, allocate space on stack, don't remove.
+ * - nothing, allocate space on stack and remove.
+ * - STASG, get the address of the left side as arg.
+ * - FORCE, this ends up in a return, get supplied addr.
+ * (this is not pretty, but what to do?)
+ */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ /* Create nodes to generate stack space */
+ n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT),
+ mkbinode(MINUS, mklnode(REG, 0, STKREG, INT),
+ mklnode(ICON, p->n_stsize, 0, INT), INT), INT);
+ //printf("stsize %d\n", p->n_stsize);
+ pass2_compile(ipnode(n));
+ } else if (prev->n_op == STASG) {
+ n = prev->n_left;
+ if (n->n_op == UMUL)
+ n = nfree(n);
+ else if (n->n_op == NAME) {
+ n->n_op = ICON; /* Constant reference */
+ n->n_type = INCREF(n->n_type);
+ } else
+ comperr("gencall stasg");
+ } else if (prev->n_op == FORCE) {
+ ; /* do nothing here */
+ } else {
+ comperr("gencall bad op %d", prev->n_op);
+ }
+
+ /* Deal with standard arguments */
+ gencall(p->n_left, p);
+ if (o == STCALL) {
+ p->n_op = USTCALL;
+ p->n_rval = storearg(p->n_right);
+ } else
+ p->n_rval = 0;
+ /* push return struct address */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ n = mklnode(REG, 0, STKREG, INT);
+ if (p->n_rval)
+ n = mkbinode(PLUS, n,
+ mklnode(ICON, p->n_rval, 0, INT), INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ if (prev == NULL)
+ p->n_rval += p->n_stsize/4;
+ } else if (prev->n_op == FORCE) {
+ /* return value for this function */
+ n = mklnode(OREG, 8, FPREG, INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ p->n_rval++;
+ } else {
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ n = p;
+ *prev = *p;
+ nfree(n);
+ }
+ //printf("end stcall\n");
+ break;
+
+ default:
+ if (ty != UTYPE)
+ gencall(p->n_right, p);
+ gencall(p->n_left, p);
+ break;
+ }
+}
+
+/*
+ * Create separate node trees for function arguments.
+ * Returns the number of registers needed to hold the argument.
+ */
+static int
+storearg(NODE *p)
+{
+ static void storecall(NODE *);
+ struct interpass *ip;
+ NODE *np;
+ int tsz, recval;
+ TWORD t;
+ extern int thisline;
+ static int counter = 0; /* Count number of register arguments */
+
+ ip = tmpalloc(sizeof(struct interpass));
+ ip->type = IP_NODE;
+ ip->lineno = thisline;
+
+ if (p->n_op == CM) {
+ np = p->n_left;
+
+ if (p->n_right->n_op == STARG) {
+ NODE *op = p;
+ p = p->n_right;
+ nfree(op);
+ tsz = (p->n_stsize + 3) / 4;
+ } else {
+ p->n_type = p->n_right->n_type;
+ p->n_left = p->n_right;
+
+
+ /* Process left subtree first, to get arguments in the correct
+ order on the stack as well as in the registers. */
+ recval = storearg(np);
+
+ /* Not a register argument */
+ if (!(counter < 4)) {
+ p->n_op = FUNARG;
+ ip->ip_node = p;
+ pass2_compile(ip);
+ tsz = szty(p->n_type);
+
+ } else { /* Else fetch value from stack to register */
+ t = p->n_type;
+
+ pass2_compile(ipnode(mkbinode(ASSIGN,
+ mklnode(REG, 0, A0+counter, t),
+ p->n_right, t)));
+ tsz = 0;
+ counter++;
+
+ /* Free the comma node */
+ nfree(p);
+
+ }
+ }
+
+ return recval + tsz;
+ } else {
+ if (p->n_op != STARG) {
+ /* Register argument */
+ if (counter < 4) {
+ t = p->n_type;
+
+ pass2_compile(ipnode(mkbinode(ASSIGN,
+ mklnode(REG, 0, A0+counter, t),
+ p, t)));
+ counter++;
+
+ return 0;
+ } else {
+ np = talloc();
+
+ np->n_type = p->n_type;
+ np->n_op = FUNARG;
+ np->n_left = p;
+ p = np;
+ tsz = szty(p->n_type);
+ }
+ } else {
+ p->n_op = FUNARG;
+ tsz = (p->n_stsize + 3) / 4;
+ }
+ ip->ip_node = p;
+ pass2_compile(ip);
+ return tsz;
+ }
+}
diff --git a/usr.bin/pcc/arch/mips/table.c b/usr.bin/pcc/arch/mips/table.c
new file mode 100644
index 00000000000..e7d10ad1fe7
--- /dev/null
+++ b/usr.bin/pcc/arch/mips/table.c
@@ -0,0 +1,776 @@
+/* $Id: table.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
+ * Simon Olsson (simols-1@student.ltu.se) 2005.
+ */
+
+# 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
+
+struct optab table[] = {
+/* First entry must be an empty entry */
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
+
+
+/*
+ * A bunch conversions of integral<->integral types
+ */
+
+
+
+
+
+
+/* convert char to (u)short */
+{ SCONV, INTAREG,
+ SOREG, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " lb A1, ZA\n nop\n", },
+
+/* convert uchar to (u)short */
+{ SCONV, INTAREG,
+ SOREG, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " lbu A1, ZA\n nop\n", },
+
+/* convert char to (u)long */
+{ SCONV, INTAREG,
+ SOREG, TCHAR,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " lb A1, ZA\n nop\n", },
+
+/* convert uchar to (u)long */
+{ SCONV, INTAREG,
+ SOREG, TUCHAR,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " lbu A1, ZA\n nop\n", },
+
+/* convert char to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TCHAR,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lb U1, ZA\n"
+ " nop\n"
+ " sra A1, U1, 31\n"
+ " sub A1, $zero, A1\n", },
+
+/* convert uchar to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TUCHAR,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lbu U1, ZA\n"
+ " move A1, $zero\n", },
+
+
+
+
+
+/* convert (u)short to char */
+{ SCONV, INTAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " lb A1, ZA\n nop\n", },
+
+/* convert (u)short to uchar */
+{ SCONV, INTAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TUCHAR,
+ NAREG, RESC1,
+ " lbu A1, ZA\n nop\n", },
+
+
+/* convert short to (u)long */
+{ SCONV, INTAREG,
+ SOREG, TSHORT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " lh A1, ZA\n nop\n", },
+
+/* convert ushort to (u)long */
+{ SCONV, INTAREG,
+ SOREG, TUSHORT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " lhu A1, ZA\n nop\n", },
+
+/* convert short to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TSHORT,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lh U1, ZA\n"
+ " nop\n"
+ " sra A1, U1, 31\n"
+ " sub A1, $zero, A1\n", },
+
+/* convert ushort to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TUSHORT,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lhu U1, ZA\n"
+ " move A1, $zero\n", },
+
+
+
+
+
+/* convert (u)long to char */
+{ SCONV, INTAREG,
+ SOREG, TWORD,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " lb A1, ZA\n nop\n", },
+
+/* convert (u)long to uchar */
+{ SCONV, INTAREG,
+ SOREG, TWORD,
+ SAREG, TUCHAR,
+ NAREG, RESC1,
+ " lbu A1, ZA\n nop\n", },
+
+/* convert (u)long to short */
+{ SCONV, INTAREG,
+ SOREG, TWORD,
+ SAREG, TSHORT,
+ NAREG, RESC1,
+ " lh A1, ZA\n nop\n", },
+
+/* convert (u)long to ushort */
+{ SCONV, INTAREG,
+ SOREG, TWORD,
+ SAREG, TUSHORT,
+ NAREG, RESC1,
+ " lhu A1, ZA\n nop\n", },
+
+/* convert long to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TSWORD,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lw U1, ZA\n"
+ " nop\n"
+ " sra A1, U1, 31\n"
+ " sub A1, $zero, A1\n", },
+
+/* convert ulong to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TUWORD,
+ SAREG, TLL,
+ NAREG, RESC1,
+ " lw U1, ZA\n"
+ " move A1, $zero\n", },
+
+
+
+
+
+/* convert (u)long long to char */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " lb A1, ZA\n nop\n", },
+
+/* convert (u)long long to uchar */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TUCHAR,
+ NAREG, RESC1,
+ " lbu A1, ZA\n nop\n", },
+
+/* convert (u)long long to short */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TSHORT,
+ NAREG, RESC1,
+ " lh A1, ZA\n nop\n", },
+
+/* convert (u)long long to ushort */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TUSHORT,
+ NAREG, RESC1,
+ " lhu A1, ZA\n nop\n", },
+
+/* convert (u)long long to long */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TSWORD,
+ NAREG, RESC1,
+ " lw U1, ZA\n nop\n", },
+
+/* convert (u)long long to (u)long long */
+{ SCONV, INTAREG,
+ SOREG, TLL,
+ SAREG, TUWORD,
+ NAREG, RESC1,
+ " lwu U1, ZA\n nop\n", },
+
+
+
+
+
+
+
+/* Register to register conversion with long long */
+
+{ SCONV, INTAREG,
+ SAREG, TLL,
+ SAREG, TLL,
+ 0, 0,
+ "", },
+
+{ SCONV, INTAREG,
+ SAREG, TPOINT|TWORD|SHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TLL,
+ NAREG, 0,
+ "move A1, AR\n"
+ "move U1, $zero\n", },
+
+{ SCONV, INTAREG,
+ SAREG, TLL,
+ SAREG, TPOINT|TWORD|SHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG, 0,
+ "move A1, AL\n", },
+
+
+
+
+/* For register to register conversion with bit length <= 32, do nothing */
+
+{ SCONV, INTAREG,
+ SAREG, TPOINT|TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TPOINT|TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, 0,
+ "", },
+
+
+
+
+
+
+/*
+ * Multiplication and division
+ */
+
+{ MUL, INAREG|FOREFF,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " mult AL, AR\n mflo A1\n nop\n nop\n", },
+
+{ MUL, INAREG|FOREFF,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " multu AL, AR\n mflo A1\n nop\n nop\n", },
+
+{ DIV, INAREG|FOREFF,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " div AL, AR\n mflo A1\n nop\n nop\n", },
+
+{ DIV, INAREG|FOREFF,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " divu AL, AR\n mflo A1\n nop\n nop\n", },
+
+/*
+ * Templates for unsigned values needs to come before OPSIMP
+ */
+
+{ PLUS, INAREG|FOREFF,
+ SAREG, TLL,
+ SAREG, TLL,
+ 3*NAREG, RESC3,
+ " addu A1, AL, AR\n"
+ " sltu A2, A1, AR\n"
+ " addu A3, UL, UR\n"
+ " addu A3, A3, A2\n", },
+
+{ PLUS, INAREG|FOREFF,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SCON, TUSHORT|TSHORT|TCHAR|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " addiu A1, AL, AR\n", },
+
+ /*
+{ PLUS, INAREG|FOREFF,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " addu A1, AL, AR\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " subu A1, AL, AR\n", },
+ */
+
+{ MINUS, INAREG|FOREFF,
+ SAREG, TLL,
+ SAREG, TLL,
+ NAREG|NASR|NASL, RESC1,
+ " sltu A1, AL, AR\n"
+ " subu AR, AL, AR\n"
+ " subu UR, UL, UR\n"
+ " subu UR, UR, A1\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SCON, TUSHORT|TSHORT|TCHAR|TUCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " subiu A1, AL, AR\n", },
+
+
+{ UMINUS, INAREG|FOREFF|INTAREG,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " neg A1, AL\n", },
+
+
+/* Simple 'op rd, rs, rt' or 'op rt, rs, imm' operations */
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TLL,
+ SAREG, TLL,
+ NAREG|NASR|NASL, RESC1,
+ " O A1, AL, AR\n"
+ " O U1, UL, UR\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " O A1, AL, AR\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
+ SCON, TSHORT|TUSHORT|TUCHAR|TCHAR,
+ NAREG|NASR|NASL, RESC1,
+ " Oi A1, AL, AR\n", },
+
+/*
+ * Shift instructions
+ */
+
+ /* order.c SPECIAL
+{ RS, INAREG|INTAREG|FOREFF,
+ SAREG, TWORD|TUSHORT|TSHORT|TCHAR|TUCHAR,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " srl A1, AL, AR\n", },
+
+{ LS, INAREG|INTAREG|FOREFF,
+ SAREG, TWORD|TUSHORT|TSHORT|TCHAR|TUCHAR,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sll A1, AL, AR\n", },
+ */
+
+{ RS, INAREG|INTAREG|FOREFF,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " srlv A1, AL, AR\n", },
+
+{ LS, INAREG|INTAREG|FOREFF,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sllv A1, AL, AR\n", },
+
+/*
+ * Rule for unary one's complement
+ */
+
+{ COMPL, INTAREG,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " not A1, AL\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+
+{ ASSIGN, INTAREG,
+ SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RRIGHT,
+ " sw AR, AL\n", },
+
+{ ASSIGN, INTAREG,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RRIGHT,
+ " sh AR, AL\n", },
+
+{ ASSIGN, INTAREG,
+ SOREG, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ 0, RRIGHT,
+ " sb AR, AL\n", },
+
+{ ASSIGN, INTAREG,
+ SOREG, TLL,
+ SAREG, TLL,
+ 0, RRIGHT,
+ " sw UR, UL\n"
+ " sw AR, AL\n", },
+
+{ ASSIGN, INTAREG, // XXX: Funkar ej A1 == AR
+ SNAME, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ NAREG, RRIGHT,
+ " la A1, AL\n sw AR, 0(A1)\n", },
+
+{ ASSIGN, INTAREG,
+ SNAME, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RRIGHT,
+ " la A1, AL\n sh AR, 0(A1)\n", },
+
+{ ASSIGN, INTAREG,
+ SNAME, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ NAREG, RRIGHT,
+ " la A1, AL\n sb AR, 0(A1)\n", },
+
+{ ASSIGN, INTAREG,
+ SNAME, TLL,
+ SAREG, TLL,
+ 0, RRIGHT,
+ " sw UR, UL\n"
+ " sw AR, AL\n", },
+
+{ ASSIGN, INTAREG,
+ SAREG, TLL,
+ SAREG, TLL,
+ 0, RRIGHT,
+ " move UR, UL\n"
+ " move AR, AL\n", },
+
+{ ASSIGN, INTAREG|FOREFF,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RLEFT,
+ " move AL, AR\n", },
+
+#if 0
+/* XXX - Stupid rule, shouldn't exist */
+{ ASSIGN, INTAREG,
+ SANY, TANY,
+ SAREG, TANY,
+ 0, RLEFT,
+ " move AL, AR\n", },
+#endif
+
+/*
+ * Compare instructions
+ */
+
+{ EQ, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " ZQ\n", },
+
+{ NE, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " ZQ\n", },
+
+{ LE, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub A1, AL, AR\n ZQ\n", },
+
+{ LT, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub A1, AL, AR\n ZQ\n", },
+
+{ GE, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub A1, AL, AR\n ZQ\n", },
+
+{ GT, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ NAREG|NASL, RESCC,
+ " sub A1, AL, AR\n ZQ\n", },
+
+
+/*
+ * Convert LTYPE to reg.
+ */
+
+
+/* from OREG to REG */
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TCHAR,
+ NAREG, RESC1,
+ " lb A1,AR\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TUCHAR,
+ NAREG, RESC1,
+ " lbu A1,AR\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TSHORT,
+ NAREG, RESC1,
+ " lh A1,AR\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TUSHORT,
+ NAREG, RESC1,
+ " lhu A1,AR\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TWORD|TPOINT,
+ NAREG, RESC1,
+ " lw A1, AR\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SOREG, TLL,
+ NAREG, RESC1,
+ " lw U1, UR\n"
+ " lw A1, AR\n"
+ " nop\n", },
+
+/* from NAME to REG */
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TCHAR,
+ 2*NAREG, RESC1,
+ " la A2, AR\n lb A1, 0(A2)\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TUCHAR,
+ 2*NAREG, RESC1,
+ " la A2, AR\n lbu A1, 0(A2)\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TSHORT,
+ 2*NAREG, RESC1,
+ " la A2, AR\n lh A1, 0(A2)\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TUSHORT,
+ 2*NAREG, RESC1,
+ " la A2, AR\n lhu A1, 0(A2)\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TWORD|TPOINT,
+ 2*NAREG, RESC1,
+ " la A2, AR\n lw A1, 0(A2)\n nop\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SNAME, TLL,
+ 2*NAREG, RESC1,
+ " la A2, UR\n"
+ " lw U1, 0(A2)\n"
+ " la A2, AR\n"
+ " lw A1, 0(A2)\n"
+ " nop\n", },
+
+/* from CON to REG */
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SCON, TPOINT,
+ NAREG, RESC1,
+ " la A1, AR\n", },
+
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SCON, TANY,
+ NAREG, RESC1,
+ " li A1, AR\n", },
+
+#if 0
+/* Matches REG nodes. XXX - shouldn't be necessary? */
+{ OPLTYPE, INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ NAREG, RESC1,
+ " move A1, AR\n", },
+#endif
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " j LL\n nop\n", },
+
+/*
+ * Subroutine calls.
+ */
+
+{ UCALL, INTAREG|FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG, RESC1,
+ " addi $sp, $sp, -16\n jal AL\n nop\nZC\n", },
+
+/* struct return */
+{ USTCALL, INTAREG|FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+/*
+ * Function arguments
+ */
+
+
+{ FUNARG, FOREFF,
+ SAREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ 0, RNULL,
+ " addi $sp, $sp, -4\n sw AL, 0($sp)\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TSHORT|TUSHORT,
+ 0, RNULL,
+ " addi $sp, $sp, -4\n sh AL, 0($sp)\n", },
+{ FUNARG, FOREFF,
+ SAREG, TCHAR|TUCHAR,
+ SANY, TCHAR|TUCHAR,
+ 0, RNULL,
+ " addi $sp, $sp, -4\n sb AL, 0($sp)\n", },
+
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INTAREG,
+ SOREG, TPOINT|TWORD|TPTRTO,
+ SANY, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " lw A1, AL\n nop\n", },
+
+{ UMUL, INTAREG,
+ SOREG, TSHORT|TUSHORT|TPTRTO,
+ SANY, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " lh A1, AL\n nop\n", },
+
+{ UMUL, INTAREG,
+ SOREG, TCHAR|TUCHAR|TPTRTO,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " lb A1, AL\n nop\n", },
+
+{ UMUL, INTAREG,
+ SNAME, TPOINT|TWORD|TPTRTO,
+ SANY, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " la A1, AL\n lw A1, 0(A1)\n nop\n", },
+
+{ UMUL, INTAREG,
+ SNAME, TSHORT|TUSHORT|TPTRTO,
+ SANY, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " la A1, AL\n lh A1, 0(A1)\n nop\n", },
+
+{ UMUL, INTAREG,
+ SNAME, TCHAR|TUCHAR|TPTRTO,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " la A1, AL\n lb A1, 0(A1)\n nop\n", },
+
+{ UMUL, INTAREG,
+ SAREG, TPOINT|TWORD|TPTRTO,
+ SANY, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " lw A1, 0(AL)\n nop\n", },
+
+{ UMUL, INTAREG,
+ SAREG, TSHORT|TUSHORT|TPTRTO,
+ SANY, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " lh A1, 0(AL)\n nop\n", },
+
+{ UMUL, INTAREG,
+ SAREG, TCHAR|TUCHAR|TPTRTO,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " lb A1, 0(AL)\n nop\n", },
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
diff --git a/usr.bin/pcc/arch/nova/README b/usr.bin/pcc/arch/nova/README
new file mode 100644
index 00000000000..939f8061c2a
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/README
@@ -0,0 +1,120 @@
+Calling conventions, stack frame and zero page:
+
+The variables that normally are placed on the stack or in registers in C
+are instead allocated in the zero page and saved on a (fictive) stack
+when calling functions. Some locations have predefined functions though.
+Arrays allocated as automatics are stored on the stack with a pointer
+in zero page to its destination.
+
+0-7 Unused
+10 Stack pointer
+11 Frame pointer
+12-14 Unused
+15 Used by prolog
+16 Prolog address, written in crt0
+17 Epilog address, written in crt0
+20-27 Auto-increment, scratch
+30-37 Auto-decrement, scratch
+40-47 Unused
+50-57 Scratch/Arguments
+60-77 Permanent, save before use.
+100-377 Addresses for subroutines, written by the assembler
+
+The normal registers (AC0-AC3) are all considered scratch registers.
+
+Register classes are assigned as:
+ AC0-AC3: AREGs.
+ AC2-AC3: BREGs.
+ 50-77: CREGs.
+ ...and eventually register pairs as DREGs.
+
+In byte code the low half of a word is the first byte (little-endian).
+This is bit 8-15 in Nova syntax.
+
+The stack is growing towards lower adresses (as opposed to the Eclipse stack).
+Stack layout:
+
+ ! arg1 !
+ ! arg0 !
+ fp -> ! old pc!
+ ! old fp!
+ pc -> ! saved !
+
+A reference to a struct member in assembler, a = b->c; b is in ZP 50
++ is zeropage-addressing
+* is fp-adressing
+
+# offset 0
++ lda 0,@50 # load value from indirect ZP 50 into ac0
+* lda 2,,3 # load value from (ac3) into ac2
+* lda 0,,2 # load value from (ac2) into ac0
+
+# offset 12
++ lda 2,50 # load value from ZP 50 into ac2
++ lda 0,12,2 # load value from (ac2+12) into ac0
+* lda 2,,3 # load value from (ac3) into ac2
+* lda 0,12,2 # load value from 12(ac2) into ac0
+
+# offset 517
++ lda 2,50 # load value from ZP 50 into ac2
++ lda 0,.L42-.,1 # load offset from .L42 PC-indexed
++ addz 0,2,skp # add offset to ac2 and skip
++.L42: .word 517 # offset value
++ lda 0,,2 # load value from (ac2) into ac0
+
+The prolog/epilog implementation; it is implemented as subroutines.
+
+.L42: .word 13 # number of words to save
+func:
+ sta 3,@40 # save return address on stack
+ lda 2,.L42-.,1 # get save word count
+ jsr @45 # go to prolog
+ ...
+ lda 2,.L42-.,1 # get restore word count
+ jmp @46 # jump to epilog
+
+# words to save in 2, return address in 3
+prolog:
+ sta 2,45 # save # of words to move at scratch
+ lda 0,41 # get old fp
+ lda 1,40 # get sp
+ sta 1,41 # save new fp
+ dsz 40 # decrement stack, will never be 0
+ sta 0,@40 # save old fp
+ dsz 40
+
+ lda 0,off57 # fetch address of regs to save - 1
+ sta 0,20 # store address at autoincr
+1: lda 0,@20 # get word to copy
+ sta 0,@40 # push on stack
+ dsz 40 # manually decrement sp
+ dsz 45 # copied all words?
+ jmp 1b,1 # no, continue
+ jmp 0,3 # return
+
+epilog:
+ sta 2,45 # save # of words to move at scratch
+
+ lda 3,off57 # fetch address of regs to save
+ sta 3,20 # store at autoincr
+ lda 3,41 # fetch fp
+ sta 3,30 # store at autodecr
+ lda 3,@30 # get old fp
+
+1: lda 2,@30 # fetch word from stack
+ sta 2,@20 # store at orig place
+ dsz 45 # enough?
+ jmp 1b,1 # no, continue
+
+ lda 2,41 # get new fp
+ sta 2,40 # restore stack
+ sta 3,41 # restore old fp
+ jmp @40 # Return
+
+Assembler syntax and functions.
+
+The assembler syntax mimics the DG assembler.
+Load and store to addresses is written "lda 0,foo" to load from address foo.
+If foo is not in zero page then the assembler will put the lda in the
+text area close to the instruction and do an indirect pc-relative load.
+
diff --git a/usr.bin/pcc/arch/nova/code.c b/usr.bin/pcc/arch/nova/code.c
new file mode 100644
index 00000000000..78bcdd4d4be
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/code.c
@@ -0,0 +1,212 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass1.h"
+
+/*
+ * cause the alignment to become a multiple of n
+ * never called for text segment.
+ */
+void
+defalign(int n)
+{
+ /* alignment are always correct */
+}
+
+/*
+ * 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(" .globl %s\n", c);
+ printf("%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;
+cerror("efcode");
+ /* address of return struct is in eax */
+ /* create a call to memcpy() */
+ /* will get the result in eax */
+ p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+// p->n_rval = EAX;
+ q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+// q->n_rval = EBP;
+ 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;
+cerror("bfcode");
+ /* 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 flag )
+{
+}
+
+void
+bjobcode()
+{
+}
+
+/*
+ * 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(" .zero %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);
+}
diff --git a/usr.bin/pcc/arch/nova/local.c b/usr.bin/pcc/arch/nova/local.c
new file mode 100644
index 00000000000..61ccb9429e9
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/local.c
@@ -0,0 +1,618 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * 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"
+
+/* this file contains code which is dependent on the target machine */
+
+NODE *
+clocal(NODE *p)
+{
+ struct symtab *q;
+ NODE *r, *l;
+ int o;
+
+ switch( o = p->n_op ){
+ case NAME:
+ /* handle variables */
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+ switch (q->sclass) {
+ 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;
+ default:
+ break;
+ }
+ 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 PCONV:
+ l = p->n_left;
+ /* 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;
+ }
+
+#if 0
+ register struct symtab *q;
+ register NODE *r, *l;
+ register int o;
+ register int m;
+ TWORD t;
+
+//printf("in:\n");
+//fwalk(p, eprint, 0);
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ 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 STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ 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)
+ 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;
+ /* 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);
+ return l;
+ }
+
+ 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 == NAME || l->n_op == UMUL ||
+ l->n_op == TEMP) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ }
+ }
+
+ if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
+ coptype(l->n_op) == BITYPE) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+
+ 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 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;
+ return p;
+ }
+ 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 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, 0, MKSUE(INT));
+ p->n_left->n_rval = RETREG(p->n_type);
+ break;
+
+ case LS:
+ case RS:
+ /* shift count must be in a char
+ * unless longlong, where it must be int */
+ if (p->n_right->n_op == ICON)
+ break; /* do not do anything */
+ if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
+ if (p->n_right->n_type != INT)
+ p->n_right = block(SCONV, p->n_right, NIL,
+ INT, 0, MKSUE(INT));
+ break;
+ }
+ if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
+ break;
+ p->n_right = block(SCONV, p->n_right, NIL,
+ CHAR, 0, MKSUE(CHAR));
+ break;
+ }
+//printf("ut:\n");
+//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; /* try to put anything in a register */
+}
+
+/*
+ * 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 nova, return the type-specific index number which calculation
+ * is based on its size. For example, char 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 %ld type %x dim %p siz %d\n",
+ off, t, d, sue->suesize);
+
+ p = bcon(0);
+ p->n_lval = off/SZINT; /* Default */
+ if (ISPTR(DECREF(t)))
+ return p;
+ if (t == VOID || t == CHAR || t == UCHAR)
+ p->n_lval = off/SZCHAR; /* pointer to char */
+ return(p);
+}
+
+/*
+ * Allocate off bits on the stack. p is a tree that when evaluated
+ * is the multiply count for off, t is a NAME node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+cerror("spalloc");
+ if ((off % SZINT) == 0)
+ p = buildtree(MUL, p, bcon(off/SZINT));
+ else if ((off % SZSHORT) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZSHORT));
+ p = buildtree(PLUS, p, bcon(1));
+ p = buildtree(RS, p, bcon(1));
+ } else if ((off % SZCHAR) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZCHAR));
+ p = buildtree(PLUS, p, bcon(3));
+ p = buildtree(RS, p, bcon(2));
+ } else
+ cerror("roundsp");
+
+ /* 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! */
+
+ /* add the size to sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, 0);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(PLUSEQ, sp, p));
+}
+
+/*
+ * print out a constant node
+ * mat be associated with a label
+ */
+void
+ninval(NODE *p)
+{
+ struct symtab *q;
+ TWORD t;
+
+ p = p->n_left;
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ if (p->n_op != ICON)
+ cerror("ninval: init node not constant");
+
+ switch (t) {
+ case LONG:
+ case ULONG:
+ inval(p->n_lval & 0xffff);
+ inval(p->n_lval >> 16);
+ break;
+ case INT:
+ case UNSIGNED:
+ printf("\t.word 0%o", (short)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;
+ default:
+ cerror("ninval");
+ }
+}
+
+/*
+ * print out an integer.
+ */
+void
+inval(CONSZ word)
+{
+ word &= 0xffff;
+ printf(" .word 0%o\n", (int)word);
+}
+
+/* output code to initialize a floating point value */
+/* the proper alignment has been obtained */
+void
+finval(NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+
+cerror("finval");
+ switch (p->n_type) {
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+ break;
+ 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;
+ }
+}
+
+/* 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 LONGLONG:
+ MODTYPE(type,LONG);
+ break;
+
+ case ULONGLONG:
+ MODTYPE(type,ULONG);
+ break;
+ case SHORT:
+ MODTYPE(type,INT);
+ break;
+ case USHORT:
+ MODTYPE(type,UNSIGNED);
+ break;
+ }
+ return (type);
+}
+
+/* curid is a variable which is defined but
+ * is not initialized (and not a function );
+ * This routine returns the storage class for an uninitialized declaration
+ */
+int
+noinit()
+{
+ return(EXTERN);
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+/* 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(" .comm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .comm %s,0%o\n", exname(q->sname), off);
+#endif
+}
+
+/* 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(" .lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+ printf(" .%s\n", loctbl[locc]);
+}
diff --git a/usr.bin/pcc/arch/nova/local2.c b/usr.bin/pcc/arch/nova/local2.c
new file mode 100644
index 00000000000..93c2f843781
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/local2.c
@@ -0,0 +1,563 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+# include <ctype.h>
+# include <string.h>
+
+void acon(NODE *p);
+int argsize(NODE *p);
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int prolnum;
+static struct ldq {
+ struct ldq *next;
+ int val;
+ int lab;
+ char *name;
+} *ldq;
+
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int i, j;
+
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1)
+ if (i&1)
+ j++;
+ printf(".LP%d: .word 0%o\n", prolnum, j);
+ if (ipp->ipp_vis)
+ printf(" .globl %s\n", ipp->ipp_name);
+ printf("%s:\n", ipp->ipp_name);
+ printf(" sta 3,@40\n"); /* save ret pc on stack */
+ printf(" lda 2,.LP%d-.,1\n", prolnum);
+ printf(" jsr @45\n");
+ prolnum++;
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i, j;
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1)
+ if (i & 1)
+ j++;
+ printf(" lda 2,.LP%d-.,1\n", prolnum);
+ printf(" jmp @46\n");
+ printf(".LP%d: .word 0%o\n", prolnum, j);
+ prolnum++;
+ while (ldq) {
+ printf(".LP%d: .word 0%o", ldq->lab, ldq->val);
+ if (ldq->name && *ldq->name)
+ printf("+%s", ldq->name);
+ printf("\n");
+ ldq = ldq->next;
+ }
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+ char *str = 0;
+
+ switch (o) {
+ case PLUS:
+ str = "add";
+ break;
+ case MINUS:
+ str = "sub";
+ break;
+ case AND:
+ str = "and";
+ break;
+ case OR:
+ cerror("hopcode OR");
+ break;
+ case ER:
+ cerror("hopcode xor");
+ str = "xor";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+ printf("%s%c", str, f);
+}
+
+#if 0
+/*
+ * Return type size in bytes. Used by R2REGS, arg 2 to offset().
+ */
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(SZSHORT/SZCHAR);
+
+ case DOUBLE:
+ return(SZDOUBLE/SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ return(SZINT/SZCHAR);
+
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG/SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type)/SZCHAR;
+ }
+}
+#endif
+
+#if 0
+/*
+ * Assign to a bitfield.
+ * Clumsy at least, but what to do?
+ */
+static void
+bfasg(NODE *p)
+{
+ NODE *fn = p->n_left;
+ int shift = UPKFOFF(fn->n_rval);
+ int fsz = UPKFSZ(fn->n_rval);
+ int andval, tch = 0;
+
+ /* get instruction size */
+ switch (p->n_type) {
+ case CHAR: case UCHAR: tch = 'b'; break;
+ case SHORT: case USHORT: tch = 'w'; break;
+ case INT: case UNSIGNED: tch = 'l'; break;
+ default: comperr("bfasg");
+ }
+
+ /* put src into a temporary reg */
+ fprintf(stdout, " mov%c ", tch);
+ adrput(stdout, getlr(p, 'R'));
+ fprintf(stdout, ",");
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* AND away the bits from dest */
+ andval = ~(((1 << fsz) - 1) << shift);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+
+ /* AND away unwanted bits from src */
+ andval = ((1 << fsz) - 1);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* SHIFT left src number of bits */
+ if (shift) {
+ fprintf(stdout, " sal%c $%d,", tch, shift);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+ }
+
+ /* OR in src to dest */
+ fprintf(stdout, " or%c ", tch);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, ",");
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+}
+#endif
+
+#if 0
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+ FILE *fp = stdout;
+
+ fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
+ fprintf(fp, " pushl $%d\n", p->n_stsize);
+ expand(p, 0, " pushl AL\n");
+ expand(p, 0, " leal 8(%esp),A1\n");
+ expand(p, 0, " pushl A1\n");
+ fprintf(fp, " call memcpy\n");
+ fprintf(fp, " addl $12,%%esp\n");
+}
+#endif
+
+void
+zzzcode(NODE *p, int c)
+{
+ struct ldq *ld;
+
+ switch (c) {
+ case 'A': /* print out a skip ending if any numbers in queue */
+ if (ldq == NULL)
+ return;
+ printf(",skp\n.LP%d: .word 0%o", ldq->lab, ldq->val);
+ if (ldq->name && *ldq->name)
+ printf("+%s", ldq->name);
+ printf("\n");
+ ldq = ldq->next;
+ break;
+
+ case 'B': /* print a label for later load */
+ ld = tmpalloc(sizeof(struct ldq));
+ ld->val = p->n_lval;
+ ld->name = p->n_name;
+ ld->lab = prolnum++;
+ ld->next = ldq;
+ ldq = ld;
+ printf(".LP%d-.", ld->lab);
+ break;
+
+ case 'C': /* fix reference to external variable via indirection */
+ zzzcode(p->n_left, 'B');
+ break;
+
+ case 'D': /* fix reference to external variable via indirection */
+ zzzcode(p, 'B');
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+cerror("flshape");
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+#if 0
+ int r;
+
+ if (p->n_op == STARG )
+ p = p->n_left;
+
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
+
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return(0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
+
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
+
+ if (optype(p->n_op) != LTYPE)
+ return(0);
+ return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+ printf("$" CONFMT, val);
+}
+
+/*
+ * Conput should only be used by e2print on Nova.
+ */
+void
+conput(FILE *fp, NODE *p)
+{
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput, p %p", p);
+ }
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+ comperr("insput");
+}
+
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
+void
+upput(NODE *p, int size)
+{
+comperr("upput");
+#if 0
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+#endif
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+ /* output an address, with offsets, from p */
+
+ if (p->n_op == FLD)
+ p = p->n_left;
+
+ switch (p->n_op) {
+
+ case NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ printf("%d,%s", (int)p->n_lval, rnames[p->n_rval]);
+ return;
+
+ case ICON:
+ /* addressable value of the constant */
+ fputc('$', io);
+ conput(io, p);
+ return;
+
+ case MOVE:
+ case REG:
+ switch (p->n_type) {
+ case LONGLONG:
+ case ULONGLONG:
+ fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
+ rnames[p->n_rval][1], rnames[p->n_rval][2]);
+ break;
+ case SHORT:
+ case USHORT:
+ fprintf(io, "%%%s", &rnames[p->n_rval][2]);
+ break;
+ default:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ }
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+ comperr("cbgen");
+}
+
+void
+myreader(struct interpass *ipole)
+{
+ if (x2debug)
+ printip(ipole);
+}
+
+void
+mycanon(NODE *p)
+{
+}
+
+void
+myoptim(struct interpass *ip)
+{
+}
+
+void
+rmove(int s, int d, TWORD t)
+{
+ comperr("rmove");
+}
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ * Return true if we always can find a color.
+ */
+int
+COLORMAP(int c, int *r)
+{
+ int num;
+
+ switch (c) {
+ case CLASSA:
+ num = r[CLASSB] + r[CLASSA];
+ return num < 4;
+ case CLASSB:
+ num = r[CLASSB] + r[CLASSA];
+ return num < 2;
+ case CLASSC:
+ return r[CLASSC] < CREGCNT;
+ case CLASSD:
+ return r[CLASSD] < DREGCNT;
+ }
+ return 0; /* XXX gcc */
+}
+
+char *rnames[] = {
+ "0", "1", "2", "3",
+ "050", "051", "052", "053", "054", "055", "056", "057",
+ "060", "061", "062", "063", "064", "065", "066", "067",
+ "070", "071", "072", "073", "074", "075", "076", "077",
+ "041", "040"
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ return CLASSA;
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+}
+
+/*
+ * Special shapes.
+ */
+int
+special(NODE *p, int shape)
+{
+ return SRNOPE;
+}
diff --git a/usr.bin/pcc/arch/nova/macdefs.h b/usr.bin/pcc/arch/nova/macdefs.h
new file mode 100644
index 00000000000..3104c900ef4
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/macdefs.h
@@ -0,0 +1,195 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent defines for Data General Nova.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|(val);
+
+#define ARGINIT 16 /* adjusted in MD code */
+#define AUTOINIT 16 /* adjusted in MD code */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZINT 16
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 64
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 32
+#define SZPOINT(t) 16 /* Actually 15 */
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALINT 16
+#define ALFLOAT 16
+#define ALDOUBLE 16
+#define ALLDOUBLE 16
+#define ALLONG 16
+#define ALLONGLONG 16
+#define ALSHORT 16
+#define ALPOINT 16
+#define ALSTRUCT 16
+#define ALSTACK 16
+
+/*
+ * 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 MIN_SHORT
+#define MAX_INT MAX_SHORT
+#define MAX_UNSIGNED MAX_USHORT
+#define MIN_LONG 0x80000000L
+#define MAX_LONG 0x7fffffffL
+#define MAX_ULONG 0xffffffffUL
+#define MIN_LONGLONG MIN_LONG
+#define MAX_LONGLONG MAX_LONG
+#define MAX_ULONGLONG MAX_ULONG
+
+/* Default char is unsigned */
+#define CHAR_UNSIGNED
+
+/*
+ * Use large-enough types.
+ */
+typedef long CONSZ;
+typedef unsigned long U_CONSZ;
+typedef long OFFSZ;
+
+#define CONFMT "%ld" /* format for printing constants */
+#define LABFMT ".L%d" /* format for printing labels */
+#define STABLBL ".LL%d" /* format for stab (debugging) labels */
+#ifdef FORTRAN
+#define XL 8
+#define FLABELFMT "%s:\n"
+#define USETEXT ".text"
+#define USECONST ".data\t0" /* XXX - fix */
+#define USEBSS ".data\t1" /* XXX - fix */
+#define USEINIT ".data\t2" /* XXX - fix */
+#define MAXREGVAR 3 /* XXX - fix */
+#define BLANKCOMMON "_BLNK_"
+#define MSKIREG (M(TYSHORT)|M(TYLONG))
+#define TYIREG TYLONG
+#define FSZLENG FSZLONG
+#define FUDGEOFFSET 1
+#define AUTOREG EBP
+#define ARGREG EBP
+#define ARGOFFSET 4
+#endif
+
+#define BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+/* Definitions mostly used in pass2 */
+
+#define BYTEOFF(x) ((x)&01)
+#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 genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE) ? 4 : \
+ ((t) == LONGLONG || (t) == ULONGLONG || \
+ (t) == LONG || (t) == ULONG) ? 2 : 1)
+
+/*
+ * The Nova has three register classes. Note that the space used in
+ * zero page is considered registers.
+ * Register 28 and 29 are FP and SP.
+ *
+ * The classes used on Nova are:
+ * A - AC0-AC3 (as non-index registers) : reg 0-3
+ * B - AC2-AC3 (as index registers) : reg 2-3
+ * C - address 50-77 in memory : reg 4-27
+ */
+#define MAXREGS 30 /* 0-29 */
+
+#define RSTATUS \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|SBREG|TEMPREG, SAREG|SBREG|TEMPREG,\
+ SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, \
+ SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, \
+ SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \
+ SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \
+ SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \
+ SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \
+ 0, 0
+
+#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 },
+
+
+/* Return a register class based on the type of the node */
+/* all types in all classes */
+#define PCLASS(p) (SAREG|SBREG|SCREG)
+
+#define NUMCLASS 4 /* highest number of reg classes used */
+ /* XXX - must be 4 */
+
+int COLORMAP(int c, int *r);
+#define GCLASS(x) (x < 4 ? CLASSA : CLASSC)
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 6) /* A1 */
+#define ENCRA2(x) ((x) << 12) /* A2 */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+#define RETREG(x) (0) /* ? Sanity */
+
+/* XXX - to die */
+#define FPREG 28 /* frame pointer */
+#define STKREG 29 /* stack pointer */
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
diff --git a/usr.bin/pcc/arch/nova/order.c b/usr.bin/pcc/arch/nova/order.c
new file mode 100644
index 00000000000..fc6b2191d2c
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/order.c
@@ -0,0 +1,164 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+
+#include <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)
+{
+ if (r != 2 && r != 3)
+ return 1; /* can only index ac2 and ac3 */
+ if (t == CHAR || t == UCHAR) {
+ if (off < -256 || off > 254)
+ return 1;
+ } else if (off < -128 || off > 127)
+ return 1;
+ 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 ||
+ (p->n_left->n_op == REG &&
+ p->n_left->n_rval != 2 && p->n_left->n_rval != 3))
+ (void)geninsn(p->n_left, INBREG);
+ /* Converted in ormake() */
+ return;
+ }
+ }
+ (void)geninsn(p, INBREG);
+}
+
+/*
+ * Do the actual conversion of offstar-found OREGs into real OREGs.
+ */
+void
+myormake(NODE *q)
+{
+ if (x2debug)
+ printf("myormake(%p)\n", q);
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p)
+{
+
+ if (x2debug)
+ printf("shumul(%p)\n", p);
+
+ /* Turns currently anything into OREG on x86 */
+ 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)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int 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;
+}
diff --git a/usr.bin/pcc/arch/nova/table.c b/usr.bin/pcc/arch/nova/table.c
new file mode 100644
index 00000000000..d2d7bdd6513
--- /dev/null
+++ b/usr.bin/pcc/arch/nova/table.c
@@ -0,0 +1,1514 @@
+/* $Id: table.c,v 1.1 2007/09/15 18:12:28 otto Exp $ */
+/*
+ * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+
+# 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
+
+struct optab table[] = {
+/* First entry must be an empty entry */
+{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " mov AR,ALZA\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " sta AR,ZC,1\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " sta AR,AL\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SONE, TWORD,
+ NAREG, RESC1,
+ " subzl A1,A1ZA\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON, TWORD,
+ NAREG, RESC1,
+ " lda A1,ZB,1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SZERO, TWORD,
+ NAREG, RESC1,
+ " sub A1,A1ZA\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SNAME, TWORD|TPOINT,
+ NAREG, RESC1,
+ " lda A1,ZD,1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SNAME, TWORD|TPOINT,
+ NBREG, RESC1,
+ " lda A1,ZD,1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SCREG, TWORD|TPOINT,
+ NBREG, RESC1,
+ " lda A1,AR\n", },
+
+{ PLUS, INBREG|INAREG,
+ SAREG|SBREG, TWORD|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " inc AL,AL\n", },
+
+{ OPSIMP, INBREG|INAREG|FOREFF,
+ SAREG|SBREG, TWORD|TPOINT,
+ SAREG|SBREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " O AR,AL\n", },
+
+{ UMUL, INAREG,
+ SANY, TPOINT|TWORD,
+ SOREG, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " lda A1,AL\n", },
+
+#if 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 (u)char to (u)char. */
+{ SCONV, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ 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 double <-> float. nothing to do here */
+{ SCONV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to pointers. */
+{ SCONV, ININT,
+ SHINT, TPOINT,
+ SANY, TPOINT,
+ 0, RLEFT,
+ "", },
+
+/* char to something */
+
+/* convert char to (unsigned) short. */
+{ SCONV, ININT,
+ SBREG|SOREG|SNAME, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movsbw AL,A1\n", },
+
+/* convert unsigned char to (u)short. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movzbw AL,A1\n", },
+
+/* convert signed char to int (or pointer). */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TCHAR,
+ SAREG, TWORD|TPOINT,
+ NASL|NAREG, RESC1,
+ " movsbl AL,A1\n", },
+
+/* convert unsigned char to (u)int. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzbl AL,A1\n", },
+
+/* convert char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SANY, TLL,
+ NSPECIAL|NAREG|NASL, RESC1,
+ " movsbl AL,%eax\n cltd\n", },
+
+/* convert unsigned char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SANY, TLL,
+ NCREG|NCSL, RESC1,
+ " movzbl AL,A1\n xorl U1,U1\n", },
+
+/* convert char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movsbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* convert (u)char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movzbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* short to something */
+
+/* convert short (in memory) to char */
+{ SCONV, INCH,
+ SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert short (in reg) to char. */
+{ SCONV, INCH,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movswl AL,A1\n", },
+
+/* convert unsigned short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzwl AL,A1\n", },
+
+/* convert short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TSHORT,
+ SHLL, TLL,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " movswl AL,%eax\n cltd\n", },
+
+/* convert unsigned short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHLL, TLL,
+ NCREG|NCSL, RESC1,
+ " movzwl AL,A1\n xorl U1,U1\n", },
+
+/* convert short (in memory) to float/double */
+{ SCONV, INFL,
+ SOREG|SNAME, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fild AL\n", },
+
+/* convert short (in register) to float/double */
+{ SCONV, INFL,
+ SAREG, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushw AL\n fild (%esp)\n addl $2,%esp\n", },
+
+/* convert unsigned short to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG|NTEMP, RESC2,
+ " movzwl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* int to something */
+
+/* convert int to char. This is done when register is loaded */
+{ SCONV, INCH,
+ SAREG, TWORD,
+ SANY, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert int to short. Nothing to do */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SANY, TSHORT|TUSHORT,
+ 0, RLEFT,
+ "", },
+
+/* convert int to long long */
+{ SCONV, INLL,
+ SAREG, TWORD|TPOINT,
+ SCREG, TLONGLONG,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " cltd\n", },
+
+/* convert int to unsigned long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SHLL, TULONGLONG,
+ NCSL|NCREG, RESC1,
+ " movl AL,A1\n xorl U1,U1\n", },
+
+/* convert int (in memory) to double */
+{ SCONV, INFL,
+ SOREG|SNAME, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildl AL\n", },
+
+/* convert int (in register) to double */
+{ SCONV, INFL,
+ SAREG, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl AL\n fildl (%esp)\n addl $4,%esp\n", },
+
+/* long long to something */
+
+/* convert (u)long long to (u)char (mem->reg) */
+{ SCONV, INCH,
+ SOREG|SNAME, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
+{ SCONV, INCH,
+ SHLL, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert (u)long long to (u)short (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long to int (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+/* convert long long to int (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long (in memory) to floating */
+{ SCONV, INFL,
+ SOREG|SNAME, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildq AL\n", },
+
+/* convert long long (in register) to floating */
+{ SCONV, INFL,
+ SHLL, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl UL\n pushl AL\n"
+ " fildq (%esp)\n addl $8,%esp\n", },
+
+/* convert unsigned long long to floating */
+{ SCONV, INFL,
+ SCREG, TULONGLONG,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ "ZJ", },
+
+/* float to something */
+
+#if 0 /* go via int by adding an extra sconv in clocal() */
+/* convert float/double to (u) char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double to (u) int/short/char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NCREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#endif
+
+/* convert float/double to (u)int. XXX should use NTEMP here */
+{ SCONV, INAREG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double (in register) to (unsigned) long long */
+/* XXX - unsigned is not handled correct */
+{ SCONV, INLL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHLL, TLONGLONG|TULONGLONG,
+ NCREG, RESC1,
+ " subl $8,%esp\n fistpq (%esp)\n"
+ " popl A1\n popl U1\n", },
+
+/* slut sconv */
+
+/*
+ * Subroutine calls.
+ */
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL\nZC", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ 0, 0,
+ " call CL\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+/* struct return */
+{ USTCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+{ STCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+/*
+ * The next rules handle all binop-style operators.
+ */
+/* Special treatment for long long */
+{ PLUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " addl AR,AL\n adcl UR,UL\n", },
+
+/* Special treatment for long long XXX - fix commutative check */
+{ PLUS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RRIGHT,
+ " addl AL,AR\n adcl UL,UR\n", },
+
+{ PLUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " faddl AR\n", },
+
+{ PLUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " faddp\n", },
+
+{ PLUS, INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incl AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal CR(AL),A1\n", },
+
+{ PLUS, INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " incb AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ NAREG|NASL|NASR, RESC1,
+ " leal (AL,AR),A1\n", },
+
+
+/* address as register offset, negative */
+{ MINUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal -CR(AL),A1\n", },
+
+{ MINUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " subl AR,AL\n sbbl UR,UL\n", },
+
+{ MINUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fsubl AR\n", },
+
+{ MINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fsubZAp\n", },
+
+/* Simple r/m->reg ops */
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT, TSHORT|TUSHORT,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " Ol AR,AL\n Ol UR,UL\n", },
+
+
+/*
+ * The next rules handle all shift operators.
+ */
+/* (u)longlong left shift is emulated */
+{ LS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG, TWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " salb AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " salb AR,AL\n", },
+
+/* (u)longlong right shift is emulated */
+{ RS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrb AR,AL\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+{ ASSIGN, FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, 0,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, 0,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR|TWORD,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TANY,
+ SAREG, TANY,
+ NAREG, RDEST,
+ "ZE", },
+
+{ ASSIGN, FOREFF,
+ SFLD, TANY,
+ SAREG|SNAME|SOREG|SCON, TANY,
+ NAREG, 0,
+ "ZE", },
+
+{ ASSIGN, INDREG|FOREFF,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "", }, /* This will always be in the correct register */
+
+/* order of table entries is very important here! */
+{ ASSIGN, INFL,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstt AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpt AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstl AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpl AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fsts AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstps AL\n", },
+/* end very important order */
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TLDOUBLE,
+ SHFL|SOREG|SNAME, TLDOUBLE,
+ 0, RDEST,
+ " fldt AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TDOUBLE,
+ SHFL|SOREG|SNAME, TDOUBLE,
+ 0, RDEST,
+ " fldl AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TFLOAT,
+ SHFL|SOREG|SNAME, TFLOAT,
+ 0, RDEST,
+ " flds AR\n", },
+
+/* Do not generate memcpy if return from funcall */
+#if 0
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME|SAREG, TPTRTO|TSTRUCT,
+ SFUNCALL, TPTRTO|TSTRUCT,
+ 0, RRIGHT,
+ "", },
+#endif
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG|SOREG|SNAME, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+/*
+ * DIV/MOD/MUL
+ */
+/* long long div is emulated */
+{ DIV, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ DIV, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TWORD,
+ NSPECIAL, RDEST,
+ " cltd\n idivl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ DIV, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NSPECIAL, RDEST,
+ " xorb %ah,%ah\n divb AR\n", },
+
+{ DIV, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fdivl AR\n", },
+
+{ DIV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fdivZAp\n", },
+
+/* (u)longlong mod is emulated */
+{ MOD, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MOD, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TSWORD,
+ NAREG|NSPECIAL, RESC1,
+ " cltd\n idivl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TUWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ MOD, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NBREG|NSPECIAL, RESC1,
+ " xorb %ah,%ah\n divb AR\n", },
+
+/* (u)longlong mul is emulated */
+{ MUL, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MUL, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " imull AR,AL\n", },
+
+{ MUL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imulw AR,AL\n", },
+
+{ MUL, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ NSPECIAL, RDEST,
+ " imulb AR\n", },
+
+{ MUL, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fmull AR\n", },
+
+{ MUL, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fmulp\n", },
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INLL,
+ SANY, TANY,
+ SOREG, TLL,
+ NCREG|NCSL, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TPOINT|TWORD,
+ SOREG, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ UMUL, INCH,
+ SANY, TANY,
+ SOREG, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldt AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldl AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NDREG|NDSL, RESC1,
+ " flds AL\n", },
+
+/*
+ * Logical/branching operators
+ */
+
+/* Comparisions, take care of everything */
+{ OPLOG, FORCC,
+ SHLL|SOREG|SNAME, TLL,
+ SHLL, TLL,
+ 0, 0,
+ "ZD", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SCON|SAREG, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCON|SAREG, TWORD|TPOINT,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TANY,
+ 0, RESCC,
+ " cmpw AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TANY,
+ 0, RESCC,
+ " cmpb AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+{ OPLOG, FORCC,
+ SOREG|SNAME, TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+#if 0
+/* Ppro and later only */
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RESCC,
+ "ZA fucomip %st,%st(1)\n", },
+#endif
+
+{ OPLOG, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "diediedie!", },
+
+/* AND/OR/ER/NOT */
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TWORD,
+ SCON|SAREG, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG|SOREG|SNAME, TLL,
+ 0, RLEFT,
+ " andl AR,AL\n andl UR,UL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TWORD,
+ SAREG|SOREG|SNAME, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+/* AND/OR/ER/NOT */
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp LL\n", },
+
+#ifdef GCC_COMPAT
+{ GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp *AL\n", },
+#endif
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SCREG|SCON|SOREG|SNAME, TLL,
+ NCREG, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SCON|SOREG|SNAME, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " movb AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " movw AL,A1\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TLDOUBLE,
+ SOREG|SNAME, TLDOUBLE,
+ NDREG, RESC1,
+ " fldt AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TDOUBLE,
+ SOREG|SNAME, TDOUBLE,
+ NDREG, RESC1,
+ " fldl AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT,
+ SOREG|SNAME, TFLOAT,
+ NDREG, RESC1,
+ " flds AL\n", },
+
+/* Only used in ?: constructs. The stack already contains correct value */
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT|TDOUBLE|TLDOUBLE,
+ SDREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "", },
+
+/*
+ * Negate a word.
+ */
+
+{ UMINUS, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG, TLL,
+ 0, RLEFT,
+ " negl AL\n adcl $0,UL\n negl UL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " negl AL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " negw AL\n", },
+
+{ UMINUS, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " negb AL\n", },
+
+{ UMINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fchs\n", },
+
+{ COMPL, INCREG,
+ SCREG, TLL,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n notl UL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TWORD,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RLEFT,
+ " notw AL\n", },
+
+{ COMPL, INBREG,
+ SBREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, RLEFT,
+ " notb AL\n", },
+
+/*
+ * Arguments to functions.
+ */
+{ FUNARG, FOREFF,
+ SCON|SCREG|SNAME|SOREG, TLL,
+ SANY, TLL,
+ 0, RNULL,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SANY, TSHORT,
+ NAREG, 0,
+ " movswl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SANY, TUSHORT,
+ NAREG, 0,
+ " movzwl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SANY, TCHAR,
+ NAREG, 0,
+ " movsbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SANY, TUCHAR,
+ NAREG, 0,
+ " movzbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " subl $8,%esp\n fstpl (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " subl $4,%esp\n fstps (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TLDOUBLE,
+ SANY, TLDOUBLE,
+ 0, 0,
+ " subl $12,%esp\n fstpt (%esp)\n", },
+
+{ STARG, FOREFF,
+ SAREG|SOREG|SNAME|SCON, TANY,
+ SANY, TSTRUCT,
+ NSPECIAL|NAREG, 0,
+ "ZF", },
+
+#endif
+
+# 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]);
diff --git a/usr.bin/pcc/arch/pdp10/code.c b/usr.bin/pcc/arch/pdp10/code.c
new file mode 100644
index 00000000000..6121bdc6219
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/code.c
@@ -0,0 +1,167 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:29 otto Exp $ */
+/*
+ * 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
+ * Nothing to do on PDP10.
+ */
+void
+defalign(int n)
+{
+}
+
+/*
+ * code for the end of a function
+ */
+void
+efcode()
+{
+}
+
+/*
+ * code for the beginning of a function; a is an array of
+ * indices in stab for the arguments; n is the number
+ */
+void
+bfcode(struct symtab **a, int n)
+{
+ send_passt(IP_LOCCTR, PROG);
+ defnam(cftnsp);
+}
+
+
+/*
+ * 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 flag )
+{
+}
+
+/*
+ * 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(" .block %d\n", n);
+ 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(struct swents **p, int n)
+{
+ int i;
+ char *s;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ s = (isinlining ? permalloc(40) : tmpalloc(40));
+ if (p[i]->sval >= 0 && p[i]->sval <= 0777777)
+ sprintf(s, " cain 1,0%llo", p[i]->sval);
+ else if (p[i]->sval < 0)
+ sprintf(s, " camn 1,[ .long -0%llo ]", -p[i]->sval);
+ else
+ sprintf(s, " camn 1,[ .long 0%llo ]", p[i]->sval);
+ send_passt(IP_ASM, s);
+ branch(p[i]->slab);
+ }
+ if (p[0]->slab > 0) {
+ send_passt(IP_DEFLAB, getlab()); /* XXX - fool optimizer */
+ branch(p[0]->slab);
+ }
+}
diff --git a/usr.bin/pcc/arch/pdp10/local.c b/usr.bin/pcc/arch/pdp10/local.c
new file mode 100644
index 00000000000..8d18720aa1e
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/local.c
@@ -0,0 +1,782 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:29 otto Exp $ */
+/*
+ * 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"
+
+/* this file contains code which is dependent on the target machine */
+
+static int pointp(TWORD t);
+static struct symtab *newfun(char *name, TWORD type);
+
+#define PTRNORMAL 1
+#define PTRCHAR 2
+#define PTRSHORT 3
+static int ptype(TWORD t);
+
+NODE *
+clocal(NODE *p)
+{
+ /* this 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 */
+
+ register struct symtab *q;
+ register NODE *r, *l, *oop;
+ register int o;
+ register int m, ml;
+ int siz;
+
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ case AUTO:
+ /* fake up a structure reference */
+ if (q->stype == CHAR || q->stype == UCHAR ||
+ q->stype == SHORT || q->stype == USHORT)
+ r = block(REG, NIL, NIL, PTR+q->stype, 0, 0);
+ else
+ 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 STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ if ((q->sflags & SLABEL) == 0)
+ cerror("STATIC");
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ break;
+
+ case PCONV:
+ l = p->n_left;
+ /*
+ * Handle frame pointer directly without conversion,
+ * for efficiency.
+ */
+ if (l->n_op == REG && l->n_rval == 0) {
+rmpc: l->n_type = p->n_type;
+ l->n_df = p->n_df;
+ l->n_sue = p->n_sue;
+ nfree(p);
+ return l;
+ }
+ /* Convert ICON with name to new type */
+ if (l->n_op == ICON && l->n_sp != NULL &&
+ l->n_type == INCREF(STRTY) &&
+ (p->n_type == INCREF(CHAR) ||
+ p->n_type == INCREF(UCHAR) ||
+ p->n_type == INCREF(SHORT) ||
+ p->n_type == INCREF(USHORT))) {
+ l->n_lval *= (BTYPE(p->n_type) == CHAR ||
+ BTYPE(p->n_type) == UCHAR ? 4 : 2);
+ goto rmpc;
+ }
+ /* Convert only address constants, never convert other */
+ if (l->n_op == ICON) {
+ if (l->n_sp == NULL)
+ goto rmpc;
+ if (p->n_type == INCREF(CHAR) ||
+ p->n_type == INCREF(UCHAR) ||
+ p->n_type == INCREF(VOID))
+ l->n_lval = (l->n_lval & 07777777777) |
+ 0700000000000LL;
+ else if (p->n_type == INCREF(SHORT) ||
+ p->n_type == INCREF(USHORT))
+ l->n_lval = (l->n_lval & 07777777777) |
+ 0750000000000LL;
+ else
+ l->n_lval = l->n_lval & 07777777777;
+ goto rmpc;
+ }
+
+ /* Remove more conversions of identical pointers */
+ /* Be careful! optim() may do bad things */
+ if (ISPTR(DECREF(p->n_type))) {
+ if (ISPTR(DECREF(l->n_type))) {
+ if ((coptype(l->n_op) == UTYPE ||
+ coptype(l->n_op) == BITYPE) &&
+ (l->n_left->n_op == REG))
+ l->n_left->n_type = p->n_type;
+ goto rmpc;
+ }
+ }
+
+ /* Change PCONV from int to double pointer to right shift */
+ if (ISPTR(p->n_type) && ISPTR(DECREF(p->n_type)) &&
+ (l->n_type == INT || l->n_type == UNSIGNED)) {
+ p->n_op = RS;
+ p->n_right = bcon(2);
+ break;
+ }
+
+ /* Check for cast integral -> pointer */
+ if (BTYPE(l->n_type) == l->n_type)
+ break;
+
+ /* Remove conversions to identical pointers */
+ switch (ptype(p->n_type)) {
+ case PTRNORMAL:
+ if (ptype(l->n_type) == PTRNORMAL)
+ goto rmpc;
+ break;
+
+ case PTRSHORT:
+ if (ptype(l->n_type) == PTRSHORT)
+ goto rmpc;
+ break;
+
+ case PTRCHAR:
+ if (ptype(l->n_type) == PTRCHAR)
+ goto rmpc;
+ break;
+ }
+
+ break;
+
+ case SCONV:
+ l = p->n_left;
+
+ if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
+ btdim[p->n_type] == btdim[l->n_type]) {
+ if (p->n_type != FLOAT && p->n_type != DOUBLE &&
+ l->n_type != FLOAT && l->n_type != DOUBLE) {
+ nfree(p);
+ return l;
+ }
+ }
+ /* cast to (void) XXX should be removed in MI code */
+ if (p->n_type == VOID) {
+ nfree(p);
+ return l;
+ }
+ m = p->n_type;
+ ml = l->n_type;
+ if (m == ml) {
+ nfree(p);
+ return l;
+ }
+ o = l->n_op;
+ if (ml == FLOAT || ml == DOUBLE) {
+ if (o != FCON)
+ break;
+ ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */
+ r = block(ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0);
+ r->n_lval = ml == INT ?
+ (int) p->n_left->n_dcon :
+ (unsigned) p->n_left->n_dcon;
+ r->n_sp = NULL;
+ nfree(p->n_left);
+ p->n_left = r;
+ o = ICON;
+ if (m == ml) {
+ r = p->n_left;
+ nfree(p);
+ return r;
+ }
+ }
+ if (o == ICON) {
+ CONSZ val = l->n_lval;
+
+ switch (m) {
+ case CHAR:
+ l->n_lval = val & 0777;
+ if (val & 0400)
+ l->n_lval |= ~((CONSZ)0777);
+ break;
+ case UCHAR:
+ l->n_lval = val & 0777;
+ break;
+ case USHORT:
+ l->n_lval = val & 0777777;
+ break;
+ case SHORT:
+ l->n_lval = val & 0777777;
+ if (val & 0400000)
+ l->n_lval |= ~((CONSZ)0777777);
+ break;
+ case UNSIGNED:
+ l->n_lval = val & 0777777777777LL;
+ break;
+ case ENUMTY:
+ case MOETY:
+ case INT:
+ l->n_lval = val & 0777777777777LL;
+ if (val & 0400000000000LL)
+ l->n_lval |= ~(0777777777777LL);
+ break;
+ case LONGLONG: /* XXX */
+ case ULONGLONG:
+ l->n_lval = val;
+ break;
+ case VOID:
+ break;
+ case DOUBLE:
+ case FLOAT:
+ l->n_op = FCON;
+ l->n_dcon = 0;
+ break;
+ default:
+ cerror("unknown type %d", m);
+ }
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return l;
+ }
+ 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 RS:
+ case RSEQ:
+ /* convert >> to << with negative shift count */
+ /* Beware! constant shifts will be converted back in optim() */
+
+ if (p->n_right->n_op != UMINUS) {
+ p->n_right = buildtree(UMINUS, p->n_right, NIL);
+ } else {
+ r = p->n_right;
+ p->n_right = p->n_right->n_left;
+ nfree(r);
+ }
+ if (p->n_op == RS)
+ p->n_op = LS;
+ else
+ p->n_op = LSEQ;
+ break;
+
+ case UMUL: /* Convert structure assignment to memcpy() */
+ if (p->n_left->n_op == PLUS &&
+ p->n_left->n_left->n_op == PCONV &&
+ p->n_left->n_right->n_op == ICON &&
+ (p->n_type == CHAR || p->n_type == UCHAR ||
+ p->n_type == SHORT || p->n_type == USHORT)) {
+ /* Can remove the left SCONV */
+ l = p->n_left->n_left;
+ p->n_left->n_left = l->n_left;
+ nfree(l);
+ break;
+
+ }
+ if (p->n_left->n_op != STASG)
+ break;
+ oop = p;
+ p = p->n_left;
+ siz = p->n_sue->suesize/SZCHAR;
+ l = p->n_left;
+ r = p->n_right;
+ if (l->n_type == STRTY || l->n_type == UNIONTY) {
+ if (l->n_op == UMUL) {
+ p->n_left = l->n_left;
+ nfree(l);
+ l = p->n_left;
+ } else {
+ l = block(ADDROF, l, NIL, INCREF(l->n_type),
+ 0, MKSUE(INT));
+ }
+ }
+ if ((l->n_type != (STRTY+PTR) && l->n_type != (UNIONTY+PTR)) ||
+ (r->n_type != (STRTY+PTR) && r->n_type != (UNIONTY+PTR)))
+ cerror("bad stasg, l = %o, r = %o", l->n_type, r->n_type);
+ q = newfun("__structcpy", p->n_type);
+
+ /* structure pointer block */
+ l = block(CM, l, r, INT, 0, MKSUE(INT));
+ /* Size block */
+ r = block(CM, l, bcon(siz), INT, 0, MKSUE(INT));
+
+ l = block(ICON, NIL, NIL, q->stype, 0, MKSUE(INT));
+ l->n_sp = q;
+ p->n_left = l;
+ p->n_right = r;
+ p->n_op = CALL;
+ oop->n_left = p;
+ return oop;
+
+ }
+
+ return(p);
+}
+
+void
+myp2tree(NODE *p)
+{
+ NODE *r;
+
+ switch (p->n_op) {
+ case ULT: /* exor sign bit to avoid unsigned comparitions */
+ case ULE:
+ case UGT:
+ case UGE:
+ if (ISLONGLONG(p->n_left->n_type)) {
+ r = block(ICON, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ r->n_lval = 0x8000000000000000ULL; /* XXX */
+ } else {
+ r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0400000000000LL;
+ }
+ r->n_sp = NULL;
+ p->n_left = buildtree(ER, p->n_left, r);
+ if (ISUNSIGNED(p->n_left->n_type))
+ p->n_left->n_type = DEUNSIGN(p->n_left->n_type);
+
+ if (ISLONGLONG(p->n_right->n_type)) {
+ r = block(ICON, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ r->n_lval = 0x8000000000000000ULL; /* XXX */
+ } else {
+ r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0400000000000LL;
+ }
+ r->n_sp = NULL;
+ p->n_right = buildtree(ER, p->n_right, r);
+ if (ISUNSIGNED(p->n_right->n_type))
+ p->n_right->n_type = DEUNSIGN(p->n_right->n_type);
+
+ p->n_op -= (ULT-LT);
+ break;
+ }
+}
+
+
+struct symtab *
+newfun(char *name, TWORD type)
+{
+ struct symtab *sp;
+
+ sp = lookup(name, 0);
+ if (sp->stype == VOID) {
+ sp->stype = INCREF(type | FTN);
+ sp->sclass = EXTERN;
+ sp->soffset = 0;
+ }
+#ifdef notdef
+ else if (!ISFTN(DECREF(sp->stype)))
+ uerror("reserved name '%s' used illegally", name);
+#endif
+ return sp;
+}
+
+/*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;
+}
+
+/*
+ * is an automatic variable of type t OK for a register variable
+ * Everything is trusted to be in register here.
+ */
+int
+cisreg(TWORD t)
+{
+ return(1);
+}
+
+int
+ptype(TWORD t)
+{
+ int tt = BTYPE(t);
+ int e, rv;
+
+ if (!ISPTR(t))
+ cerror("not a pointer");
+
+ e = t & ~BTMASK;
+ while (e) {
+ rv = e;
+ if (DECREF(e) == 0)
+ break;
+ e = DECREF(e);
+ }
+ if (ISFTN(rv))
+ return PTRNORMAL;
+
+ switch (tt) {
+ case INT:
+ case LONG:
+ case LONGLONG:
+ case FLOAT:
+ case DOUBLE:
+ case STRTY:
+ case UNIONTY:
+ case ENUMTY:
+ case UNSIGNED:
+ case ULONG:
+ case ULONGLONG:
+ return PTRNORMAL;
+ case VOID:
+ case CHAR:
+ case UCHAR:
+ if (DECREF(t) == tt || ISARY(rv))
+ return PTRCHAR;
+ return PTRNORMAL;
+ case SHORT:
+ case USHORT:
+ if (DECREF(t) == tt || ISARY(rv))
+ return PTRSHORT;
+ return PTRNORMAL;
+ default:
+ break;
+ }
+ cerror("unknown type");
+ return PTRNORMAL; /* XXX */
+}
+
+/*
+ * Help routine to the one below; return true if it's not a word pointer.
+ */
+static int
+pointp(TWORD t)
+{
+ int rv = 0;
+
+ if (ISPTR(t) && ((t & TMASK1) == 0))
+ return 1;
+
+ t &= ~BTMASK;
+ while (t) {
+ rv = ISARY(t);
+ t = DECREF(t);
+ }
+ return rv;
+}
+
+/*
+ * 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/SZINT; /* Default */
+ if (ISPTR(DECREF(t)))
+ return p; /* Pointer/pointer reference */
+ switch (BTMASK & t) {
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ case STRTY:
+ case UNIONTY:
+ case ENUMTY:
+ case LONGLONG:
+ case ULONGLONG:
+ case FLOAT:
+ case DOUBLE:
+ break;
+
+ case SHORT:
+ case USHORT:
+ if (pointp(t))
+ p->n_lval = off/SZSHORT;
+ break;
+
+ case VOID: /* void pointers */
+ case CHAR:
+ case UCHAR:
+ if (pointp(t))
+ p->n_lval = off/SZCHAR;
+ break;
+
+ default:
+ cerror("offcon, off %llo size %d type %x", off, sue->suesize, t);
+ }
+ if (xdebug)
+ printf("offcon return 0%llo\n", p->n_lval);
+ return(p);
+}
+
+/*
+ * Allocate off bits on the stack. p is a tree that when evaluated
+ * is the multiply count for off, t is a NAME node where to write
+ * the allocated address.
+ * Be aware that a pointer conversion may be needed when saving
+ * to node t!
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ if ((off % SZINT) == 0)
+ p = buildtree(MUL, p, bcon(off/SZINT));
+ else if ((off % SZSHORT) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZSHORT));
+ p = buildtree(PLUS, p, bcon(1));
+ p = buildtree(RS, p, bcon(1));
+ } else if ((off % SZCHAR) == 0) {
+ p = buildtree(MUL, p, bcon(off/SZCHAR));
+ p = buildtree(PLUS, p, bcon(3));
+ p = buildtree(RS, p, bcon(2));
+ } else
+ cerror("roundsp");
+
+ /* 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;
+ /* Cast sp to destination type (may be redundant) */
+ sp = buildtree(CAST,
+ block(NAME, NIL, NIL, t->n_type, t->n_df, t->n_sue), sp);
+ nfree(sp->n_left);
+ nfree(sp);
+ sp = sp->n_right;
+ ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
+
+ /* add the size to sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, 0);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(PLUSEQ, sp, p));
+}
+
+static int inwd; /* current bit offsed in word */
+static CONSZ word; /* word being built from fields */
+
+/*
+ * Generate initialization code for assigning a constant c
+ * to a field of width sz
+ * we assume that the proper alignment has been obtained
+ * inoff is updated to have the proper final value
+ * we also assume sz < SZINT
+ */
+void
+incode(NODE *p, int sz)
+{
+ char *s;
+
+ inoff += sz;
+ if ((sz + inwd) > SZINT)
+ cerror("incode: field > int");
+
+ word |= ((p->n_lval & ((1 << sz) - 1)) << (36 - inwd - sz));
+
+ inwd += sz;
+ if (inoff % SZINT == 0) {
+ s = isinlining ? permalloc(30) : tmpalloc(30);
+ sprintf(s, " .long 0%llo", word);
+ send_passt(IP_ASM, s);
+ word = inwd = 0;
+ }
+ tfree(p);
+}
+
+/* output code to initialize space of size sz to the value d */
+/* the proper alignment has been obtained */
+/* inoff is updated to have the proper final value */
+/* on the target machine, write it out in octal! */
+void
+fincode(NODE *p, int sz)
+{
+ double d = p->n_dcon;
+
+ if(!nerrors)
+ printf(" %s 0%c%.20e\n",
+ sz == SZDOUBLE ? ".double" : ".float",
+ sz == SZDOUBLE ? 'd' : 'f', d);
+ inoff += sz;
+}
+
+void
+cinit(NODE *p, int sz)
+{
+ NODE *l;
+
+ /*
+ * as a favor (?) to people who want to write
+ * int i = 9600/134.5;
+ * we will, under the proper circumstances, do
+ * a coercion here.
+ */
+ switch (p->n_type) {
+ case INT:
+ case UNSIGNED:
+ l = p->n_left;
+ if (l->n_op != SCONV || l->n_left->n_op != FCON)
+ break;
+ nfree(l);
+ l = l->n_left;
+ l->n_lval = (long)(l->n_dcon);
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = INT;
+ p->n_left = l;
+ break;
+ }
+ /* arrange for the initialization of p into a space of size sz */
+ /* the proper alignment has been opbtained */
+ /* inoff is updated to have the proper final value */
+ ecode( p );
+ inoff += sz;
+}
+
+/*
+ * define n bits of zeros in a vfd
+ */
+void
+vfdzero(int n)
+{
+ char *s;
+
+ inoff += n;
+ inwd += n;
+ if (inoff%ALINT ==0) {
+ s = isinlining ? permalloc(30) : tmpalloc(30);
+ sprintf(s, " .long 0%llo", word);
+ send_passt(IP_ASM, s);
+ word = inwd = 0;
+ }
+}
+
+/* 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
+ */
+int
+ctype(TWORD type)
+{
+ switch (BTYPE(type)) {
+ case LONG:
+ MODTYPE(type,INT);
+ break;
+
+ case ULONG:
+ MODTYPE(type,UNSIGNED);
+ }
+ return (type);
+}
+
+/* curid is a variable which is defined but
+ * is not initialized (and not a function );
+ * This routine returns the stroage class for an uninitialized declaration
+ */
+int
+noinit()
+{
+ return(EXTERN);
+}
+
+/* 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+(SZINT-1))/SZINT;
+ printf(" .comm %s,0%o\n", exname(q->sname), 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+(SZINT-1))/SZINT;
+ if (q->slevel == 0)
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * Debugger code - ignore.
+ */
+void
+prcstab(int a)
+{
+}
+
+void
+pfstab(char *a)
+{
+}
diff --git a/usr.bin/pcc/arch/pdp10/local2.c b/usr.bin/pcc/arch/pdp10/local2.c
new file mode 100644
index 00000000000..8591a44f4fc
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/local2.c
@@ -0,0 +1,1237 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:29 otto Exp $ */
+/*
+ * 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>
+
+# define putstr(s) fputs((s), stdout)
+
+void acon(FILE *, NODE *p);
+int argsize(NODE *p);
+void genargs(NODE *p);
+
+static int ftlab1, ftlab2;
+static int offlab;
+int offarg;
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+defname(char *name, int visib)
+{
+ if (visib)
+ printf(" .globl %s\n", name);
+ printf("%s:\n", name);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int isoptim;
+
+void
+prologue(int regs, int autos)
+{
+ int i, addto;
+
+ offlab = getlab();
+ if (regs < 0 || autos < 0) {
+ /*
+ * non-optimized code, jump to epilogue for code generation.
+ */
+ ftlab1 = getlab();
+ ftlab2 = getlab();
+ printf(" jrst L%d\n", ftlab1);
+ printf("L%d:\n", ftlab2);
+ } else {
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ autos = autos + (SZINT-1);
+ addto = (autos - AUTOINIT)/SZINT + (MAXRVAR-regs);
+ if (addto || gflag) {
+ printf(" push %s,%s\n",rnames[017], rnames[016]);
+ printf(" move %s,%s\n", rnames[016],rnames[017]);
+ for (i = regs; i < MAXRVAR; i++) {
+ int db = ((i+1) < MAXRVAR);
+ printf(" %smovem %s,0%o(%s)\n",
+ db ? "d" : "",
+ rnames[i+1], i+1-regs, rnames[016]);
+ if (db)
+ i++;
+ }
+ if (addto)
+ printf(" addi %s,0%o\n", rnames[017], addto);
+ } else
+ offarg = 1;
+ isoptim = 1;
+ }
+}
+
+/*
+ * End of block.
+ */
+void
+eoftn(int regs, int autos, int retlab)
+{
+ register OFFSZ spoff; /* offset from stack pointer */
+ int i;
+
+ spoff = autos + (SZINT-1);
+ if (spoff >= AUTOINIT)
+ spoff -= AUTOINIT;
+ spoff /= SZINT;
+ /* return from function code */
+ printf("L%d:\n", retlab);
+ if (gflag || isoptim == 0 || autos != AUTOINIT || regs != MAXRVAR) {
+ for (i = regs; i < MAXRVAR; i++) {
+ int db = ((i+1) < MAXRVAR);
+ printf(" %smove %s,0%o(%s)\n", db ? "d" : "",
+ rnames[i+1], i+1-regs, rnames[016]);
+ if (db)
+ i++;
+ }
+ printf(" move %s,%s\n", rnames[017], rnames[016]);
+ printf(" pop %s,%s\n", rnames[017], rnames[016]);
+ }
+ printf(" popj %s,\n", rnames[017]);
+
+ /* Prolog code */
+ if (isoptim == 0) {
+ printf("L%d:\n", ftlab1);
+ printf(" push %s,%s\n", rnames[017], rnames[016]);
+ printf(" move %s,%s\n", rnames[016], rnames[017]);
+ for (i = regs; i < MAXRVAR; i++) {
+ int db = ((i+1) < MAXRVAR);
+ printf(" %smovem %s,0%o(%s)\n", db ? "d" : "",
+ rnames[i+1], i+1-regs, rnames[016]);
+ spoff++;
+ if (db)
+ i++, spoff++;
+ }
+ if (spoff)
+ printf(" addi %s,0%llo\n", rnames[017], spoff);
+ printf(" jrst L%d\n", ftlab2);
+ }
+ printf(" .set " LABFMT ",0%o\n", offlab, MAXRVAR-regs);
+ offarg = isoptim = 0;
+}
+
+static char *loctbl[] = { "text", "data", "data", "text", "text", "stab" };
+
+void
+setlocc(int locctr)
+{
+ static int lastloc;
+
+ if (locctr == lastloc)
+ return;
+
+ lastloc = locctr;
+ printf(" .%s\n", loctbl[locctr]);
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ * R - Register
+ * M - Memory
+ * C - Constant
+ */
+void
+hopcode(int f, int o)
+{
+ cerror("hopcode: f %d %d", f, o);
+}
+
+char *
+rnames[] = { /* keyed to register number tokens */
+ "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7",
+ "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+};
+
+int rstatus[] = {
+ 0, STAREG, STAREG, STAREG, STAREG, STAREG, STAREG, STAREG,
+ SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 0, 0,
+};
+
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(SZSHORT/SZCHAR);
+
+ case DOUBLE:
+ return(SZDOUBLE/SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ return(SZINT/SZCHAR);
+
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG/SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ cerror("tlen type %d not pointer");
+ return SZPOINT/SZCHAR;
+ }
+}
+
+static char *
+binskip[] = {
+ "e", /* jumpe */
+ "n", /* jumpn */
+ "le", /* jumple */
+ "l", /* jumpl */
+ "ge", /* jumpge */
+ "g", /* jumpg */
+};
+
+/*
+ * Extract the higher 36 bits from a longlong.
+ */
+static CONSZ
+gethval(CONSZ lval)
+{
+ CONSZ hval = (lval >> 35) & 03777777777LL;
+
+ if ((hval & 03000000000LL) == 03000000000LL) {
+ hval |= 0777000000000LL;
+ } else if ((hval & 03000000000LL) == 02000000000LL) {
+ hval &= 01777777777LL;
+ hval |= 0400000000000LL;
+ }
+ return hval;
+}
+
+/*
+ * Do a binary comparision, and jump accordingly.
+ */
+static void
+twocomp(NODE *p)
+{
+ int o = p->n_op;
+ extern int negrel[];
+ int isscon = 0, iscon = p->n_right->n_op == ICON;
+
+ if (o < EQ || o > GT)
+ cerror("bad binary conditional branch: %s", opst[o]);
+
+ if (iscon && p->n_right->n_name[0] != 0) {
+ printf(" cam%s ", binskip[negrel[o-EQ]-EQ]);
+ adrput(stdout, getlr(p, 'L'));
+ putchar(',');
+ printf("[ .long ");
+ adrput(stdout, getlr(p, 'R'));
+ putchar(']');
+ printf("\n jrst L%d\n", p->n_label);
+ return;
+ }
+ if (iscon)
+ isscon = p->n_right->n_lval >= 0 &&
+ p->n_right->n_lval < 01000000;
+
+ printf(" ca%c%s ", iscon && isscon ? 'i' : 'm',
+ binskip[negrel[o-EQ]-EQ]);
+ adrput(stdout, getlr(p, 'L'));
+ putchar(',');
+ if (iscon && (isscon == 0)) {
+ printf("[ .long ");
+ adrput(stdout, getlr(p, 'R'));
+ putchar(']');
+ } else
+ adrput(stdout, getlr(p, 'R'));
+ printf("\n jrst L%d\n", p->n_label);
+}
+
+/*
+ * Compare byte/word pointers.
+ * XXX - do not work for highest bit set in address
+ */
+static void
+ptrcomp(NODE *p)
+{
+ printf(" rot "); adrput(stdout, getlr(p, 'L')); printf(",6\n");
+ printf(" rot "); adrput(stdout, getlr(p, 'R')); printf(",6\n");
+ twocomp(p);
+}
+
+/*
+ * Do a binary comparision of two long long, and jump accordingly.
+ * XXX - can optimize for constants.
+ */
+static void
+twollcomp(NODE *p)
+{
+ int o = p->n_op;
+ int iscon = p->n_right->n_op == ICON;
+ int m;
+
+ if (o < EQ || o > GT)
+ cerror("bad long long conditional branch: %s", opst[o]);
+
+ /* Special strategy for equal/not equal */
+ if (o == EQ || o == NE) {
+ if (o == EQ)
+ m = getlab();
+ printf(" came ");
+ upput(getlr(p, 'L'), SZLONG);
+ putchar(',');
+ if (iscon)
+ printf("[ .long ");
+ upput(getlr(p, 'R'), SZLONG);
+ if (iscon)
+ putchar(']');
+ printf("\n jrst L%d\n", o == EQ ? m : p->n_label);
+ printf(" cam%c ", o == EQ ? 'n' : 'e');
+ adrput(stdout, getlr(p, 'L'));
+ putchar(',');
+ if (iscon)
+ printf("[ .long ");
+ adrput(stdout, getlr(p, 'R'));
+ if (iscon)
+ putchar(']');
+ printf("\n jrst L%d\n", p->n_label);
+ if (o == EQ)
+ printf("L%d:\n", m);
+ return;
+ }
+ /* First test highword */
+ printf(" cam%ce ", o == GT || o == GE ? 'l' : 'g');
+ adrput(stdout, getlr(p, 'L'));
+ putchar(',');
+ if (iscon)
+ printf("[ .long ");
+ adrput(stdout, getlr(p, 'R'));
+ if (iscon)
+ putchar(']');
+ printf("\n jrst L%d\n", p->n_label);
+
+ /* Test equality */
+ printf(" came ");
+ adrput(stdout, getlr(p, 'L'));
+ putchar(',');
+ if (iscon)
+ printf("[ .long ");
+ adrput(stdout, getlr(p, 'R'));
+ if (iscon)
+ putchar(']');
+ printf("\n jrst L%d\n", m = getlab());
+
+ /* Test lowword. Only works with pdp10 format for longlongs */
+ printf(" cam%c%c ", o == GT || o == GE ? 'l' : 'g',
+ o == LT || o == GT ? 'e' : ' ');
+ upput(getlr(p, 'L'), SZLONG);
+ putchar(',');
+ if (iscon)
+ printf("[ .long ");
+ upput(getlr(p, 'R'), SZLONG);
+ if (iscon)
+ putchar(']');
+ printf("\n jrst L%d\n", p->n_label);
+ printf("L%d:\n", m);
+}
+
+/*
+ * Print the correct instruction for constants.
+ */
+static void
+constput(NODE *p)
+{
+ CONSZ val = p->n_right->n_lval;
+ int reg = p->n_left->n_rval;
+
+ /* Only numeric constant */
+ if (p->n_right->n_name[0] == '\0') {
+ if (val == 0) {
+ printf("movei %s,0", rnames[reg]);
+ } else if ((val & 0777777000000LL) == 0) {
+ printf("movei %s,0%llo", rnames[reg], val);
+ } else if ((val & 0777777) == 0) {
+ printf("hrlzi %s,0%llo", rnames[reg], val >> 18);
+ } else {
+ printf("move %s,[ .long 0%llo]", rnames[reg],
+ szty(p->n_right->n_type) > 1 ? val :
+ val & 0777777777777LL);
+ }
+ /* Can have more tests here, hrloi etc */
+ return;
+ } else {
+ printf("xmovei %s,%s", rnames[reg], p->n_right->n_name);
+ if (val)
+ printf("+" CONFMT, val);
+ }
+}
+
+/*
+ * Return true if the constant can be bundled in an instruction (immediate).
+ */
+static int
+oneinstr(NODE *p)
+{
+ if (p->n_name[0] != '\0')
+ return 0;
+ if ((p->n_lval & 0777777000000ULL) != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Emit a halfword or byte instruction, from OREG to REG.
+ * Sign extension must also be done here.
+ */
+static void
+emitshort(NODE *p)
+{
+ CONSZ off = p->n_lval;
+ TWORD type = p->n_type;
+ int reg = p->n_rval;
+ int issigned = !ISUNSIGNED(type);
+ int ischar = type == CHAR || type == UCHAR;
+ int reg1 = getlr(p, '1')->n_rval;
+
+ if (off < 0) { /* argument, use move instead */
+ printf(" move ");
+ } else if (off == 0 && p->n_name[0] == 0) {
+ printf(" ldb %s,%s\n", rnames[reg1], rnames[reg]);
+ /* XXX must sign extend here even if not necessary */
+ switch (type) {
+ case CHAR:
+ printf(" lsh %s,033\n", rnames[reg1]);
+ printf(" ash %s,-033\n", rnames[reg1]);
+ break;
+ case SHORT:
+ printf(" hrre %s,%s\n",
+ rnames[reg1], rnames[reg1]);
+ break;
+ }
+ return;
+ } else if (ischar) {
+ if (off >= 0700000000000LL && p->n_name[0] != '\0') {
+ cerror("emitsh");
+ /* reg contains index integer */
+ if (!istreg(reg))
+ cerror("emitshort !istreg");
+ printf(" adjbp %s,[ .long 0%llo+%s ]\n",
+ rnames[reg], off, p->n_name);
+ printf(" ldb ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",%s\n", rnames[reg]);
+ goto signe;
+ }
+ printf(" ldb ");
+ adrput(stdout, getlr(p, '1'));
+ if (off)
+ printf(",[ .long 0%02o11%02o%06o ]\n",
+ (int)(27-(9*(off&3))), reg, (int)off/4);
+ else
+ printf(",%s\n", rnames[reg]);
+signe: if (issigned) {
+ printf(" lsh ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",033\n ash ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",-033\n");
+ }
+ return;
+ } else {
+ printf(" h%cr%c ", off & 1 ? 'r' : 'l',
+ issigned ? 'e' : 'z');
+ }
+ p->n_lval /= (ischar ? 4 : 2);
+ adrput(stdout, getlr(p, '1'));
+ putchar(',');
+ adrput(stdout, getlr(p, 'L'));
+ putchar('\n');
+}
+
+/*
+ * Store a short from a register. Destination is a OREG.
+ */
+static void
+storeshort(NODE *p)
+{
+ NODE *l = p->n_left;
+ CONSZ off = l->n_lval;
+ int reg = l->n_rval;
+ int ischar = BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR;
+
+ if (l->n_op == NAME) {
+ if (ischar) {
+ printf(" dpb ");
+ adrput(stdout, getlr(p, 'R'));
+ printf(",[ .long 0%02o%010o+%s ]\n",
+ 070+((int)off&3), (int)(off/4), l->n_name);
+ return;
+ }
+ printf(" hr%cm ", off & 1 ? 'r' : 'l');
+ l->n_lval /= 2;
+ adrput(stdout, getlr(p, 'R'));
+ putchar(',');
+ adrput(stdout, getlr(p, 'L'));
+ putchar('\n');
+ return;
+ }
+
+ if (off || reg == FPREG) { /* Can emit halfword instructions */
+ if (off < 0) { /* argument, use move instead */
+ printf(" movem ");
+ } else if (ischar) {
+ printf(" dpb ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",[ .long 0%02o11%02o%06o ]\n",
+ (int)(27-(9*(off&3))), reg, (int)off/4);
+ return;
+ } else {
+ printf(" hr%cm ", off & 1 ? 'r' : 'l');
+ }
+ l->n_lval /= 2;
+ adrput(stdout, getlr(p, 'R'));
+ putchar(',');
+ adrput(stdout, getlr(p, 'L'));
+ } else {
+ printf(" dpb ");
+ adrput(stdout, getlr(p, 'R'));
+ putchar(',');
+ l = getlr(p, 'L');
+ l->n_op = REG;
+ adrput(stdout, l);
+ l->n_op = OREG;
+ }
+ putchar('\n');
+}
+
+/*
+ * Multiply a register with a constant.
+ */
+static void
+imuli(NODE *p)
+{
+ NODE *r = p->n_right;
+
+ if (r->n_lval >= 0 && r->n_lval <= 0777777) {
+ printf(" imuli ");
+ adrput(stdout, getlr(p, 'L'));
+ printf(",0%llo\n", r->n_lval);
+ } else {
+ printf(" imul ");
+ adrput(stdout, getlr(p, 'L'));
+ printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
+ }
+}
+
+/*
+ * Divide a register with a constant.
+ */
+static void
+idivi(NODE *p)
+{
+ NODE *r = p->n_right;
+
+ if (r->n_lval >= 0 && r->n_lval <= 0777777) {
+ printf(" idivi ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",0%llo\n", r->n_lval);
+ } else {
+ printf(" idiv ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL);
+ }
+}
+
+/*
+ * move a constant into a register.
+ */
+static void
+xmovei(NODE *p)
+{
+ /*
+ * Trick: If this is an unnamed constant, just move it directly,
+ * otherwise use xmovei to get section number.
+ */
+ if (p->n_name[0] == '\0' || p->n_lval > 0777777) {
+ printf(" ");
+ zzzcode(p, 'D');
+ putchar(' ');
+ adrput(stdout, getlr(p, '1'));
+ putchar(',');
+ zzzcode(p, 'E');
+ } else {
+ printf(" xmovei ");
+ adrput(stdout, getlr(p, '1'));
+ printf(",%s", p->n_name);
+ if (p->n_lval != 0)
+ printf("+0%llo", p->n_lval);
+ }
+ putchar('\n');
+}
+
+static void
+printcon(NODE *p)
+{
+ CONSZ cz;
+
+ p = p->n_left;
+ if (p->n_lval >= 0700000000000LL) {
+ /* converted to pointer in clocal() */
+ conput(p);
+ return;
+ }
+ if (p->n_lval == 0 && p->n_name[0] == '\0') {
+ putchar('0');
+ return;
+ }
+ if (BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR)
+ cz = (p->n_lval/4) | ((p->n_lval & 3) << 30);
+ else
+ cz = (p->n_lval/2) | (((p->n_lval & 1) + 5) << 30);
+ cz |= 0700000000000LL;
+ printf("0%llo", cz);
+ if (p->n_name[0] != '\0')
+ printf("+%s", p->n_name);
+}
+
+static void
+putcond(NODE *p)
+{
+ char *c;
+
+ switch (p->n_op) {
+ case EQ: c = "e"; break;
+ case NE: c = "n"; break;
+ case LE: c = "le"; break;
+ case LT: c = "l"; break;
+ case GT: c = "g"; break;
+ case GE: c = "ge"; break;
+ default:
+ cerror("putcond");
+ }
+ printf("%s", c);
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *l;
+ CONSZ hval;
+
+ switch (c) {
+ case 'A': /* ildb right arg */
+ adrput(stdout, p->n_left->n_left);
+ break;
+
+ case 'B': /* remove from stack after subroutine call */
+ if (p->n_rval)
+ printf(" subi %%17,0%o\n", p->n_rval/SZINT);
+ break;
+
+ case 'C':
+ constput(p);
+ break;
+
+ case 'D': /* Find out which type of const load insn to use */
+ if (p->n_op != ICON)
+ cerror("zzzcode not ICON");
+ if (p->n_name[0] == '\0') {
+ if ((p->n_lval <= 0777777) && (p->n_lval > 0))
+ printf("movei");
+ else if ((p->n_lval & 0777777) == 0)
+ printf("hrlzi");
+ else
+ printf("move");
+ } else
+ printf("move");
+ break;
+
+ case 'E': /* Print correct constant expression */
+ if (p->n_name[0] == '\0') {
+ if ((p->n_lval <= 0777777) && (p->n_lval > 0)){
+ printf("0%llo", p->n_lval);
+ } else if ((p->n_lval & 0777777) == 0) {
+ printf("0%llo", p->n_lval >> 18);
+ } else {
+ if (p->n_lval < 0)
+ printf("[ .long -0%llo]", -p->n_lval);
+ else
+ printf("[ .long 0%llo]", p->n_lval);
+ }
+ } else {
+ if (p->n_lval == 0)
+ printf("[ .long %s]", p->n_name);
+ else
+ printf("[ .long %s+0%llo]",
+ p->n_name, p->n_lval);
+ }
+ break;
+
+ case 'P':
+ p = getlr(p, 'R');
+ /* FALLTHROUGH */
+ case 'O':
+ /*
+ * Print long long expression.
+ */
+ hval = gethval(p->n_lval);
+ printf("[ .long 0%llo,0%llo", hval,
+ (p->n_lval & 0377777777777LL) | (hval & 0400000000000LL));
+ if (p->n_name[0] != '\0')
+ printf("+%s", p->n_name);
+ printf(" ]");
+ break;
+
+ case 'F': /* Print an "opsimp" instruction based on its const type */
+ hopcode(oneinstr(p->n_right) ? 'C' : 'R', p->n_op);
+ break;
+
+ case 'H': /* Print a small constant */
+ p = p->n_right;
+ printf("0%llo", p->n_lval & 0777777);
+ break;
+
+ case 'Q': /* two-param long long comparisions */
+ twollcomp(p);
+ break;
+
+ case 'R': /* two-param conditionals */
+ twocomp(p);
+ break;
+
+ case 'U':
+ emitshort(p);
+ break;
+
+ case 'V':
+ storeshort(p);
+ break;
+
+ case 'Z':
+ ptrcomp(p);
+ break;
+
+ case 'a':
+ imuli(p);
+ break;
+
+ case 'b':
+ idivi(p);
+ break;
+
+ case 'c':
+ xmovei(p);
+ break;
+
+ case 'd':
+ printcon(p);
+ break;
+
+ case 'e':
+ putcond(p);
+ break;
+
+ case 'g':
+ if (p->n_right->n_op != OREG || p->n_right->n_lval != 0)
+ comperr("bad Zg oreg");
+ printf("%s", rnames[p->n_right->n_rval]);
+ break;
+
+#if 0
+ case '1': /* double upput */
+ p = getlr(p, '1');
+ p->n_rval += 2;
+ adrput(stdout, p);
+ p->n_rval -= 2;
+ break;
+#endif
+
+ case 'i': /* Write instruction for short load from name */
+ l = getlr(p, 'L');
+ printf(" h%cr%c %s,%s+" CONFMT "\n",
+ l->n_lval & 1 ? 'r' : 'l',
+ ISUNSIGNED(p->n_type) ? 'z' : 'e',
+ rnames[getlr(p, '1')->n_rval],
+ l->n_name, l->n_lval >> 1);
+ break;
+
+ default:
+ cerror("zzzcode %c", c);
+ }
+}
+
+/* set up temporary registers */
+void
+setregs()
+{
+ fregs = 7; /* 7 free regs on PDP10 (1-7) */
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int
+flshape(NODE *p)
+{
+ register int o = p->n_op;
+
+ return (o == REG || o == NAME || o == ICON ||
+ (o == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)));
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+int
+shtemp(NODE *p)
+{
+ 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);
+}
+
+int
+shumul(NODE *p)
+{
+ register int o;
+
+ if (x2debug) {
+ int val;
+ printf("shumul(%p)\n", p);
+ eprint(p, 0, &val, &val);
+ }
+
+ o = p->n_op;
+#if 0
+ if (o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON)
+ return(STARNM);
+#endif
+
+ if ((o == INCR) &&
+ (p->n_left->n_op == REG && p->n_right->n_op == ICON) &&
+ p->n_right->n_name[0] == '\0') {
+ switch (p->n_type) {
+ case CHAR|PTR:
+ case UCHAR|PTR:
+ o = 1;
+ break;
+
+ case SHORT|PTR:
+ case USHORT|PTR:
+ o = 2;
+ break;
+
+ case INT|PTR:
+ case UNSIGNED|PTR:
+ case LONG|PTR:
+ case ULONG|PTR:
+ case FLOAT|PTR:
+ o = 4;
+ break;
+
+ case DOUBLE|PTR:
+ case LONGLONG|PTR:
+ case ULONGLONG|PTR:
+ o = 8;
+ break;
+
+ default:
+ if (ISPTR(p->n_type) &&
+ ISPTR(DECREF(p->n_type))) {
+ o = 4;
+ break;
+ } else
+ return(0);
+ }
+ return( 0);
+ }
+
+ return( 0 );
+}
+
+void
+adrcon(CONSZ val)
+{
+ cerror("adrcon: val %llo\n", val);
+}
+
+void
+conput(NODE *p)
+{
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_lval != 0) {
+ acon(stdout, p);
+ if (p->n_name[0] != '\0')
+ putchar('+');
+ }
+ if (p->n_name[0] != '\0')
+ printf("%s", p->n_name);
+ if (p->n_name[0] == '\0' && p->n_lval == 0)
+ putchar('0');
+ return;
+
+ case REG:
+ putstr(rnames[p->n_rval]);
+ return;
+
+ default:
+ cerror("illegal conput");
+ }
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+ cerror("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 /= SZLONG;
+ switch (p->n_op) {
+ case REG:
+ putstr(rnames[p->n_rval + size]);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ printf(CONFMT, p->n_lval >> (36 * size));
+ break;
+ default:
+ cerror("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+void
+adrput(FILE *fp, 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 NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, fp);
+ if (p->n_lval != 0)
+ fprintf(fp, "+" CONFMT, p->n_lval & 0777777777777LL);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+#if 0
+ if (R2TEST(r)) { /* double indexing */
+ register int flags;
+
+ flags = R2UPK3(r);
+ if (flags & 1)
+ putc('*', fp);
+ if (flags & 4)
+ putc('-', fp);
+ if (p->n_lval != 0 || p->n_name[0] != '\0')
+ acon(p);
+ if (R2UPK1(r) != 100)
+ printf("(%s)", rnames[R2UPK1(r)]);
+ if (flags & 2)
+ putchar('+');
+ printf("[%s]", rnames[R2UPK2(r)]);
+ return;
+ }
+#endif
+ if (R2TEST(r))
+ cerror("adrput: unwanted double indexing: r %o", r);
+ if (p->n_rval != FPREG && p->n_lval < 0 && p->n_name[0]) {
+ fprintf(fp, "%s", p->n_name);
+ acon(fp, p);
+ fprintf(fp, "(%s)", rnames[p->n_rval]);
+ return;
+ }
+ if (p->n_lval < 0 && p->n_rval == FPREG && offarg) {
+ p->n_lval -= offarg-2; acon(fp, p); p->n_lval += offarg-2;
+ } else if (p->n_lval != 0)
+ acon(fp, p);
+ if (p->n_name[0] != '\0')
+ fprintf(fp, "%s%s", p->n_lval ? "+" : "", p->n_name);
+ if (p->n_lval > 0 && p->n_rval == FPREG && offlab)
+ fprintf(fp, "+" LABFMT, offlab);
+ if (p->n_lval < 0 && p->n_rval == FPREG && offarg)
+ fprintf(fp, "(017)");
+ else
+ fprintf(fp, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ if (p->n_lval > 0) {
+ acon(fp, p);
+ if (p->n_name[0] != '\0')
+ putc('+', fp);
+ }
+ if (p->n_name[0] != '\0')
+ fprintf(fp, "%s", p->n_name);
+ if (p->n_lval < 0)
+ acon(fp, p);
+ if (p->n_name[0] == '\0' && p->n_lval == 0)
+ putc('0', fp);
+ return;
+
+ case REG:
+ fputs(rnames[p->n_rval], fp);
+ return;
+
+ case MOVE: /* Specially generated node */
+ fputs(rnames[p->n_rall], fp);
+ return;
+
+ default:
+ cerror("illegal address, op %d", p->n_op);
+ return;
+
+ }
+}
+
+/*
+ * print out a constant
+*/
+void
+acon(FILE *fp, NODE *p)
+{
+ if (p->n_lval < 0 && p->n_lval > -0777777777777ULL)
+ fprintf(fp, "-" CONFMT, -p->n_lval);
+ else
+ fprintf(fp, CONFMT, p->n_lval);
+}
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o,int lab)
+{
+}
+
+/*
+ * Do some local optimizations that must be done after optim is called.
+ */
+static void
+optim2(NODE *p)
+{
+ int op = p->n_op;
+ int m, ml;
+ NODE *l;
+
+ /* Remove redundant PCONV's */
+ if (op == PCONV) {
+ l = p->n_left;
+ m = BTYPE(p->n_type);
+ ml = BTYPE(l->n_type);
+ if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT ||
+ m == DOUBLE || m == STRTY || m == UNIONTY || m == ENUMTY ||
+ m == UNSIGNED || m == ULONG || m == ULONGLONG) &&
+ (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT ||
+ ml == DOUBLE || ml == STRTY || ml == UNIONTY ||
+ ml == ENUMTY || ml == UNSIGNED || ml == ULONG ||
+ ml == ULONGLONG) && ISPTR(l->n_type)) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ } else
+ if (ISPTR(DECREF(p->n_type)) &&
+ (l->n_type == INCREF(STRTY))) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ } else
+ if (ISPTR(DECREF(l->n_type)) &&
+ (p->n_type == INCREF(INT) ||
+ p->n_type == INCREF(STRTY) ||
+ p->n_type == INCREF(UNSIGNED))) {
+ *p = *l;
+ nfree(l);
+ op = p->n_op;
+ }
+
+ }
+ /* Add constands, similar to the one in optim() */
+ if (op == PLUS && p->n_right->n_op == ICON) {
+ l = p->n_left;
+ if (l->n_op == PLUS && l->n_right->n_op == ICON &&
+ (p->n_right->n_name[0] == '\0' ||
+ l->n_right->n_name[0] == '\0')) {
+ l->n_right->n_lval += p->n_right->n_lval;
+ if (l->n_right->n_name[0] == '\0')
+ l->n_right->n_name = p->n_right->n_name;
+ nfree(p->n_right);
+ *p = *l;
+ nfree(l);
+ }
+ }
+
+ /* Convert "PTR undef" (void *) to "PTR uchar" */
+ /* XXX - should be done in MI code */
+ if (BTYPE(p->n_type) == VOID)
+ p->n_type = (p->n_type & ~BTMASK) | UCHAR;
+ if (op == ICON) {
+ if ((p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR))
+ && p->n_lval == 0 && p->n_name[0] != '\0')
+ p->n_lval = 0700000000000LL;
+ if ((p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT))
+ && p->n_lval == 0 && p->n_name[0] != '\0')
+ p->n_lval = 0750000000000LL;
+ }
+ if (op == MINUS) {
+ if ((p->n_left->n_type == (PTR|CHAR) ||
+ p->n_left->n_type == (PTR|UCHAR)) &&
+ (p->n_right->n_type == (PTR|CHAR) ||
+ p->n_right->n_type == (PTR|UCHAR))) {
+ l = talloc();
+ l->n_op = SCONV;
+ l->n_type = INT;
+ l->n_left = p->n_right;
+ p->n_right = l;
+ l = talloc();
+ l->n_op = SCONV;
+ l->n_type = INT;
+ l->n_left = p->n_left;
+ p->n_left = l;
+ }
+ }
+}
+
+void
+myreader(NODE *p)
+{
+ int e2print(NODE *p, int down, int *a, int *b);
+ walkf(p, optim2);
+ if (x2debug) {
+ printf("myreader final tree:\n");
+ fwalk(p, e2print, 0);
+ }
+}
+
+/*
+ * 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);
+}
+
+/*
+ * Remove last goto.
+ */
+void
+myoptim(struct interpass *ip)
+{
+ while (ip->sqelem.sqe_next->type != IP_EPILOG)
+ ip = ip->sqelem.sqe_next;
+ if (ip->type != IP_NODE || ip->ip_node->n_op != GOTO)
+ cerror("myoptim");
+ tfree(ip->ip_node);
+ *ip = *ip->sqelem.sqe_next;
+}
diff --git a/usr.bin/pcc/arch/pdp10/macdefs.h b/usr.bin/pcc/arch/pdp10/macdefs.h
new file mode 100644
index 00000000000..600427e554f
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/macdefs.h
@@ -0,0 +1,148 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:29 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ * Assume: If only one value; store at left side (char size), otherwise
+ * treat it as an integer.
+ */
+#define makecc(val,i) { \
+ if (i == 0) { lastcon = val; \
+ } else if (i == 1) { lastcon = (lastcon << 9) | val; lastcon <<= 18; \
+ } else { lastcon |= (val << (27 - (i * 9))); } }
+
+#define ARGINIT 36 /* # bits below fp where arguments start */
+#define AUTOINIT 36 /* # bits above fp where automatics start */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 9
+#define SZINT 36
+#define SZFLOAT 36
+#define SZDOUBLE 72
+#define SZLONG 36
+#define SZSHORT 18
+#define SZPOINT 36
+#define SZLONGLONG 72
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 9
+#define ALINT 36
+#define ALFLOAT 36
+#define ALDOUBLE 36
+#define ALLONG 36
+#define ALLONGLONG 36
+#define ALSHORT 18
+#define ALPOINT 36
+#define ALSTRUCT 36
+#define ALSTACK 36
+
+/*
+ * Max values.
+ */
+#define MAX_INT 0377777777777LL
+#define MAX_UNSIGNED 0777777777777ULL
+#define MAX_LONG 0377777777777LL
+#define MAX_ULONG 0777777777777ULL
+#define MAX_LONGLONG 000777777777777777777777LL /* XXX cross */
+#define MAX_ULONGLONG 001777777777777777777777ULL /* XXX cross */
+
+/* Default char is unsigned */
+#define CHAR_UNSIGNED
+
+/*
+ * Use large-enough types.
+ */
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "0%llo" /* format for printing constants */
+#define LABFMT "L%d" /* format for printing labels */
+
+#define FPREG 016 /* frame pointer */
+#define STKREG 017 /* stack pointer */
+
+/*
+ * Maximum and minimum register variables
+ */
+#define MINRVAR 010 /* use 10 thru ... */
+#define MAXRVAR 015 /* ... 15 */
+
+#define PARAMS_UPWARD /* stack grows upwards for parameters */
+#undef BACKAUTO /* stack grows negatively for automatics */
+#undef BACKTEMP /* stack grows negatively for temporaries */
+
+#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#undef RTOLBYTES /* bytes are numbered left to right */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+/* Definitions mostly used in pass2 */
+
+#define REGSZ 020
+#define TMPREG 016
+
+#define BYTEOFF(x) ((x)&03)
+#define wdal(k) (BYTEOFF(k)==0)
+#define BITOOR(x) ((x)/36) /* bit offset to oreg offset */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+#define genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
+
+#define shltype(o, p) \
+ ((o) == REG || (o) == NAME || (o) == ICON || \
+ (o) == OREG || ((o) == UMUL && shumul((p)->n_left)))
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+
+#undef SPECIAL_INTEGERS
+
+/*
+ * Special shapes used in code generation.
+ */
+#define SUSHCON (SPECIAL|6) /* unsigned short constant */
+#define SNSHCON (SPECIAL|7) /* negative short constant */
+#define SILDB (SPECIAL|8) /* use ildb here */
+
diff --git a/usr.bin/pcc/arch/pdp10/order.c b/usr.bin/pcc/arch/pdp10/order.c
new file mode 100644
index 00000000000..b548c294b8d
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/order.c
@@ -0,0 +1,187 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:29 otto Exp $ */
+/*
+ * 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"
+
+int canaddr(NODE *);
+
+/*
+ * should the assignment op p be stored,
+ * given that it lies as the right operand of o
+ * (or the left, if o==UMUL)
+ */
+void
+stoasg(NODE *p, int o)
+{
+ if (x2debug)
+ printf("stoasg(%p, %o)\n", p, o);
+}
+
+/* should we delay the INCR or DECR operation p */
+int
+deltest(NODE *p)
+{
+ TWORD ty = p->n_type;
+
+ return ty == PTR+CHAR || ty == PTR+UCHAR ||
+ ty == PTR+SHORT || ty == PTR+USHORT;
+}
+
+/*
+ * Check if p can be autoincremented.
+ * Nothing can be autoincremented on PDP10.
+ */
+int
+autoincr(NODE *p)
+{
+ return 0;
+}
+
+/* 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 */
+}
+
+int radebug = 0;
+
+int
+offstar(NODE *p)
+{
+ NODE *q;
+
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if( p->n_op == PLUS || p->n_op == MINUS ){
+ if( p->n_right->n_op == ICON ){
+ q = p->n_left;
+ if (q->n_op != REG)
+ geninsn(q, INTAREG|INAREG);
+ p->n_su = -1;
+ return 1;
+ }
+ }
+ geninsn(p, INTAREG|INAREG);
+ return 0;
+}
+
+/*
+ * Rewrite increment/decrement operation.
+ */
+int
+setincr(NODE *p)
+{
+ if (x2debug)
+ printf("setincr(%p)\n", p);
+
+ return(0);
+}
+
+/*
+ * findops() failed, see if we can rewrite it to match.
+ */
+int
+setbin(NODE *p)
+{
+ TWORD ty;
+ NODE *r, *s;
+
+ ty = p->n_type;
+ switch (p->n_op) {
+ case MINUS:
+ switch (ty) {
+ case PTR+CHAR:
+ case PTR+UCHAR:
+ case PTR+SHORT:
+ case PTR+USHORT:
+ /*
+ * Must negate the right side and change op to PLUS.
+ */
+ r = p->n_right;
+ if (r->n_op == ICON) {
+ r->n_lval = -r->n_lval;
+ } else {
+ s = talloc();
+ s->n_type = r->n_type;
+ s->n_op = UMINUS;
+ s->n_left = r;
+ p->n_right = s;
+ }
+ p->n_op = PLUS;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* setup for assignment operator */
+int
+setasg(NODE *p, int cookie)
+{
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+int
+special(NODE *p, int shape)
+{
+ switch (shape) {
+ case SUSHCON:
+ if (p->n_op == ICON && p->n_name[0] == '\0' &&
+ (p->n_lval > 0 && p->n_lval <= 0777777))
+ return 1;
+ break;
+
+ case SNSHCON:
+ if (p->n_op == ICON && p->n_name[0] == '\0' &&
+ (p->n_lval < 0 && p->n_lval > -01000000))
+ return 1;
+ break;
+ case SILDB:
+ if (p->n_op == ASSIGN && p->n_left->n_op == REG &&
+ p->n_right->n_op == PLUS &&
+ p->n_right->n_left->n_op == REG &&
+ p->n_right->n_right->n_op == ICON &&
+ p->n_right->n_right->n_lval == 1 &&
+ p->n_right->n_left->n_rval == p->n_left->n_rval)
+ return 1;
+ break;
+ }
+ return 0;
+}
diff --git a/usr.bin/pcc/arch/pdp10/table.c b/usr.bin/pcc/arch/pdp10/table.c
new file mode 100644
index 00000000000..321b88cb94e
--- /dev/null
+++ b/usr.bin/pcc/arch/pdp10/table.c
@@ -0,0 +1,1153 @@
+/* $Id: table.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * 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
+
+struct optab table[] = {
+{ -1, FORREW,SANY,TANY,SANY,TANY,REWRITE,-1,"", },
+/*
+ * A bunch of pointer conversions.
+ * First pointer to integer.
+ */
+/* Convert char pointer to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR,
+ SANY, TWORD,
+ NAREG, RLEFT,
+ " lsh AL,2\n"
+ " move A1,AL\n"
+ " lsh A1,-040\n"
+ " trz A1,074\n"
+ " ior AL,A1\n"
+ " tlz AL,0740000\n", },
+
+/* Convert short pointer to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TSHORT|TUSHORT,
+ SANY, TWORD,
+ NAREG, RLEFT,
+ " lsh AL,2\n"
+ " move A1,AL\n"
+ " lsh A1,-041\n"
+ " trz A1,2\n"
+ " ior AL,A1\n"
+ " tlz AL,0740000\n", },
+
+/* Convert int/unsigned/long/ulong/struct/union/func ptr to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TWORD|TSTRUCT|TPOINT,
+ SANY, TWORD,
+ 0, RLEFT,
+ " lsh AL,2\n", },
+
+/*
+ * Convert int/long to pointers.
+ */
+/* Convert int to char pointer */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ NAREG, RLEFT,
+ " move A1,AL\n"
+ " lsh A1,036\n"
+ " tlo A1,0700000\n"
+ " tlz A1,0040000\n"
+ " lsh AL,-2\n"
+ " ior AL,A1\n", },
+
+/* Convert int/long to short pointer */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ NAREG, RLEFT,
+ " move A1,AL\n"
+ " lsh AL,-2\n"
+ " tlo AL,0750000\n"
+ " lsh A1,035\n"
+ " tlz A1,0760000\n"
+ " add AL,A1\n", },
+
+/* Convert int/long to int/struct/multiple ptr */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPOINT|TWORD|TSTRUCT,
+ 0, RLEFT,
+ " lsh AL,-2\n", },
+
+/*
+ * Pointer to pointer conversions.
+ */
+/* Convert char ptr to short ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TCHAR|TUCHAR,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " tlo AL,050000\n"
+ " tlne AL,020000\n"
+ " tlz AL,010000\n", },
+
+/* Convert char/short pointer to int/struct/multiple ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TPOINT|TWORD|TSTRUCT,
+ 0, RLEFT,
+ " tlz AL,0770000\n", },
+
+/* Convert short pointer to char ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TSHORT|TUSHORT,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ 0, RLEFT,
+ " tlz AL,050000\n", },
+
+/* Convert int/struct/foo pointer to char ptr */
+{ PCONV, INTAREG,
+ STAREG, TPOINT|TWORD|TSTRUCT,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ 0, RLEFT,
+ " tlo AL,0700000\n", },
+
+/* Convert int/struct/foo pointer to short ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TWORD|TSTRUCT,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " tlo AL,0750000\n", },
+
+/*
+ * A bunch conversions of integral<->integral types
+ */
+
+/* convert short/char to int. This is done when register is loaded */
+{ SCONV, INTAREG,
+ STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
+ SANY, TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert int to short/char. This is done when register is loaded */
+{ SCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert int/long to unsigned long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TULONGLONG,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " setz A1,\n"
+ " tlze U1,0400000\n"
+ " tro A1,01\n" , },
+
+/* convert int/long to long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TLONGLONG,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " move A1,U1\n"
+ " ash A1,-043\n", },
+
+/* convert uchar/ushort to (unsigned) long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TUCHAR|TUSHORT,
+ SANY, TLL,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " setz A1,\n", },
+
+/* convert long long to int/long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n", },
+
+/* convert long long to unsigned char - XXX - signed char */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n"
+ " andi A1,0777\n", },
+
+/* convert long long to short - XXX - signed short */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n"
+ " hrrz A1,A1\n", },
+
+/* floating point conversions */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TDOUBLE|TFLOAT,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " fix A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TFLOAT,
+ NAREG|NASL, RESC1,
+ " fltr A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TDOUBLE,
+ NAREG|NASL, RESC1,
+ " fltr A1,AL\n setz U1,\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TDOUBLE,
+ SANY, TFLOAT,
+ NAREG|NASL, RESC1,
+ " move A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TFLOAT,
+ SANY, TDOUBLE,
+ NAREG|NASL, RESC1,
+ " move A1,AL\n setz U1,\n", },
+
+/*
+ * Store constant initializers.
+ */
+{ INIT, FOREFF,
+ SCON, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RNOP,
+ " .long Zd\n", },
+{ INIT, FOREFF,
+ SCON, TANY,
+ SANY, TWORD|TPOINT,
+ 0, RNOP,
+ " .long CL\n", },
+
+{ INIT, FOREFF,
+ SCON, TANY,
+ SANY, TLL,
+ 0, RNOP,
+ " .long UL\n .long CL\n", },
+
+/*
+ * Subroutine calls.
+ */
+
+{ UCALL, INTAREG,
+ SCON, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG, RESC1, /* should be 0 */
+ " pushj 017,AL\nZB", },
+
+{ UCALL, INTAREG,
+ SAREG|STAREG, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " pushj 017,(AL)\nZB", },
+
+{ UCALL, INTAREG,
+ SNAME|SOREG, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG, RESC1, /* should be 0 */
+ " pushj 017,@AL\nZB", },
+
+/*
+ * MOVE nodes are usually inserted late (at register assignment).
+ */
+{ MOVE, FOREFF,
+ SANY, TWORD,
+ STAREG|SAREG|SNAME|SOREG, TWORD,
+ 0, RRIGHT,
+ " move AR,AL\n", },
+
+{ MOVE, FOREFF,
+ SANY, TLL,
+ STAREG|SAREG|SNAME|SOREG, TLL,
+ 0, RRIGHT,
+ " dmove AR,AL\n", },
+
+/*
+ * INCR can be slightly optimized.
+ */
+{ INCR, INTAREG,
+ STAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SONE, TANY,
+ NAREG, RESC1,
+ " move A1,AL\n"
+ " ibp AL\n", },
+
+#ifdef notyet
+/* Fix check of return value */
+{ INCR, FOREFF,
+ STAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SONE, TANY,
+ 0, 0,
+ " ibp AL\n", },
+#endif
+
+/*
+ * PLUS operators.
+ */
+/* Add a value to a char/short pointer */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD,
+ 0, RRIGHT,
+ " adjbp AR,AL\n", },
+
+/* No more search for char/short pointer addition */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE!\n", },
+
+/* Add char/short/int to register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " add AL,AR\n", },
+
+/* Add char/short/int to memory */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG, TWORD,
+ 0, RLEFT,
+ " addm AR,AL\n", },
+
+/* Add a small constant to a register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
+ SUSHCON, TWORD,
+ 0, RLEFT,
+ " addi AL,AR\n", },
+
+/* Add a larger constant to a register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
+ SCON, TWORD,
+ 0, RLEFT,
+ " add AL,[ .long AR ]\n", },
+
+/* Add long long to register */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " dadd AL,AR\n", },
+
+/* Add int (or int pointer) to register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " add AL,AR # foo \n", },
+
+/* char/short are allowed to be added if they are in registers */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " add AL,AR\n", },
+
+/* get address of an memory position into a register */
+{ PLUS, INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPTRTO,
+ SCON, TANY,
+ NAREG, RESC1,
+ " xmovei A1,AR(AL)\n", },
+
+/* Safety belt for plus */
+{ PLUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * MINUS operators.
+ */
+/* Rewrite subtracts from char/short pointers (to negative adds) */
+{ MINUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SANY, TANY,
+ REWRITE, BITYPE,
+ "DIEDIEDIE", },
+
+/* Subtract char/short/int word in memory from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " sub AL,AR\n", },
+
+/* Subtract a small constant from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SUSHCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " subi AL,AR\n", },
+
+/* Subtract a large constant from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " sub AL,[ .long AR ]\n", },
+
+/* Subtract char/short/int word in memory from reg, save in memory */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RRIGHT,
+ " subm AL,AR\n", },
+
+/* Subtract long long from register */
+{ MINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " dsub AL,AR\n", },
+
+/* char/short are allowed to be subtracted if they are in registers */
+{ MINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " sub AL,AR\n", },
+
+/* Safety belt for plus */
+{ MINUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * AND/OR/ER operators.
+ * Simpler that the ops above in that they only work on integral types.
+ */
+/* And char/short/int with integer memory */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " and AL,AR\n", },
+
+/* And char/short/int with register */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " and AL,AR\n", },
+
+/* And char/short/int with small constant */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " andi AL,AR\n", },
+
+/* And char/short/int with large constant */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " and AL,[ .long AR ]\n", },
+
+/* long long AND */
+{ AND, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " and AL,AR\n"
+ " and UL,UR\n", },
+
+/* Safety belt for AND */
+{ AND, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+
+/* OR char/short/int with integer memory */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " ior AL,AR\n", },
+
+/* OR char/short/int with register */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " ior AL,AR\n", },
+
+/* OR char/short/int with small constant */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " iori AL,AR\n", },
+
+/* OR char/short/int with large constant */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " ior AL,[ .long AR ]\n", },
+
+/* long long OR */
+{ OR, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " ior AL,AR\n"
+ " ior UL,UR\n", },
+
+/* Safety belt for OR */
+{ OR, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+
+/* ER char/short/int with integer memory */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " xor AL,AR\n", },
+
+/* ER char/short/int with register */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xor AL,AR\n", },
+
+/* ER char/short/int with small constant */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xori AL,AR\n", },
+
+/* ER char/short/int with large constant */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xor AL,[ .long AR ]\n", },
+
+/* long long ER */
+{ ER, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " xor AL,AR\n"
+ " xor UL,UR\n", },
+
+/* Safety belt for ER */
+{ ER, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * The next rules handle all shift operators.
+ */
+{ LS, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " lsh AL,(AR)\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " lsh AL,@AR\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TLL,
+ SCON, TANY,
+ 0, RLEFT,
+ " ashc AL,ZH\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TLL,
+ SAREG|STAREG /* |SNAME|SOREG */, TANY,
+ 0, RLEFT,
+ " ashc AL,(AR)\n", },
+
+{ RS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TSWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " ash AL,-ZH\n", },
+
+{ RS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TUWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " lsh AL,-ZH\n", },
+
+/* Safety belt for LS/RS */
+{ LS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+{ RS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+/* Match zeroed registers first */
+{ ASSIGN, INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SZERO, TANY,
+ 0, RLEFT,
+ " setz AL,\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SZERO, TANY,
+ 0, 0,
+ " setzm AL\n", },
+
+{ ASSIGN, INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SMONE, TANY,
+ 0, RLEFT,
+ " setom AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SMONE, TANY,
+ 0, 0,
+ " setom AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ STAREG|SAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " ZC\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG, TUCHAR|TUSHORT|TWORD|TPOINT|TFLOAT,
+ 0, RRIGHT,
+ " movem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG, TSHORT,
+ 0, 0,
+ " hrrem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " move AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
+ 0, RLEFT,
+ " move AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TLL|TDOUBLE,
+ SAREG|STAREG, TLL|TDOUBLE,
+ 0, RRIGHT,
+ " dmovem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SOREG|SNAME, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG|STAREG, TANY,
+ 0, RRIGHT,
+ "ZV", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUSHORT|TUCHAR,
+ SOREG, TANY,
+ 0, RLEFT,
+ " ldb AL,Zg\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SSCON, TANY,
+ 0, RLEFT,
+ " movei AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " move AL,[ .long AR]\n", },
+
+/*
+ * DIV/MOD/MUL
+ * These can be done way more efficient.
+ */
+/* long long div. XXX - work only with unsigned */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ (2*NAREG)|NASL, RESC1,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,AR\n", },
+
+/* long long div. with constant. XXX - work only with unsigned */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SCON, TLL,
+ (2*NAREG)|NASL, RESC1,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,ZP\n", },
+
+/* Simple divide. XXX - fix so next reg can be free */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RRIGHT,
+ " idivm AL,AR\n", },
+
+/* Safety belt for DIV */
+{ DIV, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* long long MOD */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 2*NAREG|NASL, RESC2,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,AR\n", },
+
+/* integer MOD */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 2*NAREG|NASL, RESC2,
+ " move A2,AL\n"
+ " setz A1,\n"
+ " idiv A1,AR\n", },
+
+/* integer MOD for char/short */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 2*NAREG|NASL, RESC2,
+ " move A2,AL\n"
+ " setz A1,\n"
+ " idiv A1,AR\n", },
+
+/* Safety belt for MOD */
+{ MOD, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* long long MUL */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 2*NAREG|NASL, RESC2,
+ " dmove A1,AL\n"
+ " dmul A1,AR\n", },
+
+/* integer multiply to memory*/
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG, TWORD,
+ 0, RLEFT,
+ " imulm AR,AL\n", },
+
+/* integer multiply */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " imul AL,AR\n", },
+
+/* integer multiply for char/short */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imul AL,AR\n", },
+
+/* integer multiply with small constant */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SUSHCON, TWORD,
+ 0, RLEFT,
+ " imuli AL,AR\n", },
+
+/* integer multiply with large constant */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " imul AL,[ .long AR ]\n", },
+
+/* Safety belt for MUL */
+{ MUL, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* read an indirect long long value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG, TPTRTO|TLL|TWORD,
+ SANY, TLL,
+ NAREG|NASL, RESC1,
+ " dmove A1,(AL)\n", },
+
+/* read an indirect integer value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " move A1,(AL)\n", },
+
+/* read an indirect value into register */
+{ UMUL, INTAREG,
+ SOREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ NAREG, RESC1,
+ " move A1,@AL\n", },
+
+/* read an indirect value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " ldb A1,AL\n", },
+
+#ifdef notyet
+/* Match tree shape for ildb */
+{ UMUL, INTAREG,
+ SANY, TANY,
+ SILDB, TUCHAR|TCHAR|TPTRTO,
+ NAREG, RESC1,
+ " ildb A1,ZA\n", },
+#endif
+
+/* Match char/short pointers first, requires special handling */
+{ OPLOG, FORCC,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RESCC,
+ "ZZ", },
+
+/* Can check anything by just comparing if EQ/NE */
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SZERO, TANY,
+ 0, RESCC,
+ " jumpZe AL,LC # bu\n", },
+
+{ EQ, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
+ 0, RESCC,
+ "ZR", },
+
+{ NE, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SOREG|SNAME|SCON, TSWORD,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT|TFLOAT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TLL|TDOUBLE, /* XXX - does double work here? */
+ SAREG|STAREG|SOREG|SNAME, TLL|TDOUBLE,
+ 0, RESCC,
+ "ZQ", },
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jrst LL\n", },
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SMONE, TLL,
+ NAREG, RESC1,
+ " seto A1,\n seto U1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SMONE, TANY,
+ NAREG, RESC1,
+ " seto A1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SZERO, TLL,
+ NAREG, RESC1,
+ " setz A1,\n setz U1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NAREG, RESC1,
+ " setz A1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SUSHCON, TLL,
+ NAREG, RESC1,
+ " setz A1,\n movei U1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SUSHCON, ANYFIXED,
+ NAREG, RESC1,
+ " movei A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, ANYFIXED,
+ SNSHCON, ANYFIXED,
+ NAREG, RESC1,
+ " hrroi A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, ANYFIXED,
+ SCON, ANYFIXED,
+ NAREG|NASR, RESC1,
+ " ZD A1,ZE # suspekt\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG|SOREG|SNAME, TWORD|TPOINT|TFLOAT,
+ NAREG|NASR, RESC1,
+ " move A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TLL,
+ SCON, TLL,
+ NAREG, RESC1,
+ " dmove A1,ZO\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TLL|TDOUBLE,
+ SANY, TLL|TDOUBLE,
+ NAREG|NASR, RESC1,
+ " dmove A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASR, RESC1,
+ "ZU", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SNAME, TUCHAR,
+ SNAME, TUCHAR,
+ NAREG|NASR, RESC1,
+ " ldb A1,[ .long AL ]\n" },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SNAME, TCHAR,
+ SNAME, TCHAR,
+ NAREG|NASR, RESC1,
+ " ldb A1,[ .long AL ]\n"
+ " ash A1,033\n"
+ " ash A1,-033\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SNAME, TSHORT|TUSHORT,
+ NAREG|NASR, RESC1,
+ "Zi", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ NAREG|NASR, RESC1,
+ "Zc", },
+
+{ OPLTYPE, INAREG,
+ SAREG|STAREG, TUSHORT|TUCHAR,
+ SAREG|STAREG, TUSHORT|TUCHAR|TWORD,
+ NAREG, RESC1,
+ " move A1,AL\n", },
+
+/*
+ * Negate a word.
+ */
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " movn A1,AL\n", },
+
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " movn AL,AL\n", },
+
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TLL,
+ NAREG|NASR, RESC1,
+ " dmovn A1,AL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n"
+ " setcm U1,UL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n", },
+
+/*
+ * Arguments to functions.
+ */
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TPOINT|TWORD,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,[ .long AL]\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|STAREG, TLL|TDOUBLE,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n push 017,UL\n", },
+
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+{ UMUL, DF( UMUL ), },
+
+{ INCR, DF(INCR), },
+
+{ DECR, DF(INCR), },
+
+{ ASSIGN, DF(ASSIGN), },
+
+{ OPLEAF, DF(NAME), },
+
+{ INIT, DF(INIT), },
+
+{ OPUNARY, DF(UMINUS), },
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
diff --git a/usr.bin/pcc/arch/vax/code.c b/usr.bin/pcc/arch/vax/code.c
new file mode 100644
index 00000000000..d048a337fd9
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/code.c
@@ -0,0 +1,452 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 "mfile1"
+#include <a.out.h>
+
+int proflg = 0; /* are we generating profiling code? */
+int strftn = 0; /* is the current function one which returns a value */
+int gdebug;
+int fdefflag; /* are we within a function definition ? */
+char NULLNAME[8];
+int labelno;
+
+branch( n ){
+ /* output a branch to label n */
+ /* exception is an ordinary function branching to retlab: then, return */
+ if( n == retlab && !strftn ){
+ printf( " ret\n" );
+ }
+ else printf( " jbr L%d\n", n );
+ }
+
+int lastloc = { -1 };
+
+short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
+#define LOG2SZ 9
+
+defalign(n) {
+ /* cause the alignment to become a multiple of n */
+ n /= SZCHAR;
+ if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
+ }
+
+locctr( l ){
+ register temp;
+ /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
+
+ if( l == lastloc ) return(l);
+ temp = lastloc;
+ lastloc = l;
+ switch( l ){
+
+ case PROG:
+ printf( " .text\n" );
+ psline();
+ break;
+
+ case DATA:
+ case ADATA:
+ printf( " .data\n" );
+ break;
+
+ case STRNG:
+ printf( " .data 1\n" );
+ break;
+
+ case ISTRNG:
+ printf( " .data 2\n" );
+ break;
+
+ case STAB:
+ printf( " .stab\n" );
+ break;
+
+ default:
+ cerror( "illegal location counter" );
+ }
+
+ return( temp );
+ }
+
+deflab( n ){
+ /* output something to define the current position as label n */
+ printf( "L%d:\n", n );
+ }
+
+int crslab = 10;
+
+getlab(){
+ /* return a number usable for a label */
+ return( ++crslab );
+ }
+
+
+int ent_mask[] = {
+ 0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
+
+int reg_use = 11;
+
+efcode(){
+ /* code for the end of a function */
+
+ if( strftn ){ /* copy output (in R2) to caller */
+ register NODE *l, *r;
+ register struct symtab *p;
+ register TWORD t;
+ register int j;
+ int i;
+
+ p = &stab[curftn];
+ t = p->stype;
+ t = DECREF(t);
+
+ deflab( retlab );
+
+ i = getlab(); /* label for return area */
+ printf(" .data\n" );
+ printf(" .align 2\n" );
+ printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
+ printf(" .text\n" );
+ psline();
+ printf(" movab L%d,r1\n", i);
+
+ reached = 1;
+ l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
+ l->rval = 1; /* R1 */
+ l->lval = 0; /* no offset */
+ r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
+ r->rval = 0; /* R0 */
+ r->lval = 0;
+ l = buildtree( UNARY MUL, l, NIL );
+ r = buildtree( UNARY MUL, r, NIL );
+ l = buildtree( ASSIGN, l, r );
+ l->op = FREE;
+ ecomp( l->left );
+ printf( " movab L%d,r0\n", i );
+ /* turn off strftn flag, so return sequence will be generated */
+ strftn = 0;
+ }
+ branch( retlab );
+ printf( " .set .R%d,0x%x\n", ftnno, ent_mask[reg_use] );
+ reg_use = 11;
+ p2bend();
+ fdefflag = 0;
+ }
+
+bfcode( a, n ) int a[]; {
+ /* code for the beginning of a function; a is an array of
+ indices in stab for the arguments; n is the number */
+ register i;
+ register temp;
+ register struct symtab *p;
+ int off;
+ char *toreg();
+
+ locctr( PROG );
+ p = &stab[curftn];
+ printf( " .align 1\n");
+ defnam( p );
+ temp = p->stype;
+ temp = DECREF(temp);
+ strftn = (temp==STRTY) || (temp==UNIONTY);
+
+ retlab = getlab();
+
+ /* routine prolog */
+
+ printf( " .word .R%d\n", ftnno);
+ if (gdebug) {
+ pstab(NULLNAME, N_SLINE);
+ printf("0,%d,LL%d\n", lineno, labelno);
+ printf("LL%d:\n", labelno++);
+ }
+ printf( " subl2 $.F%d,sp\n", ftnno);
+ if( proflg ) { /* profile code */
+ i = getlab();
+ printf(" movab L%d,r0\n", i);
+ printf(" jsb mcount\n");
+ printf(" .data\n");
+ printf(" .align 2\n");
+ printf("L%d: .long 0\n", i);
+ printf(" .text\n");
+ psline();
+ }
+
+ off = ARGINIT;
+
+ for( i=0; i<n; ++i ){
+ p = &stab[a[i]];
+ if( p->sclass == REGISTER ){
+ temp = p->offset; /* save register number */
+ p->sclass = PARAM; /* forget that it is a register */
+ p->offset = NOOFFSET;
+ oalloc( p, &off );
+/*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
+ p->offset = temp; /* remember register number */
+ p->sclass = REGISTER; /* remember that it is a register */
+ }
+ else {
+ if( oalloc( p, &off ) ) cerror( "bad argument" );
+ }
+
+ }
+ fdefflag = 1;
+ }
+
+bccode(){ /* called just before the first executable statment */
+ /* by now, the automatics and register variables are allocated */
+ SETOFF( autooff, SZINT );
+ /* set aside store area offset */
+ p2bbeg( autooff, regvar );
+ reg_use = (reg_use > regvar ? regvar : reg_use);
+ }
+
+ejobcode( flag ){
+ /* called just before final exit */
+ /* flag is 1 if errors, 0 if none */
+ }
+
+aobeg(){
+ /* called before removing automatics from stab */
+ }
+
+aocode(p) struct symtab *p; {
+ /* called when automatic p removed from stab */
+ }
+
+aoend(){
+ /* called after removing all automatics from stab */
+ }
+
+defnam( p ) register struct symtab *p; {
+ /* define the current location as the name p->sname */
+
+ if( p->sclass == EXTDEF ){
+ printf( " .globl %s\n", exname( p->sname ) );
+ }
+ if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
+ else printf( "%s:\n", exname( p->sname ) );
+
+ }
+
+bycode( t, i ){
+ /* put byte i+1 in a string */
+
+ i &= 07;
+ if( t < 0 ){ /* end of the string */
+ if( i != 0 ) printf( "\n" );
+ }
+
+ else { /* stash byte t into string */
+ if( i == 0 ) printf( " .byte " );
+ else printf( "," );
+ printf( "0x%x", t );
+ if( i == 07 ) printf( "\n" );
+ }
+ }
+
+zecode( n ){
+ /* n integer words of zeros */
+ OFFSZ temp;
+ if( n <= 0 ) return;
+ printf( " .space %d\n", (SZINT/SZCHAR)*n );
+ temp = n;
+ inoff += temp*SZINT;
+ }
+
+fldal( t ) unsigned t; { /* return the alignment of field of type t */
+ uerror( "illegal field type" );
+ return( ALINT );
+ }
+
+fldty( p ) struct symtab *p; { /* fix up type of field p */
+ ;
+ }
+
+where(c){ /* print location of error */
+ /* c is either 'u', 'c', or 'w' */
+ /* GCOS version */
+ fprintf( stderr, "%s, line %d: ", ftitle, lineno );
+ }
+
+
+/* tbl - toreg() returns a pointer to a char string
+ which is the correct "register move" for the passed type
+ */
+struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
+ {
+ CHAR, "cvtbl",
+ SHORT, "cvtwl",
+ INT, "movl",
+ LONG, "movl",
+ FLOAT, "movf",
+ DOUBLE, "movd",
+ UCHAR, "movzbl",
+ USHORT, "movzwl",
+ UNSIGNED, "movl",
+ ULONG, "movl",
+ -1, ""
+ };
+
+char
+*toreg(type)
+ TWORD type;
+{
+ struct type_move *p;
+
+ for ( p=toreg_strs; p->fromtype > 0; p++)
+ if (p->fromtype == type) return(p->tostrng);
+
+ /* type not found, must be a pointer type */
+ return("movl");
+}
+/* tbl */
+
+
+main( argc, argv ) char *argv[]; {
+ return(mainp1( argc, argv ));
+ }
+
+struct sw heapsw[SWITSZ]; /* heap for switches */
+
+genswitch(p,n) register struct sw *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
+ */
+ register i;
+ register CONSZ j, range;
+ register dlab, swlab;
+
+ range = p[n].sval-p[1].sval;
+
+ if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
+
+ swlab = getlab();
+ dlab = p->slab >= 0 ? p->slab : getlab();
+
+ /* already in r0 */
+ printf(" casel r0,$%ld,$%ld\n", p[1].sval, range);
+ printf("L%d:\n", swlab);
+ for( i=1,j=p[1].sval; i<=n; j++) {
+ printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
+ swlab);
+ }
+
+ if( p->slab >= 0 ) branch( dlab );
+ else printf("L%d:\n", dlab);
+ return;
+
+ }
+
+ if( n>8 ) { /* heap switch */
+
+ heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
+ makeheap(p, n, 1); /* build heap */
+
+ walkheap(1, n); /* produce code */
+
+ if( p->slab >= 0 )
+ branch( dlab );
+ else
+ printf("L%d:\n", dlab);
+ return;
+ }
+
+ /* debugging code */
+
+ /* out for the moment
+ if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
+ */
+
+ /* simple switch code */
+
+ for( i=1; i<=n; ++i ){
+ /* already in r0 */
+
+ printf( " cmpl r0,$" );
+ printf( CONFMT, p[i].sval );
+ printf( "\n jeql L%d\n", p[i].slab );
+ }
+
+ if( p->slab>=0 ) branch( p->slab );
+ }
+
+makeheap(p, m, n)
+register struct sw *p;
+{
+ register int q;
+
+ q = select(m);
+ heapsw[n] = p[q];
+ if( q>1 ) makeheap(p, q-1, 2*n);
+ if( q<m ) makeheap(p+q, m-q, 2*n+1);
+}
+
+select(m) {
+ register int l,i,k;
+
+ for(i=1; ; i*=2)
+ if( (i-1) > m ) break;
+ l = ((k = i/2 - 1) + 1)/2;
+ return( l + (m-k < l ? m-k : l));
+}
+
+walkheap(start, limit)
+{
+ int label;
+
+
+ if( start > limit ) return;
+ printf(" cmpl r0,$%d\n", heapsw[start].sval);
+ printf(" jeql L%d\n", heapsw[start].slab);
+ if( (2*start) > limit ) {
+ printf(" jbr L%d\n", heapsw[0].slab);
+ return;
+ }
+ if( (2*start+1) <= limit ) {
+ label = getlab();
+ printf(" jgtr L%d\n", label);
+ } else
+ printf(" jgtr L%d\n", heapsw[0].slab);
+ walkheap( 2*start, limit);
+ if( (2*start+1) <= limit ) {
+ printf("L%d:\n", label);
+ walkheap( 2*start+1, limit);
+ }
+}
diff --git a/usr.bin/pcc/arch/vax/local.c b/usr.bin/pcc/arch/vax/local.c
new file mode 100644
index 00000000000..82bc670eb6b
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/local.c
@@ -0,0 +1,528 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 "mfile1"
+
+/* this file contains code which is dependent on the target machine */
+
+NODE *
+cast( p, t ) register NODE *p; TWORD t; {
+ /* cast node p to type t */
+
+ p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
+ p->left->op = FREE;
+ p->op = FREE;
+ return( p->right );
+ }
+
+NODE *
+clocal(p) NODE *p; {
+
+ /* this 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 */
+
+ register struct symtab *q;
+ register NODE *r;
+ register o;
+ register m, ml;
+
+ switch( o = p->op ){
+
+ case NAME:
+ if( p->rval < 0 ) { /* already processed; ignore... */
+ return(p);
+ }
+ q = &stab[p->rval];
+ switch( q->sclass ){
+
+ case AUTO:
+ case PARAM:
+ /* fake up a structure reference */
+ r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
+ r->lval = 0;
+ r->rval = (q->sclass==AUTO?STKREG:ARGREG);
+ p = stref( block( STREF, r, p, 0, 0, 0 ) );
+ break;
+
+ case ULABEL:
+ case LABEL:
+ case STATIC:
+ if( q->slevel == 0 ) break;
+ p->lval = 0;
+ p->rval = -q->offset;
+ break;
+
+ case REGISTER:
+ p->op = REG;
+ p->lval = 0;
+ p->rval = q->offset;
+ break;
+
+ }
+ break;
+
+ case PCONV:
+ /* do pointer conversions for char and longs */
+ ml = p->left->type;
+ if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->left->op != ICON ) break;
+
+ /* pointers all have the same representation; the type is inherited */
+
+ inherit:
+ p->left->type = p->type;
+ p->left->cdim = p->cdim;
+ p->left->csiz = p->csiz;
+ p->op = FREE;
+ return( p->left );
+
+ case SCONV:
+ m = (p->type == FLOAT || p->type == DOUBLE );
+ ml = (p->left->type == FLOAT || p->left->type == DOUBLE );
+ if( m != ml ) break;
+
+ /* now, look for conversions downwards */
+
+ m = p->type;
+ ml = p->left->type;
+ if( p->left->op == ICON ){ /* simulate the conversion here */
+ CONSZ val;
+ val = p->left->lval;
+ switch( m ){
+ case CHAR:
+ p->left->lval = (char) val;
+ break;
+ case UCHAR:
+ p->left->lval = val & 0XFF;
+ break;
+ case USHORT:
+ p->left->lval = val & 0XFFFFL;
+ break;
+ case SHORT:
+ p->left->lval = (short)val;
+ break;
+ case UNSIGNED:
+ p->left->lval = val & 0xFFFFFFFFL;
+ break;
+ case INT:
+ p->left->lval = (int)val;
+ break;
+ }
+ p->left->type = m;
+ }
+ else {
+ /* meaningful ones are conversion of int to char, int to short,
+ and short to char, and unsigned version of them */
+ if( m==CHAR || m==UCHAR ){
+ if( ml!=CHAR && ml!= UCHAR ) break;
+ }
+ else if( m==SHORT || m==USHORT ){
+ if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break;
+ }
+ }
+
+ /* clobber conversion */
+ if( tlen(p) == tlen(p->left) ) goto inherit;
+ p->op = FREE;
+ return( p->left ); /* conversion gets clobbered */
+
+ case PVCONV:
+ case PMCONV:
+ if( p->right->op != ICON ) cerror( "bad conversion", 0);
+ p->op = FREE;
+ return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) );
+
+ case RS:
+ case ASG RS:
+ /* convert >> to << with negative shift count */
+ /* only if type of left operand is not unsigned */
+ if( ISUNSIGNED(p->left->type) ) break;
+ p->right = buildtree( UNARY MINUS, p->right, NIL );
+ if( p->op == RS ) p->op = LS;
+ else p->op = ASG LS;
+ break;
+
+ }
+
+ return(p);
+ }
+
+andable( p ) NODE *p; {
+ return(1); /* all names can have & taken on them */
+ }
+
+cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
+ autooff = AUTOINIT;
+ }
+
+cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
+
+ if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
+ || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */
+ || ISPTR(t)) return(1); /* tbl */
+ return(0);
+ }
+
+NODE *
+offcon( off, t, d, s ) OFFSZ off; TWORD t; {
+
+ /* 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 */
+
+ register NODE *p;
+
+ /* t, d, and s are the type, dimension offset, and sizeoffset */
+ /* in general they are necessary for offcon, but not on H'well */
+
+ p = bcon(0);
+ p->lval = off/SZCHAR;
+ return(p);
+
+ }
+
+
+incode( p, sz ) register NODE *p; {
+
+ /* generate initialization code for assigning a constant c
+ to a field of width sz */
+ /* we assume that the proper alignment has been obtained */
+ /* inoff is updated to have the proper final value */
+ /* we also assume sz < SZINT */
+
+ inoff += sz;
+ if (sz>SZSHORT)
+ printf(" .long %d:%d\n", sz, p->lval);
+ else if (sz>SZCHAR)
+ printf(" .word %d:%d\n", sz, p->lval);
+ else
+ printf(" .byte %d:%d\n", sz, p->lval);
+ }
+
+fincode( d, sz ) double d; {
+ /* output code to initialize space of size sz to the value d */
+ /* the proper alignment has been obtained */
+ /* inoff is updated to have the proper final value */
+ /* on the target machine, write it out in octal! */
+
+
+ printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
+ sz == SZDOUBLE ? 'd' : 'f', d);
+ inoff += sz;
+ }
+
+cinit( p, sz ) NODE *p; {
+ /* arrange for the initialization of p into a space of
+ size sz */
+ /* the proper alignment has been opbtained */
+ /* inoff is updated to have the proper final value */
+ ecode( p );
+ inoff += sz;
+ }
+
+vfdzero( n ){ /* define n bits of zeros in a vfd */
+ register i;
+
+ if( n <= 0 ) return;
+
+ inoff += n;
+ i = n;
+ while (i>=SZCHAR) {
+ printf(" .byte 0\n");
+ i -= SZCHAR;
+ }
+ if (i) printf(" .byte %d:0\n", i);
+ }
+
+
+char *
+exname( p ) char *p; {
+ /* make a name look like an external name in the local machine */
+
+ static char text[NCHNAM+1];
+
+ register i;
+
+ text[0] = '_';
+ for( i=1; *p&&i<NCHNAM; ++i ){
+ text[i] = *p++;
+ }
+
+ text[i] = '\0';
+ text[NCHNAM] = '\0'; /* truncate */
+
+ return( text );
+ }
+
+ctype( type ){ /* map types which are not defined on the local machine */
+ switch( BTYPE(type) ){
+
+ case LONG:
+ MODTYPE(type,INT);
+ break;
+
+ case ULONG:
+ MODTYPE(type,UNSIGNED);
+ }
+ return( type );
+ }
+
+noinit( t ) { /* curid is a variable which is defined but
+ is not initialized (and not a function );
+ This routine returns the stroage class for an uninitialized declaration */
+
+ return(EXTERN);
+
+ }
+
+commdec( id ){ /* make a common declaration for id, if reasonable */
+ register struct symtab *q;
+ OFFSZ off, tsize();
+
+ q = &stab[id];
+ printf( " .comm %s,", exname( q->sname ) );
+ off = tsize( q->stype, q->dimoff, q->sizoff );
+ printf( CONFMT, off/SZCHAR );
+ printf( "\n" );
+ }
+
+isitlong( cb, ce ){ /* is lastcon to be long or short */
+ /* cb is the first character of the representation, ce the last */
+
+ if( ce == 'l' || ce == 'L' ||
+ lastcon >= (1L << (SZINT-1) ) ) return (1);
+ return(0);
+ }
+
+
+isitfloat( s ) char *s; {
+ double atof();
+ dcon = atof(s);
+ return( FCON );
+ }
+
+ecode( p ) NODE *p; {
+
+ /* walk the tree and write out the nodes.. */
+
+ if( nerrors ) return;
+ p2tree( p );
+ p2compile( p );
+ }
+
+#include "a.out.h"
+int ddebug;
+int gdebug;
+
+
+outstab(p)
+struct symtab *p; {
+ register TWORD ptype;
+ register char *pname;
+ register char pclass;
+ register int poffset;
+
+ if (!gdebug) return;
+
+ ptype = p->stype;
+ pname = p->sname;
+ pclass = p->sclass;
+ poffset = p->offset;
+
+ if (ISFTN(ptype)) {
+ return;
+ }
+
+ switch (pclass) {
+
+ case AUTO:
+ pstab(pname, N_LSYM);
+ printf("0,%d,%d\n", ptype, (-poffset)/SZCHAR);
+ poffs(p);
+ return;
+
+ case EXTDEF:
+ case EXTERN:
+ pstab(pname, N_GSYM);
+ printf("0,%d,0\n", ptype);
+ poffs(p);
+ return;
+
+ case STATIC:
+ pstab(pname, N_STSYM);
+ if (p->slevel > 1) {
+ printf("0,%d,L%d\n", ptype, poffset);
+ } else {
+ printf("0,%d,%s\n", ptype, exname(pname));
+ }
+ poffs(p);
+ return;
+
+ case REGISTER:
+ pstab(pname, N_RSYM);
+ printf("0,%d,%d\n", ptype, poffset);
+ poffs(p);
+ return;
+
+ case MOS:
+ case MOU:
+ pstab(pname, N_SSYM);
+ printf("0,%d,%d\n", ptype, poffset/SZCHAR);
+ poffs(p);
+ return;
+
+ case PARAM:
+ /* parameter stab entries are processed in dclargs() */
+ return;
+
+ default:
+ if (ddebug) printf(" No .stab for %.8s\n", pname);
+ }
+}
+
+pstab(name, type)
+char *name;
+int type; {
+ register int i;
+ register char c;
+ if (!gdebug) return;
+ printf(" .stab ");
+ for(i=0; i<8; i++)
+ if (c = name[i]) printf("'%c,", c);
+ else printf("0,");
+ printf("0%o,", type);
+}
+
+poffs(p)
+register struct symtab *p; {
+ int s;
+ if (!gdebug) return;
+ if ((s = dimtab[p->sizoff]/SZCHAR) > 1) {
+ pstab(p->sname, N_LENG);
+ printf("1,0,%d\n", s);
+ }
+}
+
+char NULLNAME[8];
+int labelno;
+int fdefflag;
+
+psline() {
+ static int lastlineno;
+ register char *cp, *cq;
+ register int i;
+
+ if (!gdebug) return;
+
+ cq = ititle;
+ cp = ftitle;
+
+ while ( *cq ) if ( *cp++ != *cq++ ) goto neq;
+ if ( *cp == '\0' ) goto eq;
+
+neq: for (i=0; i<100; i++)
+ ititle[i] = '\0';
+ cp = ftitle;
+ cq = ititle;
+ while ( *cp )
+ *cq++ = *cp++;
+ *cq = '\0';
+ *--cq = '\0';
+ for ( cp = ititle+1; *(cp-1); cp += 8 ) {
+ pstab(cp, N_SOL);
+ if (gdebug) printf("0,0,LL%d\n", labelno);
+ }
+ *cq = '"';
+ printf("LL%d:\n", labelno++);
+
+eq: if (lineno == lastlineno) return;
+ lastlineno = lineno;
+
+ if (fdefflag) {
+ pstab(NULLNAME, N_SLINE);
+ printf("0,%d,LL%d\n", lineno, labelno);
+ printf("LL%d:\n", labelno++);
+ }
+ }
+
+plcstab(level) {
+ if (!gdebug) return;
+ pstab(NULLNAME, N_LBRAC);
+ printf("0,%d,LL%d\n", level, labelno);
+ printf("LL%d:\n", labelno++);
+ }
+
+prcstab(level) {
+ if (!gdebug) return;
+ pstab(NULLNAME, N_RBRAC);
+ printf("0,%d,LL%d\n", level, labelno);
+ printf("LL%d:\n", labelno++);
+ }
+
+pfstab(sname)
+char *sname; {
+ if (!gdebug) return;
+ pstab(sname, N_FUN);
+ printf("0,%d,_%.7s\n", lineno, sname);
+}
+
+#ifndef ONEPASS
+tlen(p) NODE *p;
+{
+ switch(p->type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(2);
+
+ case DOUBLE:
+ return(8);
+
+ default:
+ return(4);
+ }
+ }
+#endif
diff --git a/usr.bin/pcc/arch/vax/local2.c b/usr.bin/pcc/arch/vax/local2.c
new file mode 100644
index 00000000000..0aa8e2b0e9e
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/local2.c
@@ -0,0 +1,923 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 "mfile2"
+# include "ctype.h"
+/* a lot of the machine dependent parts of the second pass */
+
+# define BITMASK(n) ((1L<<n)-1)
+
+where(c){
+ fprintf( stderr, "%s, line %d: ", filename, lineno );
+ }
+
+lineid( l, fn ) char *fn; {
+ /* identify line l and file fn */
+ printf( "# line %d, file %s\n", l, fn );
+ }
+
+eobl2(){
+ OFFSZ spoff; /* offset from stack pointer */
+
+ spoff = maxoff;
+ if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
+ spoff /= SZCHAR;
+ SETOFF(spoff,4);
+ printf( " .set .F%d,%Ld\n", ftnno, spoff );
+ maxargs = -1;
+ }
+
+struct hoptab { int opmask; char * opstring; } ioptab[] = {
+
+ ASG PLUS, "add",
+ ASG MINUS, "sub",
+ ASG MUL, "mul",
+ ASG DIV, "div",
+ ASG OR, "bis",
+ ASG ER, "xor",
+ ASG AND, "bic",
+ PLUS, "add",
+ MINUS, "sub",
+ MUL, "mul",
+ DIV, "div",
+ OR, "bis",
+ ER, "xor",
+ AND, "bic",
+ -1, "" };
+
+hopcode( f, o ){
+ /* output the appropriate string from the above table */
+
+ register struct hoptab *q;
+
+ for( q = ioptab; q->opmask>=0; ++q ){
+ if( q->opmask == o ){
+ printf( "%s", q->opstring );
+/* tbl
+ if( f == 'F' ) printf( "e" );
+ else if( f == 'D' ) printf( "d" );
+ tbl */
+/* tbl */
+ switch( f ) {
+ case 'L':
+ case 'W':
+ case 'B':
+ case 'D':
+ case 'F':
+ printf("%c", tolower(f));
+ break;
+
+ }
+/* tbl */
+ return;
+ }
+ }
+ cerror( "no hoptab for %s", opst[o] );
+ }
+
+char *
+rnames[] = { /* keyed to register number tokens */
+
+ "r0", "r1",
+ "r2", "r3", "r4", "r5",
+ "r6", "r7", "r8", "r9", "r10", "r11",
+ "ap", "fp", "sp", "pc",
+
+ };
+
+int rstatus[] = {
+ SAREG|STAREG, SAREG|STAREG,
+ SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
+ SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
+ SAREG, SAREG, SAREG, SAREG,
+
+ };
+
+tlen(p) NODE *p;
+{
+ switch(p->type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(2);
+
+ case DOUBLE:
+ return(8);
+
+ default:
+ return(4);
+ }
+}
+
+mixtypes(p, q) NODE *p, *q;
+{
+ register tp, tq;
+
+ tp = p->type;
+ tq = q->type;
+
+ return( (tp==FLOAT || tp==DOUBLE) !=
+ (tq==FLOAT || tq==DOUBLE) );
+}
+
+prtype(n) NODE *n;
+{
+ switch (n->type)
+ {
+ case DOUBLE:
+ printf("d");
+ return;
+
+ case FLOAT:
+ printf("f");
+ return;
+
+ case LONG:
+ case ULONG:
+ case INT:
+ case UNSIGNED:
+ printf("l");
+ return;
+
+ case SHORT:
+ case USHORT:
+ printf("w");
+ return;
+
+ case CHAR:
+ case UCHAR:
+ printf("b");
+ return;
+
+ default:
+ if ( !ISPTR( n->type ) ) cerror("zzzcode- bad type");
+ else {
+ printf("l");
+ return;
+ }
+ }
+}
+
+zzzcode( p, c ) register NODE *p; {
+ register m;
+ CONSZ val;
+ switch( c ){
+
+ case 'N': /* logical ops, turned into 0-1 */
+ /* use register given by register 1 */
+ cbgen( 0, m=getlab(), 'I' );
+ deflab( p->label );
+ printf( " clrl %s\n", rnames[getlr( p, '1' )->rval] );
+ deflab( m );
+ return;
+
+ case 'I':
+ case 'P':
+ cbgen( p->op, p->label, c );
+ return;
+
+ case 'A':
+ {
+ register NODE *l, *r;
+
+ if (xdebug) eprint(p, 0, &val, &val);
+ r = getlr(p, 'R');
+ if (optype(p->op) == LTYPE || p->op == UNARY MUL)
+ {
+ l = resc;
+ l->type = (r->type==FLOAT || r->type==DOUBLE ? DOUBLE : INT);
+ }
+ else
+ l = getlr(p, 'L');
+ if (r->op == ICON && r->name[0] == '\0')
+ {
+ if (r->lval == 0)
+ {
+ printf("clr");
+ prtype(l);
+ printf(" ");
+ adrput(l);
+ return;
+ }
+ if (r->lval < 0 && r->lval >= -63)
+ {
+ printf("mneg");
+ prtype(l);
+ r->lval = -r->lval;
+ goto ops;
+ }
+ r->type = (r->lval < 0 ?
+ (r->lval >= -128 ? CHAR
+ : (r->lval >= -32768 ? SHORT
+ : INT )) : r->type);
+ r->type = (r->lval >= 0 ?
+ (r->lval <= 63 ? INT
+ : ( r->lval <= 127 ? CHAR
+ : (r->lval <= 255 ? UCHAR
+ : (r->lval <= 32767 ? SHORT
+ : (r->lval <= 65535 ? USHORT
+ : INT ))))) : r->type );
+ }
+ if (l->op == REG && l->type != FLOAT && l->type != DOUBLE)
+ l->type = INT;
+ if (!mixtypes(l,r))
+ {
+ if (tlen(l) == tlen(r))
+ {
+ printf("mov");
+ prtype(l);
+ goto ops;
+ }
+ else if (tlen(l) > tlen(r) && ISUNSIGNED(r->type))
+ {
+ printf("movz");
+ }
+ else
+ {
+ printf("cvt");
+ }
+ }
+ else
+ {
+ printf("cvt");
+ }
+ prtype(r);
+ prtype(l);
+ ops:
+ printf(" ");
+ adrput(r);
+ printf(",");
+ adrput(l);
+ return;
+ }
+
+ case 'C': /* num words pushed on arg stack */
+ {
+ extern int gc_numbytes;
+ extern int xdebug;
+
+ if (xdebug) printf("->%d<-",gc_numbytes);
+
+ printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
+ return;
+ }
+
+ case 'D': /* INCR and DECR */
+ zzzcode(p->left, 'A');
+ printf("\n ");
+
+ case 'E': /* INCR and DECR, FOREFF */
+ if (p->right->lval == 1)
+ {
+ printf("%s", (p->op == INCR ? "inc" : "dec") );
+ prtype(p->left);
+ printf(" ");
+ adrput(p->left);
+ return;
+ }
+ printf("%s", (p->op == INCR ? "add" : "sub") );
+ prtype(p->left);
+ printf("2 ");
+ adrput(p->right);
+ printf(",");
+ adrput(p->left);
+ return;
+
+ case 'F': /* register type of right operand */
+ {
+ register NODE *n;
+ extern int xdebug;
+ register int ty;
+
+ n = getlr( p, 'R' );
+ ty = n->type;
+
+ if (xdebug) printf("->%d<-", ty);
+
+ if ( ty==DOUBLE) printf("d");
+ else if ( ty==FLOAT ) printf("f");
+ else printf("l");
+ return;
+ }
+
+ case 'L': /* type of left operand */
+ case 'R': /* type of right operand */
+ {
+ register NODE *n;
+ extern int xdebug;
+
+ n = getlr ( p, c);
+ if (xdebug) printf("->%d<-", n->type);
+
+ prtype(n);
+ return;
+ }
+
+ case 'Z': /* complement mask for bit instr */
+ printf("$%Ld", ~p->right->lval);
+ return;
+
+ case 'U': /* 32 - n, for unsigned right shifts */
+ printf("$%d", 32 - p->right->lval );
+ return;
+
+ case 'T': /* rounded structure length for arguments */
+ {
+ int size;
+
+ size = p->stsize;
+ SETOFF( size, 4);
+ printf("$%d", size);
+ return;
+ }
+
+ case 'S': /* structure assignment */
+ {
+ register NODE *l, *r;
+ register size;
+
+ if( p->op == STASG ){
+ l = p->left;
+ r = p->right;
+
+ }
+ else if( p->op == STARG ){ /* store an arg into a temporary */
+ l = getlr( p, '3' );
+ r = p->left;
+ }
+ else cerror( "STASG bad" );
+
+ if( r->op == ICON ) r->op = NAME;
+ else if( r->op == REG ) r->op = OREG;
+ else if( r->op != OREG ) cerror( "STASG-r" );
+
+ size = p->stsize;
+
+ if( size <= 0 || size > 65535 )
+ cerror("structure size <0=0 or >65535");
+
+ switch(size) {
+ case 1:
+ printf(" movb ");
+ break;
+ case 2:
+ printf(" movw ");
+ break;
+ case 4:
+ printf(" movl ");
+ break;
+ case 8:
+ printf(" movq ");
+ break;
+ default:
+ printf(" movc3 $%d,", size);
+ break;
+ }
+ adrput(r);
+ printf(",");
+ adrput(l);
+ printf("\n");
+
+ if( r->op == NAME ) r->op = ICON;
+ else if( r->op == OREG ) r->op = REG;
+
+ }
+ break;
+
+ default:
+ cerror( "illegal zzzcode" );
+ }
+ }
+
+rmove( rt, rs, t ){
+ printf( " %s %s,%s\n",
+ (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
+ rnames[rs], rnames[rt] );
+ }
+
+struct respref
+respref[] = {
+ INTAREG|INTBREG, INTAREG|INTBREG,
+ INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
+ INTEMP, INTEMP,
+ FORARG, FORARG,
+ INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
+ 0, 0 };
+
+setregs(){ /* set up temporary registers */
+ fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
+ ;
+ }
+
+szty(t){ /* size, in registers, needed to hold thing of type t */
+ return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
+ }
+
+rewfld( p ) NODE *p; {
+ return(1);
+ }
+
+callreg(p) NODE *p; {
+ return( R0 );
+ }
+
+base( p ) register NODE *p; {
+ register int o = p->op;
+
+ if( (o==ICON && p->name[0] != '\0')) return( 100 ); /* ie no base reg */
+ if( o==REG ) return( p->rval );
+ if( (o==PLUS || o==MINUS) && p->left->op == REG && p->right->op==ICON)
+ return( p->left->rval );
+ if( o==OREG && !R2TEST(p->rval) && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
+ return( p->rval + 0200*1 );
+ if( o==INCR && p->left->op==REG ) return( p->left->rval + 0200*2 );
+ if( o==ASG MINUS && p->left->op==REG) return( p->left->rval + 0200*4 );
+ if( o==UNARY MUL && p->left->op==INCR && p->left->left->op==REG
+ && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
+ return( p->left->left->rval + 0200*(1+2) );
+ return( -1 );
+ }
+
+offset( p, tyl ) register NODE *p; int tyl; {
+
+ if( tyl==1 && p->op==REG && (p->type==INT || p->type==UNSIGNED) ) return( p->rval );
+ if( (p->op==LS && p->left->op==REG && (p->left->type==INT || p->left->type==UNSIGNED) &&
+ (p->right->op==ICON && p->right->name[0]=='\0')
+ && (1<<p->right->lval)==tyl))
+ return( p->left->rval );
+ return( -1 );
+ }
+
+makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
+ register NODE *t;
+ register int i;
+ NODE *f;
+
+ p->op = OREG;
+ f = p->left; /* have to free this subtree later */
+
+ /* init base */
+ switch (q->op) {
+ case ICON:
+ case REG:
+ case OREG:
+ t = q;
+ break;
+
+ case MINUS:
+ q->right->lval = -q->right->lval;
+ case PLUS:
+ t = q->right;
+ break;
+
+ case INCR:
+ case ASG MINUS:
+ t = q->left;
+ break;
+
+ case UNARY MUL:
+ t = q->left->left;
+ break;
+
+ default:
+ cerror("illegal makeor2");
+ }
+
+ p->lval = t->lval;
+ for(i=0; i<NCHNAM; ++i)
+ p->name[i] = t->name[i];
+
+ /* init offset */
+ p->rval = R2PACK( (b & 0177), o, (b>>7) );
+
+ tfree(f);
+ return;
+ }
+
+canaddr( p ) NODE *p; {
+ register int o = p->op;
+
+ if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->left)) ) return(1);
+ return(0);
+ }
+
+shltype( o, p ) register NODE *p; {
+ return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->left)) );
+ }
+
+flshape( p ) register NODE *p; {
+ return( p->op == REG || p->op == NAME || p->op == ICON ||
+ (p->op == OREG && (!R2TEST(p->rval) || tlen(p) == 1)) );
+ }
+
+shtemp( p ) register NODE *p; {
+ if( p->op == STARG ) p = p->left;
+ return( p->op==NAME || p->op ==ICON || p->op == OREG || (p->op==UNARY MUL && shumul(p->left)) );
+ }
+
+shumul( p ) register NODE *p; {
+ register o;
+ extern int xdebug;
+
+ if (xdebug) {
+ printf("\nshumul:op=%d,lop=%d,rop=%d", p->op, p->left->op, p->right->op);
+ printf(" prname=%s,plty=%d, prlval=%D\n", p->right->name, p->left->type, p->right->lval);
+ }
+
+
+ o = p->op;
+ if( o == NAME || (o == OREG && !R2TEST(p->rval)) || o == ICON ) return( STARNM );
+
+ if( ( o == INCR || o == ASG MINUS ) &&
+ ( p->left->op == REG && p->right->op == ICON ) &&
+ p->right->name[0] == '\0' )
+ {
+ switch (p->left->type)
+ {
+ case CHAR|PTR:
+ case UCHAR|PTR:
+ o = 1;
+ break;
+
+ case SHORT|PTR:
+ case USHORT|PTR:
+ o = 2;
+ break;
+
+ case INT|PTR:
+ case UNSIGNED|PTR:
+ case LONG|PTR:
+ case ULONG|PTR:
+ case FLOAT|PTR:
+ o = 4;
+ break;
+
+ case DOUBLE|PTR:
+ o = 8;
+ break;
+
+ default:
+ if ( ISPTR(p->left->type) ) {
+ o = 4;
+ break;
+ }
+ else return(0);
+ }
+ return( p->right->lval == o ? STARREG : 0);
+ }
+
+ return( 0 );
+ }
+
+adrcon( val ) CONSZ val; {
+ printf( "$" );
+ printf( CONFMT, val );
+ }
+
+conput( p ) register NODE *p; {
+ switch( p->op ){
+
+ case ICON:
+ acon( p );
+ return;
+
+ case REG:
+ printf( "%s", rnames[p->rval] );
+ return;
+
+ default:
+ cerror( "illegal conput" );
+ }
+ }
+
+insput( p ) register NODE *p; {
+ cerror( "insput" );
+ }
+
+upput( p ) register NODE *p; {
+ cerror( "upput" );
+ }
+
+adrput( p ) register NODE *p; {
+ register int r;
+ /* output an address, with offsets, from p */
+
+ if( p->op == FLD ){
+ p = p->left;
+ }
+ switch( p->op ){
+
+ case NAME:
+ acon( p );
+ return;
+
+ case ICON:
+ /* addressable value of the constant */
+ printf( "$" );
+ acon( p );
+ return;
+
+ case REG:
+ printf( "%s", rnames[p->rval] );
+ return;
+
+ case OREG:
+ r = p->rval;
+ if( R2TEST(r) ){ /* double indexing */
+ register int flags;
+
+ flags = R2UPK3(r);
+ if( flags & 1 ) printf("*");
+ if( flags & 4 ) printf("-");
+ if( p->lval != 0 || p->name[0] != '\0' ) acon(p);
+ if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
+ if( flags & 2 ) printf("+");
+ printf( "[%s]", rnames[R2UPK2(r)] );
+ return;
+ }
+ if( r == AP ){ /* in the argument region */
+ if( p->lval <= 0 || p->name[0] != '\0' ) werror( "bad arg temp" );
+ printf( CONFMT, p->lval );
+ printf( "(ap)" );
+ return;
+ }
+ if( p->lval != 0 || p->name[0] != '\0') acon( p );
+ printf( "(%s)", rnames[p->rval] );
+ return;
+
+ case UNARY MUL:
+ /* STARNM or STARREG found */
+ if( tshape(p, STARNM) ) {
+ printf( "*" );
+ adrput( p->left);
+ }
+ else { /* STARREG - really auto inc or dec */
+ register NODE *q;
+
+/* tbl
+ p = p->left;
+ p->left->op = OREG;
+ if( p->op == INCR ) {
+ adrput( p->left );
+ printf( "+" );
+ }
+ else {
+ printf( "-" );
+ adrput( p->left );
+ }
+ tbl */
+ printf("%c(%s)%c", (p->left->op==INCR ? '\0' : '-'),
+ rnames[p->left->left->rval],
+ (p->left->op==INCR ? '+' : '\0') );
+ p->op = OREG;
+ p->rval = p->left->left->rval;
+ q = p->left;
+ p->lval = (p->left->op == INCR ? -p->left->right->lval : 0);
+ p->name[0] = '\0';
+ tfree(q);
+ }
+ return;
+
+ default:
+ cerror( "illegal address" );
+ return;
+
+ }
+
+ }
+
+acon( p ) register NODE *p; { /* print out a constant */
+
+ if( p->name[0] == '\0' ){
+ printf( CONFMT, p->lval);
+ }
+ else if( p->lval == 0 ) {
+ printf( "%.8s", p->name );
+ }
+ else {
+ printf( "%.8s+", p->name );
+ printf( CONFMT, p->lval );
+ }
+ }
+
+/*
+aacon( p ) register NODE *p; { /* print out a constant */
+/*
+
+ if( p->name[0] == '\0' ){
+ printf( CONFMT, p->lval);
+ return( 0 );
+ }
+ else if( p->lval == 0 ) {
+ printf( "$%.8s", p->name );
+ return( 1 );
+ }
+ else {
+ printf( "$(" );
+ printf( CONFMT, p->lval );
+ printf( "+" );
+ printf( "%.8s)", p->name );
+ return(1);
+ }
+ }
+ */
+
+genscall( p, cookie ) register NODE *p; {
+ /* structure valued call */
+ return( gencall( p, cookie ) );
+ }
+
+/* tbl */
+int gc_numbytes;
+/* tbl */
+
+gencall( p, cookie ) register NODE *p; {
+ /* generate the call given by p */
+ register NODE *p1, *ptemp;
+ register temp, temp1;
+ register m;
+
+ if( p->right ) temp = argsize( p->right );
+ else temp = 0;
+
+ if( p->op == STCALL || p->op == UNARY STCALL ){
+ /* set aside room for structure return */
+
+ if( p->stsize > temp ) temp1 = p->stsize;
+ else temp1 = temp;
+ }
+
+ if( temp > maxargs ) maxargs = temp;
+ SETOFF(temp1,4);
+
+ if( p->right ){ /* make temp node, put offset in, and generate args */
+ ptemp = talloc();
+ ptemp->op = OREG;
+ ptemp->lval = -1;
+ ptemp->rval = SP;
+ ptemp->name[0] = '\0';
+ ptemp->rall = NOPREF;
+ ptemp->su = 0;
+ genargs( p->right, ptemp );
+ ptemp->op = FREE;
+ }
+
+ p1 = p->left;
+ if( p1->op != ICON ){
+ if( p1->op != REG ){
+ if( p1->op != OREG || R2TEST(p1->rval) ){
+ if( p1->op != NAME ){
+ order( p1, INAREG );
+ }
+ }
+ }
+ }
+
+/*
+ if( p1->op == REG && p->rval == R5 ){
+ cerror( "call register overwrite" );
+ }
+ */
+/* tbl
+ setup gc_numbytes so reference to ZC works */
+
+ gc_numbytes = temp;
+/* tbl */
+
+ p->op = UNARY CALL;
+ m = match( p, INTAREG|INTBREG );
+/* tbl
+ switch( temp ) {
+ case 0:
+ break;
+ case 2:
+ printf( " tst (sp)+\n" );
+ break;
+ case 4:
+ printf( " cmp (sp)+,(sp)+\n" );
+ break;
+ default:
+ printf( " add $%d,sp\n", temp);
+ }
+ tbl */
+ return(m != MDONE);
+ }
+
+/* tbl */
+char *
+ccbranches[] = {
+ " jeql L%d\n",
+ " jneq L%d\n",
+ " jleq L%d\n",
+ " jlss L%d\n",
+ " jgeq L%d\n",
+ " jgtr L%d\n",
+ " jlequ L%d\n",
+ " jlssu L%d\n",
+ " jgequ L%d\n",
+ " jgtru L%d\n",
+ };
+/* tbl */
+
+cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
+
+/* tbl */
+ if( o == 0 ) printf( " jbr L%d\n", lab );
+/* tbl */
+ else {
+ if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
+ printf( ccbranches[o-EQ], lab );
+ }
+ }
+
+nextcook( p, cookie ) NODE *p; {
+ /* we have failed to match p with cookie; try another */
+ if( cookie == FORREW ) return( 0 ); /* hopeless! */
+ if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
+ if( !(cookie&INTEMP) && asgop(p->op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
+ return( FORREW );
+ }
+
+lastchance( p, cook ) NODE *p; {
+ /* forget it! */
+ return(0);
+ }
+
+optim2( p ) register NODE *p; {
+ /* do local tree transformations and optimizations */
+
+ register NODE *r;
+
+ switch( p->op ) {
+
+ case AND:
+ /* commute L and R to eliminate compliments and constants */
+ if( (p->left->op==ICON&&p->left->name[0]==0) || p->left->op==COMPL ) {
+ r = p->left;
+ p->left = p->right;
+ p->right = r;
+ }
+ case ASG AND:
+ /* change meaning of AND to ~R&L - bic on pdp11 */
+ r = p->right;
+ if( r->op==ICON && r->name[0]==0 ) { /* compliment constant */
+ r->lval = ~r->lval;
+ }
+ else if( r->op==COMPL ) { /* ~~A => A */
+ r->op = FREE;
+ p->right = r->left;
+ }
+ else { /* insert complement node */
+ p->right = talloc();
+ p->right->op = COMPL;
+ p->right->rall = NOPREF;
+ p->right->type = r->type;
+ p->right->left = r;
+ p->right->right = NULL;
+ }
+ break;
+
+ }
+ }
+
+
+# ifndef ONEPASS
+main( argc, argv ) char *argv[]; {
+ return( mainp2( argc, argv ) );
+ }
+# endif
diff --git a/usr.bin/pcc/arch/vax/macdefs.h b/usr.bin/pcc/arch/vax/macdefs.h
new file mode 100644
index 00000000000..095e55ad910
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/macdefs.h
@@ -0,0 +1,155 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+# define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+# define ARGINIT 32
+# define AUTOINIT 0
+# define SZCHAR 8
+# define SZINT 32
+# define SZFLOAT 32
+# define SZDOUBLE 64
+# define SZLONG 32
+# define SZSHORT 16
+# define SZPOINT 32
+# define ALCHAR 8
+# define ALINT 32
+# define ALFLOAT 32
+# define ALDOUBLE 32
+# define ALLONG 32
+# define ALSHORT 16
+# define ALPOINT 32
+# define ALSTRUCT 8
+# define ALSTACK 32
+
+/* size in which constants are converted */
+/* should be long if feasable */
+
+# define CONSZ long
+# define CONFMT "%Ld"
+
+/* size in which offsets are kept
+/* should be large enough to cover address space in bits
+*/
+
+# define OFFSZ long
+
+/* character set macro */
+
+# define CCTRANS(x) x
+
+/* register cookie for stack poINTer */
+
+# define STKREG 13
+# define ARGREG 12
+
+/* maximum and minimum register variables */
+
+# define MAXRVAR 11
+# define MINRVAR 6
+
+ /* various standard pieces of code are used */
+# define STDPRTREE
+# define LABFMT "L%d"
+
+/* show stack grows negatively */
+#define BACKAUTO
+#define BACKTEMP
+
+/* show field hardware support on VAX */
+#define FIELDOPS
+
+/* bytes are numbered from right to left */
+#define RTOLBYTES
+
+/* we want prtree included */
+# define STDPRTREE
+# ifndef FORT
+# define ONEPASS
+#endif
+
+# define ENUMSIZE(high,low) INT
+
+/* VAX-11/780 Registers */
+
+ /* scratch registers */
+# define R0 0
+# define R1 1
+# define R2 2
+# define R3 3
+# define R4 4
+# define R5 5
+
+ /* register variables */
+# define R6 6
+# define R7 7
+# define R8 8
+# define R9 9
+# define R10 10
+# define R11 11
+
+ /* special purpose */
+# define AP 12 /* argument pointer */
+# define FP 13 /* frame pointer */
+# define SP 14 /* stack pointer */
+# define PC 15 /* program counter */
+
+ /* floating registers */
+
+ /* there are no floating point registers on the VAX */
+
+extern int fregs;
+extern int maxargs;
+
+# define BYTEOFF(x) ((x)&03)
+# define wdal(k) (BYTEOFF(k)==0)
+# define BITOOR(x) ((x)>>3) /* bit offset to oreg offset */
+
+# define REGSZ 16
+
+# define TMPREG FP
+
+# define R2REGS /* permit double indexing */
+
+# define STOARG(p) /* just evaluate the arguments, and be done with it... */
+# define STOFARG(p)
+# define STOSTARG(p)
+# define genfcall(a,b) gencall(a,b)
+
+# define NESTCALL
+
+# define MYREADER(p) walkf(p, optim2)
+int optim2();
+# define special(a, b) 0
diff --git a/usr.bin/pcc/arch/vax/order.c b/usr.bin/pcc/arch/vax/order.c
new file mode 100644
index 00000000000..b1f1006adcd
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/order.c
@@ -0,0 +1,533 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 "mfile2"
+
+int maxargs = { -1 };
+
+stoasg( p, o ) register NODE *p; {
+ /* should the assignment op p be stored,
+ given that it lies as the right operand of o
+ (or the left, if o==UNARY MUL) */
+/*
+ if( p->op == INCR || p->op == DECR ) return;
+ if( o==UNARY MUL && p->left->op == REG && !isbreg(p->left->rval) ) SETSTO(p,INAREG);
+ */
+ }
+
+deltest( p ) register NODE *p; {
+ /* should we delay the INCR or DECR operation p */
+ p = p->left;
+ return( p->op == REG || p->op == NAME || p->op == OREG );
+ }
+
+autoincr( p ) NODE *p; {
+ register NODE *q = p->left, *r;
+
+ if( q->op == INCR && (r=q->left)->op == REG &&
+ ISPTR(q->type) && p->type == DECREF(q->type) &&
+ tlen(p) == q->right->lval ) return(1);
+
+ return(0);
+ }
+
+mkadrs(p) register NODE *p; {
+ register o;
+
+ o = p->op;
+
+ if( asgop(o) ){
+ if( p->left->su >= p->right->su ){
+ if( p->left->op == UNARY MUL ){
+ SETSTO( p->left->left, INTEMP );
+ }
+ else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
+ SETSTO( p->left->left->left, INTEMP );
+ }
+ else { /* should be only structure assignment */
+ SETSTO( p->left, INTEMP );
+ }
+ }
+ else SETSTO( p->right, INTEMP );
+ }
+ else {
+ if( p->left->su > p->right->su ){
+ SETSTO( p->left, INTEMP );
+ }
+ else {
+ SETSTO( p->right, INTEMP );
+ }
+ }
+ }
+
+notoff( t, r, off, cp) CONSZ off; char *cp; {
+ /* 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 */
+
+/* if( r == R0 ) return( 1 ); /* NO */
+ return(0); /* YES */
+ }
+
+# define max(x,y) ((x)<(y)?(y):(x))
+
+sucomp( p ) register NODE *p; {
+
+ /* set the su field in the node to the sethi-ullman
+ number, or local equivalent */
+
+ register o, ty, sul, sur, r;
+
+ o = p->op;
+ ty = optype( o );
+ p->su = szty( p->type ); /* 2 for float or double, else 1 */;
+
+ if( ty == LTYPE ){
+ if( o == OREG ){
+ r = p->rval;
+ /* oreg cost is (worst case) 1 + number of temp registers used */
+ if( R2TEST(r) ){
+ if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->su;
+ if( istreg(R2UPK2(r)) ) ++p->su;
+ }
+ else {
+ if( istreg( r ) ) ++p->su;
+ }
+ }
+ if( p->su == szty(p->type) &&
+ (p->op!=REG || !istreg(p->rval)) &&
+ (p->type==INT || p->type==UNSIGNED || p->type==DOUBLE) )
+ p->su = 0;
+ return;
+ }
+
+ else if( ty == UTYPE ){
+ switch( o ) {
+ case UNARY CALL:
+ case UNARY STCALL:
+ p->su = fregs; /* all regs needed */
+ return;
+
+ default:
+ p->su = p->left->su + (szty( p->type ) > 1 ? 2 : 0) ;
+ return;
+ }
+ }
+
+
+ /* If rhs needs n, lhs needs m, regular su computation */
+
+ sul = p->left->su;
+ sur = p->right->su;
+
+ if( o == ASSIGN ){
+ /* computed by doing right, then left (if not in mem), then doing it */
+ p->su = max(sur,sul+1);
+ return;
+ }
+
+ if( o == CALL || o == STCALL ){
+ /* in effect, takes all free registers */
+ p->su = fregs;
+ return;
+ }
+
+ if( o == STASG ){
+ /* right, then left */
+ p->su = max( max( 1+sul, sur), fregs );
+ return;
+ }
+
+ if( asgop(o) ){
+ /* computed by doing right, doing left address, doing left, op, and store */
+ p->su = max(sur,sul+2);
+/*
+ if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->su = max(p->su,fregs);
+ */
+ return;
+ }
+
+ switch( o ){
+ case ANDAND:
+ case OROR:
+ case QUEST:
+ case COLON:
+ case COMOP:
+ p->su = max( max(sul,sur), 1);
+ return;
+
+ case PLUS:
+ case OR:
+ case ER:
+ /* commutative ops; put harder on left */
+ if( p->right->su > p->left->su && !istnode(p->left) ){
+ register NODE *temp;
+ temp = p->left;
+ p->left = p->right;
+ p->right = temp;
+ }
+ break;
+ }
+
+ /* binary op, computed by left, then right, then do op */
+ p->su = max(sul,szty(p->right->type)+sur);
+/*
+ if( o==MUL||o==DIV||o==MOD) p->su = max(p->su,fregs);
+ */
+
+ }
+
+int radebug = 0;
+
+rallo( p, down ) NODE *p; {
+ /* do register allocation */
+ register o, type, down1, down2, ty;
+
+ if( radebug ) printf( "rallo( %o, %d )\n", p, down );
+
+ down2 = NOPREF;
+ p->rall = down;
+ down1 = ( down &= ~MUSTDO );
+
+ ty = optype( o = p->op );
+ type = p->type;
+
+
+ if( type == DOUBLE || type == FLOAT ){
+ if( o == FORCE ) down1 = R0|MUSTDO;
+ }
+ else switch( o ) {
+ case ASSIGN:
+ down1 = NOPREF;
+ down2 = down;
+ break;
+
+/*
+ case MUL:
+ case DIV:
+ case MOD:
+ down1 = R3|MUSTDO;
+ down2 = R5|MUSTDO;
+ break;
+
+ case ASG MUL:
+ case ASG DIV:
+ case ASG MOD:
+ p->left->rall = down1 = R3|MUSTDO;
+ if( p->left->op == UNARY MUL ){
+ rallo( p->left->left, R4|MUSTDO );
+ }
+ else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
+ rallo( p->left->left->left, R4|MUSTDO );
+ }
+ else rallo( p->left, R3|MUSTDO );
+ rallo( p->right, R5|MUSTDO );
+ return;
+ */
+
+ case CALL:
+ case STASG:
+ case EQ:
+ case NE:
+ case GT:
+ case GE:
+ case LT:
+ case LE:
+ case NOT:
+ case ANDAND:
+ case OROR:
+ down1 = NOPREF;
+ break;
+
+ case FORCE:
+ down1 = R0|MUSTDO;
+ break;
+
+ }
+
+ if( ty != LTYPE ) rallo( p->left, down1 );
+ if( ty == BITYPE ) rallo( p->right, down2 );
+
+ }
+
+offstar( p ) register NODE *p; {
+ if( p->op == PLUS ) {
+ if( p->left->su == fregs ) {
+ order( p->left, INTAREG|INAREG );
+ return;
+ } else if( p->right->su == fregs ) {
+ order( p->right, INTAREG|INAREG );
+ return;
+ }
+ if( p->left->op==LS &&
+ (p->left->left->op!=REG || tlen(p->left->left)!=sizeof(int) ) ) {
+ order( p->left->left, INTAREG|INAREG );
+ return;
+ }
+ if( p->right->op==LS &&
+ (p->right->left->op!=REG || tlen(p->right->left)!=sizeof(int) ) ) {
+ order( p->right->left, INTAREG|INAREG );
+ return;
+ }
+ if( p->type == (PTR|CHAR) || p->type == (PTR|UCHAR) ) {
+ if( p->left->op!=REG || tlen(p->left)!=sizeof(int) ) {
+ order( p->left, INTAREG|INAREG );
+ return;
+ }
+ else if( p->right->op!=REG || tlen(p->right)!=sizeof(int) ) {
+ order(p->right, INTAREG|INAREG);
+ return;
+ }
+ }
+ }
+ if( p->op == PLUS || p->op == MINUS ){
+ if( p->right->op == ICON ){
+ p = p->left;
+ order( p , INTAREG|INAREG);
+ return;
+ }
+ }
+
+ if( p->op == UNARY MUL && !canaddr(p) ) {
+ offstar( p->left );
+ return;
+ }
+
+ order( p, INTAREG|INAREG );
+ }
+
+setincr( p ) NODE *p; {
+ return( 0 ); /* for the moment, don't bother */
+ }
+
+setbin( p ) register NODE *p; {
+ register ro, rt;
+
+ rt = p->right->type;
+ ro = p->right->op;
+
+ if( canaddr( p->left ) && !canaddr( p->right ) ) { /* address rhs */
+ if( ro == UNARY MUL ) {
+ offstar( p->right->left );
+ return(1);
+ } else {
+ order( p->right, INAREG|INTAREG|SOREG );
+ return(1);
+ }
+ }
+ if( !istnode( p->left) ) { /* try putting LHS into a reg */
+/* order( p->left, logop(p->op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/
+ order( p->left, INAREG|INTAREG|INBREG|INTBREG|SOREG );
+ return(1);
+ }
+ else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){
+ offstar( p->right->left );
+ return(1);
+ }
+ else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG &&
+ ro != NAME && ro != OREG && ro != ICON ) ){
+ order( p->right, INAREG|INBREG );
+ return(1);
+ }
+/*
+ else if( logop(p->op) && rt==USHORT ){ /* must get rhs into register */
+/*
+ order( p->right, INAREG );
+ return( 1 );
+ }
+ */
+ return(0);
+ }
+
+setstr( p ) register NODE *p; { /* structure assignment */
+ if( p->right->op != REG ){
+ order( p->right, INTAREG );
+ return(1);
+ }
+ p = p->left;
+ if( p->op != NAME && p->op != OREG ){
+ if( p->op != UNARY MUL ) cerror( "bad setstr" );
+ order( p->left, INTAREG );
+ return( 1 );
+ }
+ return( 0 );
+ }
+
+setasg( p ) register NODE *p; {
+ /* setup for assignment operator */
+
+ if( !canaddr(p->right) ) {
+ if( p->right->op == UNARY MUL )
+ offstar(p->right->left);
+ else
+ order( p->right, INAREG|INBREG|SOREG );
+ return(1);
+ }
+ if( p->left->op == UNARY MUL ) {
+ offstar( p->left->left );
+ return(1);
+ }
+ if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
+ offstar( p->left->left->left );
+ return(1);
+ }
+/* FLD patch */
+ if( p->left->op == FLD && !(p->right->type==INT || p->right->type==UNSIGNED)) {
+ order( p->right, INAREG);
+ return(1);
+ }
+/* end of FLD patch */
+ return(0);
+ }
+
+setasop( p ) register NODE *p; {
+ /* setup for =ops */
+ register rt, ro;
+
+ rt = p->right->type;
+ ro = p->right->op;
+
+ if( ro == UNARY MUL && rt != CHAR ){
+ offstar( p->right->left );
+ return(1);
+ }
+ if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT ||
+ ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){
+ order( p->right, INAREG|INBREG );
+ return(1);
+ }
+/*
+ if( (p->op == ASG LS || p->op == ASG RS) && ro != ICON && ro != REG ){
+ order( p->right, INAREG );
+ return(1);
+ }
+ */
+
+
+ p = p->left;
+ if( p->op == FLD ) p = p->left;
+
+ switch( p->op ){
+
+ case REG:
+ case ICON:
+ case NAME:
+ case OREG:
+ return(0);
+
+ case UNARY MUL:
+ if( p->left->op==OREG )
+ return(0);
+ else
+ offstar( p->left );
+ return(1);
+
+ }
+ cerror( "illegal setasop" );
+ }
+
+int crslab = 9999; /* Honeywell */
+
+getlab(){
+ return( crslab-- );
+ }
+
+deflab( l ){
+ printf( "L%d:\n", l );
+ }
+
+genargs( p, ptemp ) register NODE *p, *ptemp; {
+ register NODE *pasg;
+ register align;
+ register size;
+ register TWORD type;
+
+ /* generate code for the arguments */
+
+ /* first, do the arguments on the right */
+ while( p->op == CM ){
+ genargs( p->right, ptemp );
+ p->op = FREE;
+ p = p->left;
+ }
+
+ if( p->op == STARG ){ /* structure valued argument */
+
+ size = p->stsize;
+ align = p->stalign;
+
+ /* ptemp->lval = (ptemp->lval/align)*align; /* SETOFF for negative numbers */
+ ptemp->lval = 0; /* all moves to (sp) */
+
+ p->op = STASG;
+ p->right = p->left;
+ p->left = tcopy( ptemp );
+
+ /* the following line is done only with the knowledge
+ that it will be undone by the STASG node, with the
+ offset (lval) field retained */
+
+ if( p->right->op == OREG ) p->right->op = REG; /* only for temporaries */
+
+ order( p, FORARG );
+ ptemp->lval += size;
+ return;
+ }
+
+ /* ordinary case */
+
+ order( p, FORARG );
+ }
+
+argsize( p ) register NODE *p; {
+ register t;
+ t = 0;
+ if( p->op == CM ){
+ t = argsize( p->left );
+ p = p->right;
+ }
+ if( p->type == DOUBLE || p->type == FLOAT ){
+ SETOFF( t, 4 );
+ return( t+8 );
+ }
+ else if( p->op == STARG ){
+ SETOFF( t, 4 ); /* alignment */
+ return( t + ((p->stsize+3)/4)*4 ); /* size */
+ }
+ else {
+ SETOFF( t, 4 );
+ return( t+4 );
+ }
+ }
diff --git a/usr.bin/pcc/arch/vax/table.c b/usr.bin/pcc/arch/vax/table.c
new file mode 100644
index 00000000000..12d8de17e10
--- /dev/null
+++ b/usr.bin/pcc/arch/vax/table.c
@@ -0,0 +1,652 @@
+/* $Id: table.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 "mfile2"
+
+# define WPTR TPTRTO|TINT|TLONG|TFLOAT|TDOUBLE|TPOINT|TUNSIGNED|TULONG
+# define AWD SNAME|SOREG|SCON|STARNM|STARREG
+/* tbl */
+# define ANYSIGNED TPOINT|TINT|TLONG|TSHORT|TCHAR
+# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
+# define ANYFIXED ANYSIGNED|ANYUSIGNED
+# define TWORD TINT|TUNSIGNED|TPOINT|TLONG|TULONG
+/* tbl */
+
+struct optab table[] = {
+
+PCONV, INAREG|INTAREG,
+ SAREG|AWD, TCHAR|TSHORT,
+ SANY, TPOINT,
+ NAREG|NASL, RESC1,
+ " cvtZLl AL,A1\n",
+
+PCONV, INAREG|INTAREG,
+ SAREG|AWD, TUCHAR|TUSHORT,
+ SANY, TPOINT,
+ NAREG|NASL, RESC1,
+ " movzZLl AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SAREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, RLEFT,
+ "",
+
+SCONV, INTAREG|FORCC,
+ SAREG|AWD, TANY,
+ SANY, TFLOAT|TDOUBLE,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtZLd AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SAREG|AWD, TFLOAT|TDOUBLE,
+ SANY, ANYFIXED,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtZLZF AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SAREG|SNAME|SCON|STARNM, TANY,
+ SANY, ANYUSIGNED,
+ NAREG|NASL, RESC1|RESCC,
+ " movzZRl AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SSOREG, TANY,
+ SANY, ANYUSIGNED,
+ NAREG|NASL, RESC1|RESCC,
+ " movzZRl AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SAREG|SNAME|SCON|STARNM, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtZRl AL,A1\n",
+
+SCONV, INTAREG|FORCC,
+ SSOREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtZRl AL,A1\n",
+
+
+INIT, FOREFF,
+ SCON, TANY,
+ SANY, TWORD,
+ 0, RNOP,
+ " .long CL\n",
+
+INIT, FOREFF,
+ SCON, TANY,
+ SANY, TSHORT|TUSHORT,
+ 0, RNOP,
+ " .word CL\n",
+
+INIT, FOREFF,
+ SCON, TANY,
+ SANY, TCHAR|TUCHAR,
+ 0, RNOP,
+ " .byte CL\n",
+
+ /* for the use of fortran only */
+
+GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jbr CL\n",
+
+GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp (AL)\n",
+
+STARG, INTEMP,
+ SCON|SAREG, TANY,
+ SANY, TANY,
+ NTEMP+2*NAREG, RESC3,
+ "ZS",
+
+STASG, FORARG,
+ SNAME|SOREG, TANY,
+ SCON|SAREG, TANY,
+ 0, RNULL,
+ " subl2 ZT,sp\nZS",
+
+STASG, FOREFF,
+ SNAME|SOREG, TANY,
+ SCON|SAREG, TANY,
+ 0, RNOP,
+ "ZS",
+
+STASG, INAREG,
+ SNAME|SOREG, TANY,
+ SCON, TANY,
+ NAREG, RESC1,
+ "ZS movl AR,A1\n",
+
+STASG, INAREG,
+ SNAME|SOREG, TANY,
+ SAREG, TANY,
+ 0, RRIGHT,
+ " pushl AR\nZS movl (sp)+,AR\n",
+
+FLD, INAREG|INTAREG,
+ SANY, TANY,
+ SFLD, ANYSIGNED,
+ NAREG|NASR, RESC1,
+ " extv H,S,AR,A1\n",
+
+FLD, INAREG|INTAREG,
+ SANY, TANY,
+ SFLD, ANYUSIGNED,
+ NAREG|NASR, RESC1,
+ " extzv H,S,AR,A1\n",
+
+FLD, FORARG,
+ SANY, TANY,
+ SFLD, ANYSIGNED,
+ 0, RNULL,
+ " extv H,S,AR,-(sp)\n",
+
+FLD, FORARG,
+ SANY, TANY,
+ SFLD, ANYUSIGNED,
+ 0, RNULL,
+ " extzv H,S,AR,-(sp)\n",
+
+OPLOG, FORCC,
+ SAREG|AWD, TWORD,
+ SAREG|AWD, TWORD,
+ 0, RESCC,
+ " cmpl AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TSHORT|TUSHORT,
+ SAREG|AWD, TSHORT|TUSHORT,
+ 0, RESCC,
+ " cmpw AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TCHAR|TUCHAR,
+ SAREG|AWD, TCHAR|TUCHAR,
+ 0, RESCC,
+ " cmpb AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TSHORT|TUSHORT,
+ SSCON, TANY,
+ 0, RESCC,
+ " cmpw AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TCHAR|TUCHAR,
+ SCCON, TANY,
+ 0, RESCC,
+ " cmpb AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TDOUBLE,
+ SAREG|AWD, TDOUBLE,
+ 0, RESCC,
+ " cmpd AL,AR\nZP",
+
+OPLOG, FORCC,
+ SAREG|AWD, TFLOAT|TDOUBLE,
+ SAREG|AWD, TFLOAT|TDOUBLE,
+ 0, RESCC,
+ " cmpf AL,AR\nZP",
+
+CCODES, INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ NAREG, RESC1,
+ " movl $1,A1\nZN",
+
+UNARY CALL, INTAREG,
+ SCON, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE,
+ NAREG|NASL, RESC1, /* should be register 0 */
+ " calls ZC,CL\n",
+
+UNARY CALL, INTAREG,
+ SAREG, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " calls ZC,(AL)\n",
+
+UNARY CALL, INAREG|INTAREG,
+ SNAME, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* really reg 0 */
+ " calls ZC,*AL\n",
+
+UNARY CALL, INAREG|INTAREG,
+ SSOREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* really reg 0 */
+ " calls ZC,*AL\n",
+
+ASG RS, INAREG|FOREFF|FORCC,
+ SAREG, TWORD,
+ SCON, TINT,
+ 0, RLEFT|RESCC,
+ " extzv AR,ZU,AL,AL\n",
+
+ASG RS, INAREG|FOREFF|FORCC,
+ SAREG, TWORD,
+ SAREG, ANYFIXED,
+ NAREG, RLEFT|RESCC,
+ " subl3 AR,$32,A1\n extzv AR,A1,AL,AL\n",
+
+ASG RS, INAREG|FOREFF|FORCC,
+ SAREG, TWORD,
+ SAREG|AWD, TWORD,
+ NAREG, RLEFT|RESCC,
+ " subl3 AR,$32,A1\n extzv AR,A1,AL,AL\n",
+
+RS, INAREG|INTAREG|FORCC,
+ SAREG, TWORD,
+ SCON, TINT,
+ NAREG|NASL, RESC1|RESCC,
+ " extzv AR,ZU,AL,A1\n",
+
+ASG LS, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TWORD,
+ SAREG|AWD, ANYSIGNED|ANYUSIGNED,
+ 0, RLEFT|RESCC,
+ " ashl AR,AL,AL\n",
+
+LS, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TWORD,
+ SAREG|AWD, ANYSIGNED|ANYUSIGNED,
+ NAREG|NASL|NASR, RESC1|RESCC,
+ " ashl AR,AL,A1\n",
+
+INCR, FOREFF,
+ SAREG|AWD, TANY,
+ SANY, TANY,
+ 0, RLEFT,
+ " ZE\n",
+
+DECR, FOREFF,
+ SAREG|AWD, TANY,
+ SCON, TANY,
+ 0, RLEFT,
+ " ZE\n",
+
+INCR, INAREG|INTAREG,
+ SAREG|AWD, TANY,
+ SCON, TANY,
+ NAREG, RESC1,
+ " ZD\n",
+
+DECR, INAREG|INTAREG,
+ SAREG|AWD, TANY,
+ SCON, TANY,
+ NAREG, RESC1,
+ " ZD\n",
+
+ASSIGN, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TANY,
+ SAREG|AWD, TANY,
+ 0, RLEFT|RRIGHT|RESCC,
+ " ZA\n",
+
+ASSIGN, INAREG|FOREFF|FORCC,
+ SFLD, TANY,
+ SAREG|AWD, TWORD,
+ 0, RRIGHT|RESCC,
+ " insv AR,H,S,AL\n",
+
+ASSIGN, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TWORD,
+ SFLD, ANYSIGNED,
+ 0, RLEFT|RESCC,
+ " extv H,S,AR,AL\n",
+
+ASSIGN, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TWORD,
+ SFLD, ANYUSIGNED,
+ 0, RLEFT|RESCC,
+ " extzv H,S,AR,AL\n",
+
+/* dummy UNARY MUL entry to get U* to possibly match OPLTYPE */
+UNARY MUL, FOREFF,
+ SCC, TANY,
+ SCC, TANY,
+ 0, RNULL,
+ " HELP HELP HELP\n",
+
+REG, FORARG,
+ SANY, TANY,
+ SAREG, TDOUBLE|TFLOAT,
+ 0, RNULL,
+ " movZR AR,-(sp)\n",
+
+REG, INTEMP,
+ SANY, TANY,
+ SAREG, TDOUBLE,
+ 2*NTEMP, RESC1,
+ " movd AR,A1\n",
+
+REG, INTEMP,
+ SANY, TANY,
+ SAREG, TANY,
+ NTEMP, RESC1,
+ " movZF AR,A1\n",
+
+OPLEAF, FOREFF,
+ SANY, TANY,
+ SAREG|AWD, TANY,
+ 0, RLEFT,
+ "",
+
+OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TFLOAT|TDOUBLE,
+ 2*NAREG|NASR, RESC1,
+ " ZA\n",
+
+OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ NAREG|NASR, RESC1,
+ " ZA\n",
+
+OPLTYPE, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ 0, RESCC,
+ " tstZR AR\n",
+
+OPLTYPE, FORARG,
+ SANY, TANY,
+ SANY, TWORD,
+ 0, RNULL,
+ " pushl AR\n",
+
+OPLTYPE, FORARG,
+ SANY, TANY,
+ SANY, TCHAR|TSHORT,
+ 0, RNULL,
+ " cvtZRl AR,-(sp)\n",
+
+OPLTYPE, FORARG,
+ SANY, TANY,
+ SANY, TUCHAR|TUSHORT,
+ 0, RNULL,
+ " movzZRl AR,-(sp)\n",
+
+OPLTYPE, FORARG,
+ SANY, TANY,
+ SANY, TDOUBLE,
+ 0, RNULL,
+ " movd AR,-(sp)\n",
+
+OPLTYPE, FORARG,
+ SANY, TANY,
+ SANY, TFLOAT,
+ 0, RNULL,
+ " cvtfd AR,-(sp)\n",
+
+UNARY MINUS, INTAREG|FORCC,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG|TDOUBLE,
+ SANY, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " mnegZL AL,A1\n",
+
+COMPL, INTAREG|FORCC,
+ SAREG|AWD, TINT|TUNSIGNED,
+ SANY, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " mcomZL AL,A1\n",
+
+COMPL, INTAREG|FORCC,
+ SAREG|AWD, ANYSIGNED|ANYUSIGNED,
+ SANY, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtZLl AL,A1\n mcoml A1,A1\n",
+
+AND, FORCC,
+ SAREG|AWD, TWORD,
+ SCON, TWORD,
+ 0, RESCC,
+ " bitl ZZ,AL\n",
+
+AND, FORCC,
+ SAREG|AWD, TSHORT|TUSHORT,
+ SSCON, TWORD,
+ 0, RESCC,
+ " bitw ZZ,AL\n",
+
+AND, FORCC,
+ SAREG|AWD, TCHAR|TUCHAR,
+ SCCON, TWORD,
+ 0, RESCC,
+ " bitb ZZ,AL\n",
+
+ASG AND, INAREG|FOREFF|FORCC,
+ SAREG, ANYFIXED,
+ SCON, TWORD,
+ 0, RLEFT|RESCC,
+ " bicl2 AR,AL\n",
+
+ASG OPMUL, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ 0, RLEFT|RESCC,
+ " OL2 AR,AL\n",
+
+OPMUL, INAREG|INTAREG|FORCC,
+ STAREG, TINT|TUNSIGNED|TLONG|TULONG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ 0, RLEFT|RESCC,
+ " OL2 AR,AL\n",
+
+OPMUL, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ NAREG|NASL|NASR, RESC1|RESCC,
+ " OL3 AR,AL,A1\n",
+
+ASG MOD, INAREG|INTAREG|FOREFF|FORCC,
+ SAREG, TINT|TUNSIGNED|TLONG|TULONG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ NAREG, RLEFT|RESCC,
+ " divl3 AR,AL,A1\n mull2 AR,A1\n subl2 A1,AL\n",
+
+MOD, INAREG|INTAREG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG,
+ NAREG, RESC1,
+ " divl3 AR,AL,A1\n mull2 AR,A1\n subl3 A1,AL,A1\n",
+
+ASG PLUS, INAREG|FOREFF|FORCC,
+ SAREG|AWD, ANYSIGNED|ANYUSIGNED,
+ SONE, TINT|TLONG,
+ 0, RLEFT|RESCC,
+ " incZL AL\n",
+
+ASG MINUS, INAREG|FOREFF|FORCC,
+ SAREG|AWD, ANYSIGNED|ANYUSIGNED,
+ SONE, TINT|TLONG,
+ 0, RLEFT|RESCC,
+ " decZL AL\n",
+
+PLUS, INAREG|INTAREG|FORCC,
+ STAREG, ANYFIXED,
+ SONE, TWORD,
+ 0, RLEFT|RESCC,
+ " incZL AL\n",
+
+MINUS, INAREG|INTAREG|FORCC,
+ STAREG, ANYFIXED,
+ SONE, TWORD,
+ 0, RLEFT|RESCC,
+ " decZL AL\n",
+
+ASG OPSIMP, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TWORD,
+ SAREG|AWD, TWORD,
+ 0, RLEFT|RESCC,
+ " OL2 AR,AL\n",
+
+ASG OPSIMP, INAREG|FOREFF|FORCC,
+ AWD, TSHORT|TUSHORT,
+ SAREG|AWD, TSHORT|TUSHORT,
+ 0, RLEFT|RESCC,
+ " OW2 AR,AL\n",
+
+ASG OPSIMP, INAREG|FOREFF|FORCC,
+ AWD, TSHORT|TUSHORT,
+ SSCON, TWORD,
+ 0, RLEFT|RESCC,
+ " OW2 AR,AL\n",
+
+ASG OPSIMP, INAREG|FOREFF|FORCC,
+ AWD, TCHAR|TUCHAR,
+ SAREG|AWD, TCHAR|TUCHAR,
+ 0, RLEFT|RESCC,
+ " OB2 AR,AL\n",
+
+ASG OPSIMP, INAREG|FOREFF|FORCC,
+ AWD, TCHAR|TUCHAR,
+ SCCON, TWORD,
+ 0, RLEFT|RESCC,
+ " OB2 AR,AL\n",
+
+OPSIMP, INAREG|INTAREG|FORCC,
+ STAREG, ANYFIXED,
+ SAREG|AWD, TWORD,
+ 0, RLEFT|RESCC,
+ " OL2 AR,AL\n",
+
+OPSIMP, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TWORD,
+ SAREG|AWD, TWORD,
+ NAREG|NASL|NASR, RESC1|RESCC,
+ " OL3 AR,AL,A1\n",
+
+ASG OPFLOAT, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TDOUBLE,
+ SAREG|AWD, TDOUBLE,
+ 0, RLEFT|RESCC,
+ " OD2 AR,AL\n",
+
+ASG OPFLOAT, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TFLOAT,
+ SAREG|AWD, TFLOAT,
+ 0, RLEFT|RESCC,
+ " OF2 AR,AL\n",
+
+ASG OPFLOAT, INAREG|FOREFF|FORCC,
+ SAREG|AWD, TDOUBLE,
+ SAREG|AWD, TFLOAT,
+ NAREG|NASR, RLEFT|RESCC,
+ " cvtfd AR,A1\n OD2 A1,AL\n",
+
+ASG OPFLOAT, INAREG|INTAREG|FOREFF|FORCC,
+ SAREG|AWD, TFLOAT,
+ SAREG|AWD, TDOUBLE,
+ NAREG, RLEFT|RESC1|RESCC,
+ " cvtfd AL,A1\n OD2 AR,A1\n cvtdf A1,AL\n",
+
+OPFLOAT, INAREG|INTAREG|FORCC,
+ STAREG, TDOUBLE,
+ SAREG|AWD, TDOUBLE,
+ 0, RLEFT|RESCC,
+ " OD2 AR,AL\n",
+
+OPFLOAT, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TDOUBLE,
+ SAREG|AWD, TDOUBLE,
+ NAREG|NASL|NASR, RESC1|RESCC,
+ " OD3 AR,AL,A1\n",
+
+OPFLOAT, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TFLOAT,
+ SAREG|AWD, TDOUBLE,
+ NAREG|NASL, RESC1|RESCC,
+ " cvtfd AL,A1\n OD2 AR,A1\n",
+
+OPFLOAT, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TDOUBLE,
+ SAREG|AWD, TFLOAT,
+ NAREG|NASR, RESC1|RESCC,
+ " cvtfd AR,A1\n OD3 A1,AL,A1\n",
+
+OPFLOAT, INAREG|INTAREG|FORCC,
+ SAREG|AWD, TFLOAT,
+ SAREG|AWD, TFLOAT,
+ NAREG|NASL|NASR, RESC1|RESCC,
+ " OF3 AR,AL,A1\n cvtfd A1,A1\n",
+
+ /* Default actions for hard trees ... */
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+UNARY MUL, DF( UNARY MUL ),
+
+INCR, DF(INCR),
+
+DECR, DF(INCR),
+
+ASSIGN, DF(ASSIGN),
+
+STASG, DF(STASG),
+
+OPLEAF, DF(NAME),
+
+OPLOG, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, BITYPE,
+ "",
+
+OPLOG, DF(NOT),
+
+COMOP, DF(COMOP),
+
+INIT, DF(INIT),
+
+OPUNARY, DF(UNARY MINUS),
+
+
+ASG OPANY, DF(ASG PLUS),
+
+OPANY, DF(BITYPE),
+
+FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" };
diff --git a/usr.bin/pcc/arch/x86/code.c b/usr.bin/pcc/arch/x86/code.c
new file mode 100644
index 00000000000..dad9c3b57aa
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/code.c
@@ -0,0 +1,213 @@
+/* $Id: code.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * 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(" .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(" .globl %s\n", c);
+ printf("%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 eax */
+ p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_rval = EAX;
+ q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ q->n_rval = EBP;
+ 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 flag )
+{
+}
+
+void
+bjobcode()
+{
+}
+
+/*
+ * 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(" .zero %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);
+}
diff --git a/usr.bin/pcc/arch/x86/local.c b/usr.bin/pcc/arch/x86/local.c
new file mode 100644
index 00000000000..88b622d4317
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/local.c
@@ -0,0 +1,743 @@
+/* $Id: local.c,v 1.1 2007/09/15 18:12:30 otto Exp $ */
+/*
+ * 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"
+
+/* 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;
+ register int o;
+ register int m;
+ 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)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ 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 STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ 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)
+ 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);
+ return l;
+ }
+
+ 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 == NAME || l->n_op == UMUL ||
+ l->n_op == TEMP) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ }
+ }
+
+ if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
+ coptype(l->n_op) == BITYPE) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+
+ 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;
+ return p;
+ }
+ 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 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, 0, MKSUE(INT));
+ p->n_left->n_rval = p->n_left->n_type == BOOL ?
+ RETREG(CHAR) : RETREG(p->n_type);
+ break;
+
+ case LS:
+ case RS:
+ /* shift count must be in a char
+ * unless longlong, where it must be int */
+ if (p->n_right->n_op == ICON)
+ break; /* do not do anything */
+ if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
+ if (p->n_right->n_type != INT)
+ p->n_right = block(SCONV, p->n_right, NIL,
+ INT, 0, MKSUE(INT));
+ break;
+ }
+ if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
+ break;
+ p->n_right = block(SCONV, p->n_right, NIL,
+ CHAR, 0, MKSUE(CHAR));
+ 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)
+{
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return 0; /* not yet */
+ 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(MINUSEQ, 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
+ */
+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:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+ break;
+ 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");
+ }
+}
+
+#if 0
+/*
+ * print out an integer.
+ */
+void
+inval(CONSZ word)
+{
+ word &= 0xffffffff;
+ printf(" .long 0x%llx\n", word);
+}
+
+/* output code to initialize a floating point value */
+/* the proper alignment has been obtained */
+void
+finval(NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+
+ switch (p->n_type) {
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+ break;
+ 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;
+ }
+}
+#endif
+
+/* 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)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+/* 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(" .comm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .comm %s,0%o\n", exname(q->sname), off);
+#endif
+}
+
+/* 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(" .lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+ printf(" .%s\n", loctbl[locc]);
+}
+
+#if 0
+int
+ftoint(NODE *p, CONSZ **c)
+{
+ static CONSZ cc[3];
+ union { float f; double d; long double l; int i[3]; } u;
+ int n;
+
+ switch (p->n_type) {
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ n = SZLDOUBLE;
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ n = SZDOUBLE;
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ n = SZFLOAT;
+ break;
+ }
+ cc[0] = u.i[0];
+ cc[1] = u.i[1];
+ cc[2] = u.i[2];
+ *c = cc;
+ return n;
+}
+#endif
diff --git a/usr.bin/pcc/arch/x86/local2.c b/usr.bin/pcc/arch/x86/local2.c
new file mode 100644
index 00000000000..ec3c521a3db
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/local2.c
@@ -0,0 +1,1051 @@
+/* $Id: local2.c,v 1.1 2007/09/15 18:12:31 otto Exp $ */
+/*
+ * 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;
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int regoff[7];
+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, j;
+
+ printf(" pushl %%ebp\n");
+ printf(" movl %%esp,%%ebp\n");
+ if (addto)
+ printf(" subl $%d,%%esp\n", addto);
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
+ if (i & 1)
+ fprintf(stdout, " movl %s,-%d(%s)\n",
+ rnames[j], regoff[j], rnames[FPREG]);
+}
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int i, j, addto;
+
+ addto = p2maxautooff;
+ if (addto >= AUTOINIT/SZCHAR)
+ addto -= AUTOINIT/SZCHAR;
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1) {
+ addto += SZINT/SZCHAR;
+ regoff[j] = addto;
+ }
+ }
+ return addto;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+
+ ftype = ipp->ipp_type;
+ if (ipp->ipp_vis)
+ printf(" .globl %s\n", ipp->ipp_name);
+ printf(" .align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+ prtprolog(ipp, addto);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i, j;
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1)
+ fprintf(stdout, " movl -%d(%s),%s\n",
+ regoff[j], rnames[FPREG], rnames[j]);
+
+ }
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ printf(" movl 8(%%ebp),%%eax\n");
+ printf(" leave\n");
+ printf(" ret $4\n");
+ } else {
+ printf(" leave\n");
+ printf(" ret\n");
+ }
+}
+
+/*
+ * 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;
+ 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 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;
+ }
+}
+
+/*
+ * Emit code to compare two longlong numbers.
+ */
+static void
+twollcomp(NODE *p)
+{
+ int o = p->n_op;
+ int s = getlab();
+ int e = p->n_label;
+ int cb1, cb2;
+
+ if (o >= ULE)
+ o -= (ULE-LE);
+ switch (o) {
+ case NE:
+ cb1 = 0;
+ cb2 = NE;
+ break;
+ case EQ:
+ cb1 = NE;
+ cb2 = 0;
+ break;
+ case LE:
+ case LT:
+ cb1 = GT;
+ cb2 = LT;
+ break;
+ case GE:
+ case GT:
+ cb1 = LT;
+ cb2 = GT;
+ break;
+
+ default:
+ cb1 = cb2 = 0; /* XXX gcc */
+ }
+ if (p->n_op >= ULE)
+ cb1 += 4, cb2 += 4;
+ expand(p, 0, " cmpl UR,UL\n");
+ if (cb1) cbgen(cb1, s);
+ if (cb2) cbgen(cb2, e);
+ expand(p, 0, " cmpl AR,AL\n");
+ cbgen(p->n_op, e);
+ deflab(s);
+}
+
+/*
+ * Assign to a bitfield.
+ * Clumsy at least, but what to do?
+ */
+static void
+bfasg(NODE *p)
+{
+ NODE *fn = p->n_left;
+ int shift = UPKFOFF(fn->n_rval);
+ int fsz = UPKFSZ(fn->n_rval);
+ int andval, tch = 0;
+
+ /* get instruction size */
+ switch (p->n_type) {
+ case CHAR: case UCHAR: tch = 'b'; break;
+ case SHORT: case USHORT: tch = 'w'; break;
+ case INT: case UNSIGNED: tch = 'l'; break;
+ default: comperr("bfasg");
+ }
+
+ /* put src into a temporary reg */
+ fprintf(stdout, " mov%c ", tch);
+ adrput(stdout, getlr(p, 'R'));
+ fprintf(stdout, ",");
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* AND away the bits from dest */
+ andval = ~(((1 << fsz) - 1) << shift);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+
+ /* AND away unwanted bits from src */
+ andval = ((1 << fsz) - 1);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* SHIFT left src number of bits */
+ if (shift) {
+ fprintf(stdout, " sal%c $%d,", tch, shift);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+ }
+
+ /* OR in src to dest */
+ fprintf(stdout, " or%c ", tch);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, ",");
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+}
+
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+ FILE *fp = stdout;
+
+ fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
+ fprintf(fp, " pushl $%d\n", p->n_stsize);
+ expand(p, 0, " pushl AL\n");
+ expand(p, 0, " leal 8(%esp),A1\n");
+ expand(p, 0, " pushl A1\n");
+ fprintf(fp, " call memcpy\n");
+ fprintf(fp, " addl $12,%%esp\n");
+}
+
+/*
+ * Compare two floating point numbers.
+ */
+static void
+fcomp(NODE *p)
+{
+
+ if (p->n_left->n_op == REG) {
+ if (p->n_su & DORIGHT)
+ expand(p, 0, " fxch\n");
+ expand(p, 0, " fucompp\n"); /* emit compare insn */
+ } else if (p->n_left->n_type == DOUBLE)
+ expand(p, 0, " fcompl AL\n"); /* emit compare insn */
+ else if (p->n_left->n_type == FLOAT)
+ expand(p, 0, " fcomp AL\n"); /* emit compare insn */
+ else
+ comperr("bad compare %p\n", p);
+ expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */
+
+ switch (p->n_op) {
+ case EQ:
+ expand(p, 0, " andb $64,%ah\n jne LC\n");
+ break;
+ case NE:
+ expand(p, 0, " andb $64,%ah\n je LC\n");
+ break;
+ case LE:
+ expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
+ break;
+ case LT:
+ expand(p, 0, " andb $65,%ah\n je LC\n");
+ break;
+ case GT:
+ expand(p, 0, " andb $1,%ah\n jne LC\n");
+ break;
+ case GE:
+ expand(p, 0, " andb $65,%ah\n jne LC\n");
+ break;
+ default:
+ comperr("fcomp op %d\n", p->n_op);
+ }
+}
+
+/*
+ * Convert an unsigned long long to floating point number.
+ */
+static void
+ulltofp(NODE *p)
+{
+ static int loadlab;
+ int jmplab;
+
+ if (loadlab == 0) {
+ loadlab = getlab();
+ expand(p, 0, " .data\n");
+ printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
+ expand(p, 0, " .text\n");
+ }
+ jmplab = getlab();
+ expand(p, 0, " pushl UL\n pushl AL\n");
+ expand(p, 0, " fildq (%esp)\n");
+ expand(p, 0, " addl $8,%esp\n");
+ expand(p, 0, " cmpl $0,UL\n");
+ printf(" jge " LABFMT "\n", jmplab);
+ printf(" fldt " LABFMT "\n", loadlab);
+ printf(" faddp %%st,%%st(1)\n");
+ printf(LABFMT ":\n", jmplab);
+}
+
+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 12;
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *r, *l;
+ int pr, lr, s;
+ char *ch;
+
+ switch (c) {
+ case 'A': /* swap st0 and st1 if right is evaluated second */
+ if ((p->n_su & DORIGHT) == 0) {
+ if (logop(p->n_op))
+ printf(" fxch\n");
+ else
+ printf("r");
+ }
+ break;
+
+ case 'C': /* remove from stack after subroutine call */
+ pr = p->n_qual;
+ if (p->n_op == STCALL || p->n_op == USTCALL)
+ pr += 4;
+ if (p->n_op == UCALL)
+ return; /* XXX remove ZC from UCALL */
+ if (pr)
+ printf(" addl $%d, %s\n", pr, rnames[ESP]);
+ break;
+
+ case 'D': /* Long long comparision */
+ twollcomp(p);
+ break;
+
+ case 'E': /* Assign to bitfield */
+ bfasg(p);
+ break;
+
+ case 'F': /* Structure argument */
+ if (p->n_stalign != 0) /* already on stack */
+ starg(p);
+ break;
+
+ case 'G': /* Floating point compare */
+ fcomp(p);
+ break;
+
+ case 'J': /* convert unsigned long long to floating point */
+ ulltofp(p);
+ break;
+
+ case 'M': /* Output sconv move, if needed */
+ l = getlr(p, 'L');
+ /* XXX fixneed: regnum */
+ pr = DECRA(p->n_reg, 0);
+ lr = DECRA(l->n_reg, 0);
+ if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
+ (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
+ ;
+ else
+ printf(" movb %%%cl,%s\n",
+ rnames[lr][2], rnames[pr]);
+ l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
+ break;
+
+ case 'N': /* output extended reg name */
+ printf("%s", rnames[getlr(p, '1')->n_rval]);
+ break;
+
+ case 'O': /* print out emulated ops */
+ pr = 16;
+ if (p->n_op == RS || p->n_op == LS) {
+ expand(p, INAREG, "\tpushl AR\n");
+ pr = 12;
+ } else
+ expand(p, INCREG, "\tpushl UR\n\tpushl AR\n");
+ expand(p, INCREG, "\tpushl UL\n\tpushl AL\n");
+ if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
+ else if (p->n_op == DIV) ch = "div";
+ else if (p->n_op == MUL) ch = "mul";
+ else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
+ else if (p->n_op == MOD) ch = "mod";
+ else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshr";
+ else if (p->n_op == RS) ch = "ashr";
+ else if (p->n_op == LS) ch = "ashl";
+ else ch = 0, comperr("ZO");
+ printf("\tcall __%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]);
+ break;
+
+ case 'P': /* push hidden argument on stack */
+ r = (NODE *)p->n_sue;
+ printf("\tleal -%d(%%ebp),", stkpos);
+ adrput(stdout, getlr(p, '1'));
+ printf("\n\tpushl ");
+ adrput(stdout, getlr(p, '1'));
+ putchar('\n');
+ break;
+
+ case 'Q': /* emit struct assign */
+ /* XXX - optimize for small structs */
+ printf("\tpushl $%d\n", p->n_stsize);
+ expand(p, INAREG, "\tpushl AR\n");
+ expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n");
+ printf("\tcall memcpy\n");
+ printf("\taddl $12,%%esp\n");
+ break;
+
+ case 'S': /* emit eventual move after cast from longlong */
+ pr = DECRA(p->n_reg, 0);
+ lr = p->n_left->n_rval;
+ switch (p->n_type) {
+ case CHAR:
+ case UCHAR:
+ if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
+ rnames[pr][1] == rnames[lr][1])
+ break;
+ if (rnames[lr][2] == 'x') {
+ printf("\tmovb %%%cl,%s\n",
+ rnames[lr][1], rnames[pr]);
+ break;
+ }
+ /* Must go via stack */
+ s = BITOOR(freetemp(1));
+ printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s);
+ printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]);
+// comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
+ break;
+
+ case SHORT:
+ case USHORT:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovw %%%c%c,%%%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]+2);
+ break;
+ case INT:
+ case UNSIGNED:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovl %%e%c%c,%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]);
+ break;
+
+ default:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]);
+ break;
+ }
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+#if 0
+ int r;
+
+ if (p->n_op == STARG )
+ p = p->n_left;
+
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
+
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return(0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
+
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
+
+ if (optype(p->n_op) != LTYPE)
+ return(0);
+ return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+ printf("$" CONFMT, val);
+}
+
+void
+conput(FILE *fp, NODE *p)
+{
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput, p %p", p);
+ }
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+ comperr("insput");
+}
+
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
+void
+upput(NODE *p, int size)
+{
+
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+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 NAME:
+ if (p->n_name[0] != '\0') {
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ } else
+ fprintf(io, CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+ if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+ if (R2TEST(r)) {
+ fprintf(io, "(%s,%s,4)", rnames[R2UPK1(r)],
+ rnames[R2UPK2(r)]);
+ } else
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ fputc('$', io);
+ conput(io, p);
+ return;
+
+ case MOVE:
+ case REG:
+ switch (p->n_type) {
+ case LONGLONG:
+ case ULONGLONG:
+ fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
+ rnames[p->n_rval][1], rnames[p->n_rval][2]);
+ break;
+ case SHORT:
+ case USHORT:
+ fprintf(io, "%%%s", &rnames[p->n_rval][2]);
+ break;
+ default:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ }
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+static char *
+ccbranches[] = {
+ "je", /* jumpe */
+ "jne", /* jumpn */
+ "jle", /* jumple */
+ "jl", /* jumpl */
+ "jge", /* jumpge */
+ "jg", /* jumpg */
+ "jbe", /* jumple (jlequ) */
+ "jb", /* jumpl (jlssu) */
+ "jae", /* jumpge (jgequ) */
+ "ja", /* jumpg (jgtru) */
+};
+
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+ if (o < EQ || o > UGT)
+ comperr("bad conditional branch: %s", opst[o]);
+ printf(" %s " LABFMT "\n", ccbranches[o-EQ], 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;
+ }
+}
+
+/*
+ * Must store floats in memory if there are two function calls involved.
+ */
+static int
+storefloat(struct interpass *ip, NODE *p)
+{
+ int l, r;
+
+ switch (optype(p->n_op)) {
+ case BITYPE:
+ l = storefloat(ip, p->n_left);
+ r = storefloat(ip, p->n_right);
+ if (p->n_op == CM)
+ return 0; /* arguments, don't care */
+ if (callop(p->n_op))
+ return 1; /* found one */
+#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
+ (p)->n_type == LDOUBLE)
+ if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
+ /* must store one. store left */
+ struct interpass *nip;
+ TWORD t = p->n_left->n_type;
+ NODE *ll;
+ int off;
+
+ off = BITOOR(freetemp(szty(t)));
+ ll = mklnode(OREG, off, FPREG, t);
+ nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
+ p->n_left = mklnode(OREG, off, FPREG, t);
+ DLIST_INSERT_BEFORE(ip, nip, qelem);
+ }
+ return l|r;
+
+ case UTYPE:
+ l = storefloat(ip, p->n_left);
+ if (callop(p->n_op))
+ l = 1;
+ return l;
+ default:
+ return 0;
+ }
+}
+
+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);
+ storefloat(ip, ip->ip_node);
+ }
+ 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)
+{
+}
+
+static char rl[] =
+ { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI };
+static char rh[] =
+ { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI };
+
+void
+rmove(int s, int d, TWORD t)
+{
+ int sl, sh, dl, dh;
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+#if 1
+ sl = rl[s-EAXEDX];
+ sh = rh[s-EAXEDX];
+ dl = rl[d-EAXEDX];
+ dh = rh[d-EAXEDX];
+
+ /* 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(" movl %s,%s\n", rnames[sl], rnames[dl]);
+ if (sh != dh)
+ printf(" movl %s,%s\n", rnames[sh], rnames[dh]);
+#else
+ if (memcmp(rnames[s], rnames[d], 3) != 0)
+ printf(" movl %%%c%c%c,%%%c%c%c\n",
+ rnames[s][0],rnames[s][1],rnames[s][2],
+ rnames[d][0],rnames[d][1],rnames[d][2]);
+ if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
+ printf(" movl %%%c%c%c,%%%c%c%c\n",
+ rnames[s][3],rnames[s][4],rnames[s][5],
+ rnames[d][3],rnames[d][4],rnames[d][5]);
+#endif
+ break;
+ case CHAR:
+ case UCHAR:
+ printf(" movb %s,%s\n", rnames[s], rnames[d]);
+ break;
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+#ifdef notdef
+ /* a=b()*c(); will generate this */
+ comperr("bad float rmove: %d %d", s, d);
+#endif
+ break;
+ default:
+ printf(" movl %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 = r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ num += r[CLASSA];
+ return num < 6;
+ case CLASSB:
+ num = r[CLASSA];
+ num += 2*r[CLASSC];
+ num += r[CLASSB];
+ return num < 4;
+ case CLASSC:
+ num = r[CLASSA];
+ num += r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ return num < 5;
+ case CLASSD:
+ return r[CLASSD] < DREGCNT;
+ }
+ return 0; /* XXX gcc */
+}
+
+char *rnames[] = {
+ "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
+ "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
+ "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
+ "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
+ "ebxesi", "ebxedi", "esiedi",
+ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ if (t == CHAR || t == UCHAR)
+ return CLASSB;
+ if (t == LONGLONG || t == ULONGLONG)
+ return CLASSC;
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return CLASSD;
+ return CLASSA;
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+ NODE *op = p;
+ int size = 0;
+
+ p->n_qual = 0;
+ 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 SPCON:
+ if (o != ICON || p->n_name[0] || p->n_lval < 0)
+ break;
+ return SRDIR;
+ }
+ return SRNOPE;
+}
diff --git a/usr.bin/pcc/arch/x86/macdefs.h b/usr.bin/pcc/arch/x86/macdefs.h
new file mode 100644
index 00000000000..46cf123c4ae
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/macdefs.h
@@ -0,0 +1,301 @@
+/* $Id: macdefs.h,v 1.1 2007/09/15 18:12:31 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT 64 /* # bits above fp where arguments start */
+#define AUTOINIT 0 /* # bits below fp where automatics start */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZBOOL 8
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 96
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 32
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALBOOL 8
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 32
+#define ALLDOUBLE 32
+#define ALLONG 32
+#define ALLONGLONG 32
+#define ALSHORT 16
+#define ALPOINT 32
+#define ALSTRUCT 32
+#define ALSTACK 32
+
+/*
+ * 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
+
+/* Default char is signed */
+#undef CHAR_UNSIGNED
+#define BOOL_TYPE CHAR /* what used to store _Bool */
+#define WCHAR_TYPE INT /* what used to store wchar_t */
+
+/*
+ * Use large-enough types.
+ */
+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 */
+#ifdef FORTRAN
+#define XL 8
+#define FLABELFMT "%s:\n"
+#define USETEXT ".text"
+#define USECONST ".data\t0" /* XXX - fix */
+#define USEBSS ".data\t1" /* XXX - fix */
+#define USEINIT ".data\t2" /* XXX - fix */
+#define MAXREGVAR 3 /* XXX - fix */
+#define BLANKCOMMON "_BLNK_"
+#define MSKIREG (M(TYSHORT)|M(TYLONG))
+#define TYIREG TYLONG
+#define FSZLENG FSZLONG
+#define FUDGEOFFSET 1
+#define AUTOREG EBP
+#define ARGREG EBP
+#define ARGOFFSET 4
+#endif
+
+#define BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+/* Definitions mostly used in pass2 */
+
+#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 genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1)
+
+/*
+ * The x86 has a bunch of register classes, most of them interfering
+ * with each other. All registers are given a sequential number to
+ * identify it which must match rnames[] in local2.c.
+ * Class membership and overlaps are defined in the macros RSTATUS
+ * and ROVERLAP below.
+ *
+ * The classes used on x86 are:
+ * A - short and int regs
+ * B - char regs
+ * C - long long regs
+ * D - floating point
+ */
+#define EAX 000 /* Scratch and return register */
+#define EDX 001 /* Scratch and secondary return register */
+#define ECX 002 /* Scratch (and shift count) register */
+#define EBX 003 /* GDT pointer or callee-saved temporary register */
+#define ESI 004 /* Callee-saved temporary register */
+#define EDI 005 /* Callee-saved temporary register */
+#define EBP 006 /* Frame pointer */
+#define ESP 007 /* Stack pointer */
+
+#define AL 010
+#define AH 011
+#define DL 012
+#define DH 013
+#define CL 014
+#define CH 015
+#define BL 016
+#define BH 017
+
+#define EAXEDX 020
+#define EAXECX 021
+#define EAXEBX 022
+#define EAXESI 023
+#define EAXEDI 024
+#define EDXECX 025
+#define EDXEBX 026
+#define EDXESI 027
+#define EDXEDI 030
+#define ECXEBX 031
+#define ECXESI 032
+#define ECXEDI 033
+#define EBXESI 034
+#define EBXEDI 035
+#define ESIEDI 036
+
+/* The 8 math registers in class D lacks names */
+
+#define MAXREGS 047 /* 39 registers */
+
+#define RSTATUS \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, 0, 0, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG,
+
+#define ROVERLAP \
+ /* 8 basic registers */\
+ { AL, AH, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { DL, DH, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { CL, CH, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { BL, BH, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EAXESI, EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EAXEDI, EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { -1 },\
+ { -1 },\
+\
+ /* 8 char registers */\
+ { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+\
+ /* 15 long-long-emulating registers */\
+ { EAX, AL, AH, EDX, DL, DH, EAXECX, EAXEBX, EAXESI, /* eaxedx */\
+ EAXEDI, EDXECX, EDXEBX, EDXESI, EDXEDI, -1, },\
+ { EAX, AL, AH, ECX, CL, CH, EAXEDX, EAXEBX, EAXESI, /* eaxecx */\
+ EAXEDI, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EAX, AL, AH, EBX, BL, BH, EAXEDX, EAXECX, EAXESI, /* eaxebx */\
+ EAXEDI, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EAX, AL, AH, ESI, EAXEDX, EAXECX, EAXEBX, EAXEDI, /* eaxesi */\
+ EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EAX, AL, AH, EDI, EAXEDX, EAXECX, EAXEBX, EAXESI, /* eaxedi */\
+ EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { EDX, DL, DH, ECX, CL, CH, EAXEDX, EAXECX, EDXEBX, /* edxecx */\
+ EDXESI, EDXEDI, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EDX, DL, DH, EBX, BL, BH, EAXEDX, EDXECX, EDXESI, /* edxebx */\
+ EDXEDI, EAXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EDX, DL, DH, ESI, EAXEDX, EDXECX, EDXEBX, EDXEDI, /* edxesi */\
+ EAXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EDX, DL, DH, EDI, EAXEDX, EDXECX, EDXEBX, EDXESI, /* edxedi */\
+ EAXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { ECX, CL, CH, EBX, BL, BH, EAXECX, EDXECX, ECXESI, /* ecxebx */\
+ ECXEDI, EAXEBX, EDXEBX, EBXESI, EBXEDI, -1 },\
+ { ECX, CL, CH, ESI, EAXECX, EDXECX, ECXEBX, ECXEDI, /* ecxesi */\
+ EAXESI, EDXESI, EBXESI, ESIEDI, -1 },\
+ { ECX, CL, CH, EDI, EAXECX, EDXECX, ECXEBX, ECXESI, /* ecxedi */\
+ EAXEDI, EDXEDI, EBXEDI, ESIEDI, -1 },\
+ { EBX, BL, BH, ESI, EAXEBX, EDXEBX, ECXEBX, EBXEDI, /* ebxesi */\
+ EAXESI, EDXESI, ECXESI, ESIEDI, -1 },\
+ { EBX, BL, BH, EDI, EAXEBX, EDXEBX, ECXEBX, EBXESI, /* ebxedi */\
+ EAXEDI, EDXEDI, ECXEDI, ESIEDI, -1 },\
+ { ESI, EDI, EAXESI, EDXESI, ECXESI, EBXESI, /* esiedi */\
+ EAXEDI, EDXEDI, ECXEDI, EBXEDI, -1 },\
+\
+ /* The fp registers do not overlap with anything */\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },
+
+
+/* Return a register class based on the type of the node */
+#define PCLASS(p) (p->n_type <= UCHAR ? SBREG : \
+ (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SCREG : \
+ (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SDREG : SAREG)))
+
+#define NUMCLASS 4 /* highest number of reg classes used */
+
+int COLORMAP(int c, int *r);
+#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : x < 31 ? CLASSC : CLASSD)
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 6) /* A1 */
+#define ENCRA2(x) ((x) << 12) /* A2 */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+/* XXX - return char in al? */
+#define RETREG(x) (x == CHAR || x == UCHAR ? AL : \
+ x == LONGLONG || x == ULONGLONG ? EAXEDX : \
+ x == FLOAT || x == DOUBLE || x == LDOUBLE ? 31 : EAX)
+
+//#define R2REGS 1 /* permit double indexing */
+
+/* XXX - to die */
+#define FPREG EBP /* frame pointer */
+#define STKREG ESP /* stack pointer */
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+
+#define SHSTR (MAXSPECIAL+1) /* short struct */
+#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
+#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */
diff --git a/usr.bin/pcc/arch/x86/order.c b/usr.bin/pcc/arch/x86/order.c
new file mode 100644
index 00000000000..35bd53c1f9b
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/order.c
@@ -0,0 +1,287 @@
+/* $Id: order.c,v 1.1 2007/09/15 18:12:31 otto Exp $ */
+/*
+ * 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;
+ }
+ if (r->n_op == LS && r->n_right->n_op == ICON &&
+ r->n_right->n_lval == 2 && p->n_op == PLUS) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ if (isreg(r->n_left) == 0)
+ (void)geninsn(r->n_left, INAREG);
+ 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 x86 */
+ 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)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+/*
+ * Special handling of some instruction register allocation.
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ switch (q->op) {
+ case OPLOG:
+ {
+ static struct rspecial s[] = { { NEVER, EAX }, { 0 } };
+ return s;
+ }
+
+ case STASG:
+ case STARG:
+ {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { 0 } };
+ return s;
+ }
+
+ case SCONV:
+ if ((q->ltype & (TINT|TUNSIGNED|TSHORT|TUSHORT)) &&
+ q->rtype == (TCHAR|TUCHAR)) {
+ static struct rspecial s[] = {
+ { NOLEFT, ESI }, { NOLEFT, EDI }, { 0 } };
+ return s;
+ } else if ((q->ltype & (TINT|TUNSIGNED)) &&
+ q->rtype == TLONGLONG) {
+ static struct rspecial s[] = {
+ { NLEFT, EAX }, { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ } else if (q->ltype == TSHORT &&
+ q->rtype == (TLONGLONG|TULONGLONG)) {
+ static struct rspecial s[] = {
+ { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ } else if (q->ltype == TCHAR &&
+ q->rtype == (TLONGLONG|TULONGLONG)) {
+ static struct rspecial s[] = {
+ { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ }
+ break;
+ case DIV:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EAX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case MOD:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AH },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EDX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case MUL:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case LS:
+ case RS:
+ if (q->visit & (INAREG|INBREG)) {
+ static struct rspecial s[] = {
+ { NRIGHT, CL }, { NOLEFT, ECX }, { 0 } };
+ return s;
+ } else if (q->visit & INCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+
+ default:
+ break;
+ }
+ 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 x86 */
+}
diff --git a/usr.bin/pcc/arch/x86/table.c b/usr.bin/pcc/arch/x86/table.c
new file mode 100644
index 00000000000..cf41ecb1bc4
--- /dev/null
+++ b/usr.bin/pcc/arch/x86/table.c
@@ -0,0 +1,1453 @@
+/* $Id: table.c,v 1.1 2007/09/15 18:12:31 otto Exp $ */
+/*
+ * 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 SHINT SAREG /* short and int */
+#define ININT INAREG
+#define SHCH SBREG /* shape for char */
+#define INCH INBREG
+#define SHLL SCREG /* shape for long long */
+#define INLL INCREG
+#define SHFL SDREG /* shape for float/double */
+#define INFL INDREG /* shape for float/double */
+
+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 (u)char to (u)char. */
+{ SCONV, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ 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 double <-> float. nothing to do here */
+{ SCONV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to pointers. */
+{ SCONV, ININT,
+ SHINT, TPOINT,
+ SANY, TPOINT,
+ 0, RLEFT,
+ "", },
+
+/* char to something */
+
+/* convert char to (unsigned) short. */
+{ SCONV, ININT,
+ SBREG|SOREG|SNAME, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movsbw AL,A1\n", },
+
+/* convert unsigned char to (u)short. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movzbw AL,A1\n", },
+
+/* convert signed char to int (or pointer). */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TCHAR,
+ SAREG, TWORD|TPOINT,
+ NASL|NAREG, RESC1,
+ " movsbl AL,A1\n", },
+
+/* convert unsigned char to (u)int. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzbl AL,A1\n", },
+
+/* convert char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SANY, TLL,
+ NSPECIAL|NAREG|NASL, RESC1,
+ " movsbl AL,%eax\n cltd\n", },
+
+/* convert unsigned char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SANY, TLL,
+ NCREG|NCSL, RESC1,
+ " movzbl AL,A1\n xorl U1,U1\n", },
+
+/* convert char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movsbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* convert (u)char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movzbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* short to something */
+
+/* convert short (in memory) to char */
+{ SCONV, INCH,
+ SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert short (in reg) to char. */
+{ SCONV, INCH,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movswl AL,A1\n", },
+
+/* convert unsigned short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzwl AL,A1\n", },
+
+/* convert short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TSHORT,
+ SHLL, TLL,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " movswl AL,%eax\n cltd\n", },
+
+/* convert unsigned short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHLL, TLL,
+ NCREG|NCSL, RESC1,
+ " movzwl AL,A1\n xorl U1,U1\n", },
+
+/* convert short (in memory) to float/double */
+{ SCONV, INFL,
+ SOREG|SNAME, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fild AL\n", },
+
+/* convert short (in register) to float/double */
+{ SCONV, INFL,
+ SAREG, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushw AL\n fild (%esp)\n addl $2,%esp\n", },
+
+/* convert unsigned short to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG|NTEMP, RESC2,
+ " movzwl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* int to something */
+
+/* convert int to char. This is done when register is loaded */
+{ SCONV, INCH,
+ SAREG, TWORD,
+ SANY, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert int to short. Nothing to do */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SANY, TSHORT|TUSHORT,
+ 0, RLEFT,
+ "", },
+
+/* convert int to long long */
+{ SCONV, INLL,
+ SAREG, TWORD|TPOINT,
+ SCREG, TLONGLONG,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " cltd\n", },
+
+/* convert int to unsigned long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SHLL, TULONGLONG,
+ NCSL|NCREG, RESC1,
+ " movl AL,A1\n xorl U1,U1\n", },
+
+/* convert int (in memory) to double */
+{ SCONV, INFL,
+ SOREG|SNAME, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildl AL\n", },
+
+/* convert int (in register) to double */
+{ SCONV, INFL,
+ SAREG, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl AL\n fildl (%esp)\n addl $4,%esp\n", },
+
+/* long long to something */
+
+/* convert (u)long long to (u)char (mem->reg) */
+{ SCONV, INCH,
+ SOREG|SNAME, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
+{ SCONV, INCH,
+ SHLL, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert (u)long long to (u)short (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long to int (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+/* convert long long to int (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long (in memory) to floating */
+{ SCONV, INFL,
+ SOREG|SNAME, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildq AL\n", },
+
+/* convert long long (in register) to floating */
+{ SCONV, INFL,
+ SHLL, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl UL\n pushl AL\n"
+ " fildq (%esp)\n addl $8,%esp\n", },
+
+/* convert unsigned long long to floating */
+{ SCONV, INFL,
+ SCREG, TULONGLONG,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ "ZJ", },
+
+/* float to something */
+
+#if 0 /* go via int by adding an extra sconv in clocal() */
+/* convert float/double to (u) char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double to (u) int/short/char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NCREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#endif
+
+/* convert float/double to (u)int. XXX should use NTEMP here */
+{ SCONV, INAREG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double (in register) to (unsigned) long long */
+/* XXX - unsigned is not handled correct */
+{ SCONV, INLL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHLL, TLONGLONG|TULONGLONG,
+ NCREG, RESC1,
+ " subl $8,%esp\n fistpq (%esp)\n"
+ " popl A1\n popl U1\n", },
+
+/* slut sconv */
+
+/*
+ * Subroutine calls.
+ */
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL\nZC", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ 0, 0,
+ " call CL\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+/* struct return */
+{ USTCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+{ STCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+/*
+ * The next rules handle all binop-style operators.
+ */
+/* Special treatment for long long */
+{ PLUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " addl AR,AL\n adcl UR,UL\n", },
+
+/* Special treatment for long long XXX - fix commutative check */
+{ PLUS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RRIGHT,
+ " addl AL,AR\n adcl UL,UR\n", },
+
+{ PLUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " faddl AR\n", },
+
+{ PLUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " faddp\n", },
+
+{ PLUS, INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incl AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal CR(AL),A1\n", },
+
+{ PLUS, INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " incb AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ NAREG|NASL|NASR, RESC1,
+ " leal (AL,AR),A1\n", },
+
+
+/* address as register offset, negative */
+{ MINUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal -CR(AL),A1\n", },
+
+{ MINUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " subl AR,AL\n sbbl UR,UL\n", },
+
+{ MINUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fsubl AR\n", },
+
+{ MINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fsubZAp\n", },
+
+/* Simple r/m->reg ops */
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT, TSHORT|TUSHORT,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " Ol AR,AL\n Ol UR,UL\n", },
+
+
+/*
+ * The next rules handle all shift operators.
+ */
+/* (u)longlong left shift is emulated */
+{ LS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG, TWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " salb AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " salb AR,AL\n", },
+
+/* (u)longlong right shift is emulated */
+{ RS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrb AR,AL\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+{ ASSIGN, FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, 0,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, 0,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR|TWORD,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SFLD, TCHAR|TUCHAR,
+ SBREG|SCON, TCHAR|TUCHAR,
+ NBREG, RDEST,
+ "ZE", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TANY,
+ SAREG, TANY,
+ NAREG, RDEST,
+ "ZE", },
+
+{ ASSIGN, FOREFF,
+ SFLD, TANY,
+ SAREG|SNAME|SOREG|SCON, TANY,
+ NAREG, 0,
+ "ZE", },
+
+{ ASSIGN, INDREG|FOREFF,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "", }, /* This will always be in the correct register */
+
+/* order of table entries is very important here! */
+{ ASSIGN, INFL,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstt AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpt AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstl AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpl AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fsts AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstps AL\n", },
+/* end very important order */
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TLDOUBLE,
+ SHFL|SOREG|SNAME, TLDOUBLE,
+ 0, RDEST,
+ " fldt AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TDOUBLE,
+ SHFL|SOREG|SNAME, TDOUBLE,
+ 0, RDEST,
+ " fldl AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TFLOAT,
+ SHFL|SOREG|SNAME, TFLOAT,
+ 0, RDEST,
+ " flds AR\n", },
+
+/* Do not generate memcpy if return from funcall */
+#if 0
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME|SAREG, TPTRTO|TSTRUCT,
+ SFUNCALL, TPTRTO|TSTRUCT,
+ 0, RRIGHT,
+ "", },
+#endif
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG|SOREG|SNAME, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+/*
+ * DIV/MOD/MUL
+ */
+/* long long div is emulated */
+{ DIV, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ DIV, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TWORD,
+ NSPECIAL, RDEST,
+ " cltd\n idivl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ DIV, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NSPECIAL, RDEST,
+ " xorb %ah,%ah\n divb AR\n", },
+
+{ DIV, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fdivl AR\n", },
+
+{ DIV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fdivZAp\n", },
+
+/* (u)longlong mod is emulated */
+{ MOD, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MOD, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TSWORD,
+ NAREG|NSPECIAL, RESC1,
+ " cltd\n idivl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ MOD, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NBREG|NSPECIAL, RESC1,
+ " xorb %ah,%ah\n divb AR\n", },
+
+/* (u)longlong mul is emulated */
+{ MUL, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MUL, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " imull AR,AL\n", },
+
+{ MUL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imulw AR,AL\n", },
+
+{ MUL, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ NSPECIAL, RDEST,
+ " imulb AR\n", },
+
+{ MUL, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fmull AR\n", },
+
+{ MUL, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fmulp\n", },
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INLL,
+ SANY, TANY,
+ SOREG, TLL,
+ NCREG|NCSL, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TPOINT|TWORD,
+ SOREG, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ UMUL, INCH,
+ SANY, TANY,
+ SOREG, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldt AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldl AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NDREG|NDSL, RESC1,
+ " flds AL\n", },
+
+/*
+ * Logical/branching operators
+ */
+
+/* Comparisions, take care of everything */
+{ OPLOG, FORCC,
+ SHLL|SOREG|SNAME, TLL,
+ SHLL, TLL,
+ 0, 0,
+ "ZD", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SCON|SAREG, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCON|SAREG, TWORD|TPOINT,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TANY,
+ 0, RESCC,
+ " cmpw AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TANY,
+ 0, RESCC,
+ " cmpb AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+{ OPLOG, FORCC,
+ SOREG|SNAME, TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+#if 0
+/* Ppro and later only */
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RESCC,
+ "ZA fucomip %st,%st(1)\n", },
+#endif
+
+{ OPLOG, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "diediedie!", },
+
+/* AND/OR/ER/NOT */
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TWORD,
+ SCON|SAREG, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG|SOREG|SNAME, TLL,
+ 0, RLEFT,
+ " andl AR,AL\n andl UR,UL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TWORD,
+ SAREG|SOREG|SNAME, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+/* AND/OR/ER/NOT */
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp LL\n", },
+
+#ifdef GCC_COMPAT
+{ GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp *AL\n", },
+#endif
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SCREG|SCON|SOREG|SNAME, TLL,
+ NCREG, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SCON|SOREG|SNAME, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " movb AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " movw AL,A1\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TLDOUBLE,
+ SOREG|SNAME, TLDOUBLE,
+ NDREG, RESC1,
+ " fldt AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TDOUBLE,
+ SOREG|SNAME, TDOUBLE,
+ NDREG, RESC1,
+ " fldl AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT,
+ SOREG|SNAME, TFLOAT,
+ NDREG, RESC1,
+ " flds AL\n", },
+
+/* Only used in ?: constructs. The stack already contains correct value */
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT|TDOUBLE|TLDOUBLE,
+ SDREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "", },
+
+/*
+ * Negate a word.
+ */
+
+{ UMINUS, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG, TLL,
+ 0, RLEFT,
+ " negl AL\n adcl $0,UL\n negl UL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " negl AL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " negw AL\n", },
+
+{ UMINUS, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " negb AL\n", },
+
+{ UMINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fchs\n", },
+
+{ COMPL, INCREG,
+ SCREG, TLL,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n notl UL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TWORD,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RLEFT,
+ " notw AL\n", },
+
+{ COMPL, INBREG,
+ SBREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, RLEFT,
+ " notb AL\n", },
+
+/*
+ * Arguments to functions.
+ */
+{ FUNARG, FOREFF,
+ SCON|SCREG|SNAME|SOREG, TLL,
+ SANY, TLL,
+ 0, RNULL,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SANY, TSHORT,
+ NAREG, 0,
+ " movswl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SANY, TUSHORT,
+ NAREG, 0,
+ " movzwl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SANY, TCHAR,
+ NAREG, 0,
+ " movsbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SANY, TUCHAR,
+ NAREG, 0,
+ " movzbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " subl $8,%esp\n fstpl (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " subl $4,%esp\n fstps (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TLDOUBLE,
+ SANY, TLDOUBLE,
+ 0, 0,
+ " subl $12,%esp\n fstpt (%esp)\n", },
+
+{ STARG, FOREFF,
+ SAREG|SOREG|SNAME|SCON, TANY,
+ SANY, TSTRUCT,
+ NSPECIAL|NAREG, 0,
+ "ZF", },
+
+# 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]);
diff --git a/usr.bin/pcc/cc/Makefile.in b/usr.bin/pcc/cc/Makefile.in
new file mode 100644
index 00000000000..f457e761f53
--- /dev/null
+++ b/usr.bin/pcc/cc/Makefile.in
@@ -0,0 +1,38 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:31 otto Exp $
+#
+# Makefile.in for top-level of pcc.
+#
+
+@SET_MAKE@
+CC=@CC@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+CPPFLAGS=@CPPFLAGS@
+YACC=@YACC@
+LEX=@LEX@
+
+SUBDIR=cc cpp ccom
+
+all: ${SUBDIR}
+
+install:
+ cd cc && ${MAKE} install
+ cd cpp && ${MAKE} install
+ cd ccom && ${MAKE} install
+
+clean:
+ cd cc && ${MAKE} clean
+ cd cpp && ${MAKE} clean
+ cd ccom && ${MAKE} clean
+
+distclean:
+ cd cc && ${MAKE} distclean
+ cd cpp && ${MAKE} distclean
+ cd ccom && ${MAKE} distclean
+ /bin/rm -rf Makefile config.log stamp-h1 config.status \
+ configure.lineno config.h autom4te.cache
+
+${SUBDIR}: nonexistant
+ cd $@; $(MAKE) all $(MFLAGS)
+
+nonexistant:
diff --git a/usr.bin/pcc/cc/cc/Makefile.in b/usr.bin/pcc/cc/cc/Makefile.in
new file mode 100644
index 00000000000..11efe29fbbb
--- /dev/null
+++ b/usr.bin/pcc/cc/cc/Makefile.in
@@ -0,0 +1,44 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:31 otto Exp $
+#
+# Makefile.in for the cc part of pcc.
+#
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libexecdir = @libexecdir@
+includedir = @includedir@
+strip = @strip@
+CC = @CC@
+TARGOS = @targos@
+TARGMACH = @targmach@
+CFLAGS = @CFLAGS@ -DLIBEXECDIR=\"${libexecdir}\" -DINCLUDEDIR=\"${includedir}\"
+CPPFLAGS = @CPPFLAGS@ -I../../os/${TARGOS} -Dmach_${TARGMACH} -Dos_${TARGOS}
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+OBJS=cc.o
+DEST=pcc
+
+all: ${DEST}
+
+${DEST}: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+.c.o:
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
+
+install:
+ test -z "${DESTDIR}$(bindir)" || mkdir -p "${DESTDIR}$(bindir)"
+ ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${bindir}
+ @if [ ${strip} = yes ]; then \
+ strip ${DESTDIR}${bindir}/${DEST} ; \
+ echo strip ${DESTDIR}${bindir}/${DEST} ; \
+ fi
+
+clean:
+ /bin/rm -f $(OBJS) ${DEST}
+
+distclean: clean
+ /bin/rm -f Makefile
diff --git a/usr.bin/pcc/cc/cc/cc.1 b/usr.bin/pcc/cc/cc/cc.1
new file mode 100644
index 00000000000..be599e48782
--- /dev/null
+++ b/usr.bin/pcc/cc/cc/cc.1
@@ -0,0 +1,179 @@
+.\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net>
+.\"
+.\" 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 AND CONTRIBUTORS DISCLAIM
+.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
+.\" CONTRIBUTORS 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.
+.\"
+.Dd September 14, 2007
+.Dt cc 1
+.Os
+.Sh NAME
+.Nm cc
+.Nd front-end to the C compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl TODO
+.Op infile...
+.Pp
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a front-end to the PCC C compiler.
+Multiple files may be given on the command line.
+Unrecognized options are all sent directly to
+.Xr ld 1 .
+.Pp
+.\" Brief description of its syntax:
+Filenames that end with
+.Sy .c
+are passed via
+.Xr cpp 1 ->
+.Xr ccom 1 ->
+.Xr as 1 ->
+.Xr ld 1 .
+.Pp
+Filenames that end with
+.Sy .s
+are passed via
+.Xr as 1 ->
+.Xr ld 1 .
+.Pp
+Filenames that end with
+.Sy .o
+are passed directly to
+.Xr ld 1 .
+.Pp
+.\" TODO: document when -D__ASSEMBLER__ ??
+.\" TODO: document __PCC__, __PCC_MINOR__, and __PCC_MINORMINOR__
+.\"
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl B Ar prefix
+Define alternate prefix path for
+.Xr cpp 1 ,
+.Xr ccom 1 ,
+.Xr as 1 ,
+or
+.Xr ld 1
+executables.
+.\" TODO: provide an example of -B
+.It Fl c
+Only compile or assemble and then stop.
+Do not link.
+Note: cannot be combined with
+.Fl o
+if multiple files are given.
+.It Fl d
+Sent to assembler. TODO?
+.It Fl E
+Stop after preprocessing with
+.Xr cpp 1 .
+Do not compile, assemble, or link.
+.It Fl fPIC
+Generate PIC code.
+See
+.Fl k
+option.
+.\" other -f GCC compatibility flags are ignored for now
+.It Fl g
+Send
+.Fl g
+flag to
+.Xr ccom 1
+to create debug output.
+.It Fl include Ar path
+.\" TODO
+.It Fl isystem Ar path
+.\" TODO
+.It Fl k
+Tells C compiler to generate PIC code
+and tells assembler that PIC code has been generated.
+.It Fl L
+.\" TODO
+.It Fl M
+Pass
+.Fl M
+flag to
+.Xr cpp 1
+to generate dependencies for
+.Xr make 1 .
+.It Fl nostdinc
+.\" TODO
+.It Fl nostdlib
+.\" TODO
+.\" implies -nostartfiles ??
+.It Fl nostartfiles
+.\" TODO
+.It Fl o Ar outfile
+Save result to
+.Ar outfile .
+.It Fl P
+TODO: what is this?
+.It Fl pg
+Not implemented.
+.It Fl O
+.\" TODO: sets -xtemps for ccom??
+Note: this is unset if
+.Fl g
+option is set.
+.It Fl pthread
+Defines
+.Sy _PTHREADS
+preprocessor directive for
+.Xr cpp 1 .
+Uses
+.Sy -lpthread
+for
+.Xr ld 1 linker.
+.It Fl static
+Do not use dynamic linkage.
+By default, it will link using the dynamic linker options
+and/or shared objects for the platform.
+.It Fl S
+Stop after compilation by
+.Xr ccom 1 .
+Do not assemble and do not link.
+Note: cannot be combined with
+.Fl o
+if multiple files are given.
+.It Fl t
+Passes
+.Fl t
+to
+.Xr cpp 1
+for traditional C preprocessor syntax.
+.It Fl v
+Outputs the version of
+.Nm
+and shows what commands will be ran with their command line arguments.
+.It Fl x
+TODO
+.It Fl X
+TODO
+.It Fl Wl Ar flags
+Options for the linker
+.\" what is ignored? llist?
+.\" TODO: DIUC options?
+.El
+.Sh SEE ALSO
+.Xr as 1 ,
+.Xr ccom 1 ,
+.Xr cpp 1
+.Sh HISTORY
+The
+.Nm
+command comes from the original Portable C Compiler by S. C.
+Johnson, written in the late 70's.
+.Pp
+This product includes software developed or owned by Caldera
+International, Inc.
+
diff --git a/usr.bin/pcc/cc/cc/cc.c b/usr.bin/pcc/cc/cc/cc.c
new file mode 100644
index 00000000000..8d5fc2900f2
--- /dev/null
+++ b/usr.bin/pcc/cc/cc/cc.c
@@ -0,0 +1,701 @@
+/* $Id: cc.c,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+/*
+ * Front-end to the C compiler.
+ *
+ * Brief description of its syntax:
+ * - Files that end with .c are passed via cpp->ccom->as->ld
+ * - Files that end with .s are passed as->ld
+ * - Files that end with .o are passed directly to ld
+ * - Multiple files may be given on the command line.
+ * - Unrecognized options are all sent directly to ld.
+ * -c or -S cannot be combined with -o if multiple files are given.
+ *
+ * This file should be rewritten readable.
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "../../config.h"
+
+#include "ccconfig.h"
+/* C command */
+
+#define MKS(x) _MKS(x)
+#define _MKS(x) #x
+
+/*
+ * Many specific definitions, should be declared elsewhere.
+ */
+#define STDINC "/usr/include"
+
+#define SBSIZE 10000
+#define MAXINC 100
+#define MAXFIL 100
+#define MAXLIB 10000
+#define MAXAV 10000
+#define MAXOPT 100
+char *tmp3;
+char *tmp4;
+char *outfile;
+char *copy(char *as),*setsuf(char *as, char ch);
+int getsuf(char []);
+int main(int, char *[]);
+void error(char *, ...);
+void errorx(int eval, char *, ...);
+int nodup(char **, char *);
+int callsys(char [], char *[]);
+int cunlink(char *);
+void dexit(int eval);
+void idexit(int);
+char *gettmp();
+char *av[MAXAV];
+char *clist[MAXFIL];
+char *llist[MAXLIB];
+char alist[20];
+char *xlist[100];
+int xnum;
+int dflag;
+int pflag;
+int sflag;
+int cflag;
+int eflag;
+int gflag;
+int vflag;
+int tflag;
+int Eflag;
+int Oflag;
+int kflag; /* generate PIC code */
+int Mflag; /* dependencies only */
+int pgflag;
+int exfail;
+int Xflag;
+int nostartfiles, Bstatic;
+int nostdinc, nostdlib;
+int onlyas;
+int pthreads;
+
+char *pass0 = LIBEXECDIR "/ccom";
+char *passp = LIBEXECDIR "/cpp";
+char *Bflag;
+char *cppadd[] = CPPADD;
+char *dynlinker[] = DYNLINKER;
+char *crt0file = CRT0FILE;
+char *startfiles[] = STARTFILES;
+char *endfiles[] = ENDFILES;
+char *cppmdadd[] = CPPMDADD;
+#ifdef LIBCLIBS
+char *libclibs[] = LIBCLIBS;
+#else
+char *libclibs[] = { "-lc", NULL };
+#endif
+#ifndef STARTLABEL
+#define STARTLABEL "__start"
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ char *t, *u;
+ char *assource;
+ char **pv, *ptemp[MAXOPT], **pvt;
+ int nc, nl, i, j, c, nxo, na;
+
+ i = nc = nl = nxo = 0;
+ pv = ptemp;
+ while(++i < argc) {
+ if (argv[i][0] == '-')
+ switch (argv[i][1]) {
+ default:
+ goto passa;
+
+ case 'B': /* other search paths for binaries */
+ Bflag = &argv[i][2];
+ break;
+
+ case 'X':
+ Xflag++;
+ break;
+ case 'W': /* Ignore (most of) W-flags */
+ if (strncmp(argv[i], "-Wl,", 4) == 0) {
+ /* options to the linker */
+ t = &argv[i][4];
+ while ((u = strchr(t, ','))) {
+ *u++ = 0;
+ llist[nl++] = t;
+ t = u;
+ }
+ llist[nl++] = t;
+ }
+ break;
+
+ case 'f': /* GCC compatibility flags */
+ if (strcmp(argv[i], "-fPIC") == 0)
+ kflag++;
+ /* silently ignore the rest */
+ break;
+
+ case 'g': /* create debug output */
+ gflag++;
+ break;
+
+ case 'i':
+ if (strcmp(argv[i], "-isystem") == 0) {
+ *pv++ = "-S";
+ *pv++ = argv[++i];
+ } else if (strcmp(argv[i], "-include") == 0) {
+ *pv++ = "-i";
+ *pv++ = argv[++i];
+ } else
+ goto passa;
+ break;
+
+ case 'k': /* generate PIC code */
+ kflag++;
+ break;
+
+ case 'n': /* handle -n flags */
+ if (strcmp(argv[i], "-nostdinc") == 0)
+ nostdinc++;
+ if (strcmp(argv[i], "-nostdlib") == 0) {
+ nostdlib++;
+ nostartfiles++;
+ } else if (strcmp(argv[i], "-nostartfiles") == 0)
+ nostartfiles = 1;
+ else
+ goto passa;
+ break;
+
+ case 'p':
+ if (strcmp(argv[i], "-pg") == 0)
+ pgflag++;
+ else if (strcmp(argv[i], "-pthread") == 0)
+ pthreads++;
+ else
+ errorx(1, "unknown option %s", argv[i]);
+ break;
+
+ case 'x':
+ xlist[xnum++] = argv[i];
+ break;
+ case 't':
+ tflag++;
+ break;
+ case 'S':
+ sflag++;
+ cflag++;
+ break;
+ case 'o':
+ if (outfile)
+ errorx(8, "too many -o");
+ outfile = argv[++i];
+ break;
+ case 'O':
+ Oflag++;
+ break;
+ case 'E':
+ Eflag++;
+ break;
+ case 'P':
+ pflag++;
+ *pv++ = argv[i];
+ case 'c':
+ cflag++;
+ break;
+
+#if 0
+ case '2':
+ if(argv[i][2] == '\0')
+ pref = "/lib/crt2.o";
+ else {
+ pref = "/lib/crt20.o";
+ }
+ break;
+#endif
+ case 'D':
+ case 'I':
+ case 'U':
+ case 'C':
+ *pv++ = argv[i];
+ if (argv[i][2] == 0)
+ *pv++ = argv[++i];
+ if (pv >= ptemp+MAXOPT)
+ {
+ error("Too many DIUC options");
+ --pv;
+ }
+ break;
+
+ case 'M':
+ Mflag++;
+ break;
+
+ case 'd':
+ dflag++;
+ strncpy(alist, argv[i], 19);
+ break;
+ case 'v':
+ printf("%s\n", VERSSTR);
+ vflag++;
+ break;
+
+ case 's':
+ if (strcmp(argv[i], "-static") == 0)
+ Bstatic = 1;
+ else
+ goto passa;
+ break;
+ } else {
+ passa:
+ t = argv[i];
+ if (*argv[i] == '-' && argv[i][1] == 'L')
+ ;
+ else if((c=getsuf(t))=='c' || c=='S' ||
+ c=='s'|| Eflag) {
+ clist[nc++] = t;
+ if (nc>=MAXFIL)
+ {
+ error("Too many source files");
+ exit(1);
+ }
+ t = setsuf(t, 'o');
+ }
+ if (nodup(llist, t)) {
+ llist[nl++] = t;
+ if (nl >= MAXLIB)
+ {
+ error("Too many object/library files");
+ exit(1);
+ }
+ if (getsuf(t)=='o')
+ nxo++;
+ }
+ }
+ }
+ /* Sanity checking */
+ if (nc == 0 && nl == 0)
+ errorx(8, "no input files");
+ if (outfile && (cflag || sflag) && nc > 1)
+ errorx(8, "-o given with -c || -S and more than one file");
+ if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
+ errorx(8, "output file will be clobbered");
+
+ if (gflag) Oflag = 0;
+#if 0
+ if (proflag)
+ pref = "/lib/mcrt0.o";
+#endif
+ if(nc==0)
+ goto nocom;
+ if (pflag==0) {
+ tmp3 = gettmp();
+ tmp4 = gettmp();
+ }
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
+ signal(SIGINT, idexit);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */
+ signal(SIGTERM, idexit);
+ pvt = pv;
+ for (i=0; i<nc; i++) {
+ /*
+ * C preprocessor
+ */
+ if (nc>1 && !Eflag)
+ printf("%s:\n", clist[i]);
+ onlyas = 0;
+ assource = tmp3;
+ if (getsuf(clist[i])=='s') {
+ assource = clist[i];
+ onlyas = 1;
+ goto assemble;
+ } else if (getsuf(clist[i])=='S') {
+ assource = clist[i];
+ onlyas = 1;
+ }
+ if (pflag)
+ tmp4 = setsuf(clist[i], 'i');
+ na = 0;
+ av[na++] = "cpp";
+ av[na++] = "-D__PCC__=" MKS(PCC_MAJOR);
+ av[na++] = "-D__PCC_MINOR__=" MKS(PCC_MINOR);
+ av[na++] = "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR);
+ if (getsuf(clist[i])=='S')
+ av[na++] = "-D__ASSEMBLER__";
+ if (pthreads)
+ av[na++] = "-D_PTHREADS";
+ if (Mflag)
+ av[na++] = "-M";
+ for (j = 0; cppadd[j]; j++)
+ av[na++] = cppadd[j];
+ for (j = 0; cppmdadd[j]; j++)
+ av[na++] = cppmdadd[j];
+ if (tflag)
+ av[na++] = "-t";
+ for(pv=ptemp; pv <pvt; pv++)
+ av[na++] = *pv;
+ if (!nostdinc)
+ av[na++] = "-S", av[na++] = STDINC;
+ av[na++] = clist[i];
+ if (!Eflag && !Mflag)
+ av[na++] = tmp4;
+ av[na++]=0;
+ if (callsys(passp, av))
+ {exfail++; eflag++;}
+ if (Eflag || Mflag)
+ continue;
+ if (onlyas)
+ goto assemble;
+
+ /*
+ * C compiler
+ */
+ na = 0;
+ av[na++]= "ccom";
+ if (gflag)
+ av[na++] = "-g";
+ if (kflag)
+ av[na++] = "-k";
+ if (Oflag) {
+ av[na++] = "-xtemps";
+ }
+ for (j = 0; j < xnum; j++)
+ av[na++] = xlist[j];
+ av[na++] = tmp4;
+ if (pflag || exfail)
+ {
+ cflag++;
+ continue;
+ }
+ if(sflag) {
+ if (outfile)
+ assource = tmp3 = outfile;
+ else
+ assource = tmp3 = setsuf(clist[i], 's');
+ }
+ av[na++] = tmp3;
+#if 0
+ if (proflag) {
+ av[3] = "-XP";
+ av[4] = 0;
+ } else
+ av[3] = 0;
+#endif
+ av[na++] = NULL;
+ if (callsys(pass0, av)) {
+ cflag++;
+ eflag++;
+ continue;
+ }
+ if (sflag)
+ continue;
+
+ /*
+ * Assembler
+ */
+ assemble:
+ na = 0;
+ av[na++] = "as";
+ if (kflag)
+ av[na++] = "-k";
+ av[na++] = "-o";
+ if (outfile && cflag)
+ av[na++] = outfile;
+ else
+ av[na++] = setsuf(clist[i], 'o');
+ av[na++] = onlyas ? tmp4 : assource;
+ if (dflag)
+ av[na++] = alist;
+ av[na++] = 0;
+ if (callsys("/bin/as", av)) {
+ cflag++;
+ eflag++;
+ cunlink(tmp4);
+ continue;
+ }
+ cunlink(tmp4);
+ }
+
+ if (Eflag || Mflag)
+ dexit(eflag);
+
+ /*
+ * Linker
+ */
+nocom:
+ if (cflag==0 && nl!=0) {
+ j = 0;
+ av[j++] = "ld";
+ av[j++] = "-X";
+ av[j++] = "-d";
+ av[j++] = "-e";
+ av[j++] = STARTLABEL;
+ if (Bstatic == 0) { /* Dynamic linkage */
+ for (i = 0; dynlinker[i]; i++)
+ av[j++] = dynlinker[i];
+ } else
+ av[j++] = "-Bstatic";
+ if (outfile) {
+ av[j++] = "-o";
+ av[j++] = outfile;
+ }
+ if (!nostartfiles) {
+ av[j++] = crt0file;
+ for (i = 0; startfiles[i]; i++)
+ av[j++] = startfiles[i];
+ }
+ i = 0;
+ while(i<nl) {
+ av[j++] = llist[i++];
+ if (j >= MAXAV)
+ error("Too many ld options");
+ }
+#if 0
+ if (gflag)
+ av[j++] = "-lg";
+#endif
+ if (pthreads)
+ av[j++] = "-lpthread";
+ if (!nostdlib)
+ for (i = 0; libclibs[i]; i++)
+ av[j++] = libclibs[i];
+ if (!nostartfiles) {
+ for (i = 0; endfiles[i]; i++)
+ av[j++] = endfiles[i];
+ }
+ av[j++] = 0;
+ eflag |= callsys("/bin/ld", av);
+ if (nc==1 && nxo==1 && eflag==0)
+ cunlink(setsuf(clist[0], 'o'));
+ else if (nc > 0 && eflag == 0) {
+ /* remove .o files XXX ugly */
+ for (i = 0; i < nc; i++)
+ cunlink(setsuf(clist[i], 'o'));
+ }
+ }
+ dexit(eflag);
+ return 0;
+}
+
+/*
+ * exit and cleanup after interrupt.
+ */
+void
+idexit(int arg)
+{
+ dexit(100);
+}
+
+/*
+ * exit and cleanup.
+ */
+void
+dexit(int eval)
+{
+ if (!pflag && !Xflag) {
+ if (sflag==0)
+ cunlink(tmp3);
+ cunlink(tmp4);
+ }
+ exit(eval);
+}
+
+static void
+ccerror(char *s, va_list ap)
+{
+ vfprintf(Eflag ? stderr : stdout, s, ap);
+ putc('\n', Eflag? stderr : stdout);
+ exfail++;
+ cflag++;
+ eflag++;
+}
+
+/*
+ * complain a bit.
+ */
+void
+error(char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ ccerror(s, ap);
+ va_end(ap);
+}
+
+/*
+ * complain a bit and then exit.
+ */
+void
+errorx(int eval, char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ ccerror(s, ap);
+ va_end(ap);
+ dexit(eval);
+}
+
+int
+getsuf(as)
+char as[];
+{
+ register char *s;
+
+ if ((s = strrchr(as, '.')) && s[1] != '\0' && s[2] == '\0')
+ return s[1];
+ return(0);
+}
+
+/*
+ * Get basename of string s and change its suffix to ch.
+ */
+char *
+setsuf(char *s, char ch)
+{
+ s = copy(basename(s));
+ s[strlen(s) - 1] = ch;
+ return(s);
+}
+
+int
+callsys(f, v)
+char f[], *v[]; {
+ int t, status;
+ char *s;
+
+ if (vflag) {
+ fprintf(stderr, "%s ", f);
+ for (t = 1; v[t]; t++)
+ fprintf(stderr, "%s ", v[t]);
+ fprintf(stderr, "\n");
+ }
+
+ if ((t=fork())==0) {
+ if (Bflag) {
+ int len = strlen(Bflag) + 8;
+ char *a = malloc(len);
+ if ((s = strrchr(f, '/'))) {
+ strlcpy(a, Bflag, len);
+ strlcat(a, s, len);
+ execv(a, v);
+ }
+ }
+ execv(f, v);
+ if ((s = strrchr(f, '/')))
+ execvp(s+1, v);
+ printf("Can't find %s\n", f);
+ exit(100);
+ } else
+ if (t == -1) {
+ printf("Try again\n");
+ return(100);
+ }
+ while(t!=wait(&status));
+ if ((t=(status&0377)) != 0 && t!=14) {
+ if (t!=2) /* interrupt */
+ errorx(8, "Fatal error in %s", f);
+ dexit(eflag);
+ }
+ return((status>>8) & 0377);
+}
+
+char *
+copy(char *as)
+{
+ char *p;
+
+ if ((p = strdup(as)) == NULL)
+ errorx(8, "no space for file names");
+
+ return p;
+}
+
+int
+nodup(l, os)
+char **l, *os;
+{
+ register char *t, *s;
+ register int c;
+
+ s = os;
+ if (getsuf(s) != 'o')
+ return(1);
+ while((t = *l++)) {
+ while((c = *s++))
+ if (c != *t++)
+ break;
+ if (*t=='\0' && c=='\0')
+ return(0);
+ s = os;
+ }
+ return(1);
+}
+
+int
+cunlink(f)
+char *f;
+{
+ if (f==0 || Xflag)
+ return(0);
+ return(unlink(f));
+}
+
+char *
+gettmp()
+{
+ char *sfn = strdup("/tmp/ctm.XXXXXX");
+ int fd = -1;
+
+ if ((fd = mkstemp(sfn)) == -1) {
+ fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
+ exit(8);
+ }
+ close(fd);
+
+ return sfn;
+}
diff --git a/usr.bin/pcc/cc/ccom/Makefile.in b/usr.bin/pcc/cc/ccom/Makefile.in
new file mode 100644
index 00000000000..0cc29c5a565
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/Makefile.in
@@ -0,0 +1,107 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:32 otto Exp $
+#
+# Makefile.in for ccom
+#
+XFL=-DPCC_DEBUG -DGCC_COMPAT \
+ -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
+
+CC = @CC@
+CFLAGS = @CFLAGS@ $(XFL) -I. -I${MIPDIR} -I$(MDIR) -Dmach_${TARGMACH} \
+ -I../../os/${TARGOS}
+CPPFLAGS = @CPPFLAGS@
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+YACC = @YACC@
+TARGOS = @targos@
+TARGMACH = @targmach@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libexecdir = @libexecdir@
+strip = @strip@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+MDIR=../../arch/$(TARGMACH)
+MIPDIR=../../mip
+
+OBJS1=optim.o pftn.o scan.o trees.o cgram.o inline.o symtabs.o \
+ gcc_compat.o init.o local.o code.o stabs.o
+
+OBJS2=match.o reader.o optim2.o regs.o local2.o order.o table.o
+
+OBJS=$(OBJS1) $(OBJS2) common.o main.o external.o
+
+DEST=ccom
+
+all: ${DEST}
+
+${DEST}: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+.c.o:
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+local.o: $(MDIR)/local.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local.c
+
+local2.o: $(MDIR)/local2.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local2.c
+
+code.o: $(MDIR)/code.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/code.c
+
+order.o: $(MDIR)/order.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/order.c
+
+table.o: $(MDIR)/table.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/table.c
+
+match.o: $(MIPDIR)/match.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/match.c
+
+reader.o: $(MIPDIR)/reader.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/reader.c
+
+optim2.o: $(MIPDIR)/optim2.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/optim2.c
+
+regs.o: $(MIPDIR)/regs.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/regs.c
+
+common.o: $(MIPDIR)/common.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/common.c
+
+external.h external.c: ${MIPDIR}/mkext.c $(MDIR)/table.c
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -DMKEXT -o mkext ${MIPDIR}/mkext.c \
+ $(MDIR)/table.c ${MIPDIR}/common.c
+ ./mkext
+
+trees.c: pass2.h
+
+pass2.h: external.h
+
+cgram.c: cgram.y
+ $(YACC) $(YFLAGS) -d $<
+ mv y.tab.c cgram.c
+ mv y.tab.h cgram.h
+
+scan.c: scan.l cgram.c
+ $(LEX) $(LFLAGS) $<
+ mv lex.yy.c scan.c
+
+optim2.o reader.o: external.h
+
+install:
+ test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)"
+ ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir}
+ @if [ ${strip} = yes ]; then \
+ strip ${DESTDIR}${libexecdir}/${DEST} ; \
+ echo strip ${DESTDIR}${libexecdir}/${DEST} ; \
+ fi
+
+clean:
+ /bin/rm -f $(OBJS) ccom scan.c cgram.[ch] mkext external.[ch]
+
+distclean: clean
+ /bin/rm -f Makefile
diff --git a/usr.bin/pcc/cc/ccom/ccom.1 b/usr.bin/pcc/cc/ccom/ccom.1
new file mode 100644
index 00000000000..3205366a5a7
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/ccom.1
@@ -0,0 +1,148 @@
+.\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net>
+.\" 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 AND CONTRIBUTORS DISCLAIM
+.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
+.\" CONTRIBUTORS 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.
+.Dd September 14, 2007
+.Dt ccom 1
+.Os
+.Sh NAME
+.Nm ccom
+.Nd C compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl X Ar flags
+.Op infile
+.Op outfile
+.Pp
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a C compiler.
+The frontend is usually
+.Xr pcc 1 .
+It is \fBnot\fR intended to be run directly.
+.Pp
+.Nm
+reads the C source from
+.Ar infile
+or standard input and writes the assembler source
+to
+.Ar outfile
+or to standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl g
+Enable debugging.
+.\" built into binary, explain stabs?
+.It Fl s
+Print statistics to standard error when complete.
+This includes:
+name table entries, name string size, permanent allocated memory,
+temporary allocated memory, lost memory, argument list unions,
+dimension/function unions, struct/union/enum blocks, inline node count,
+inline control blocks, and permanent symtab entries.
+.\" TODO: explain units for above?
+.It Fl W Ar flags
+Report warnings.
+(Do some basic checks.)
+NOTE! These are subject to change RSN!
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy implicit
+Implies
+.Sy implicit-int
+and
+.Sy implicit-function-declaration .
+.It Sy implicit-int
+TODO
+.It Sy implicit-function-declaration
+Report if no prototype for function.
+.It Sy missing-prototypes
+TODO
+.It Sy strict-prototypes
+TODO
+.El
+.\"
+.It Fl x Ar optimizations
+.Ar optimizations
+is one or more of the following:
+.Bl -tag -width deljumps
+.It Sy deljumps
+Delete redundant jumps and dead code.
+.It Sy ssa
+Convert statements into SSA form for optimization. Not yet finished.
+.It Sy tailcall
+Currently not implemented.
+.It Sy temps
+Setting this flag allow variables to be put into registers, for further
+optimization by the register allocator.
+.El
+.\"
+.It Fl X Ar C specific debugging flags
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy b
+Building of parse trees
+.It Sy d
+Declarations, more d gives more output
+.It Sy t
+Type conversions
+.It Sy i
+Initializations
+.It Sy e
+Pass1 trees at exit
+.It Sy x
+Target-specific flag, used in machine-dependent code
+.El
+.\"
+.It Fl Z Ar Code generator (pass2) specific debugging flags
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy e
+Trees when entering pass2
+.It Sy o
+Instruction generator
+.It Sy f
+Instruction matcher, may provide much output
+.It Sy r
+Register allocator
+.It Sy t
+Type matching in instruction generator
+.It Sy s
+Shape matching in instruction generator
+.It Sy u
+Sethi-Ullman computations
+.It Sy x
+Target-specific flag, used in machine-dependent code
+.El
+.Sh SEE ALSO
+.Xr as 1 ,
+.Xr cpp 1 ,
+.Xr pcc 1
+.Sh HISTORY
+The
+.Nm
+compiler is based on the original Portable C Compiler by S. C.
+Johnson, written in the late 70's.
+Even though much of the compiler has been rewritten, some of the
+basics still remain.
+About 50% of the frontend code and 80% of the backend code has been
+rewritten.
+Most is written by Anders Magnusson, with the exception of
+the data-flow analysis part and the SSA conversion code which is
+written by Peter A Jonsson, and the Mips port that were written as
+part of a project by undergraduate students at Lulea University of
+Technology.
diff --git a/usr.bin/pcc/cc/ccom/cgram.y b/usr.bin/pcc/cc/ccom/cgram.y
new file mode 100644
index 00000000000..3393bf6e13b
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/cgram.y
@@ -0,0 +1,1399 @@
+/* $Id: cgram.y,v 1.1 2007/09/15 18:12:33 otto Exp $ */
+
+/*
+ * 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * 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.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+/*
+ * Comments for this grammar file. Ragge 021123
+ *
+ * ANSI support required rewrite of the function header and declaration
+ * rules almost totally.
+ *
+ * The lex/yacc shared keywords are now split from the keywords used
+ * in the rest of the compiler, to simplify use of other frontends.
+ */
+
+/*
+ * At last count, there were 3 shift/reduce and no reduce/reduce conflicts
+ * Two was funct_idn and the third was "dangling else".
+ */
+
+/*
+ * Token used in C lex/yacc communications.
+ */
+%token C_WSTRING /* a wide string constant */
+%token C_STRING /* a string constant */
+%token C_ICON /* an integer constant */
+%token C_FCON /* a floating point constant */
+%token C_NAME /* an identifier */
+%token C_TYPENAME /* a typedef'd name */
+%token C_ANDAND /* && */
+%token C_OROR /* || */
+%token C_GOTO /* unconditional goto */
+%token C_RETURN /* return from function */
+%token C_TYPE /* a type */
+%token C_CLASS /* a storage class */
+%token C_ASOP /* assignment ops */
+%token C_RELOP /* <=, <, >=, > */
+%token C_EQUOP /* ==, != */
+%token C_DIVOP /* /, % */
+%token C_SHIFTOP /* <<, >> */
+%token C_INCOP /* ++, -- */
+%token C_UNOP /* !, ~ */
+%token C_STROP /* ., -> */
+%token C_STRUCT
+%token C_IF
+%token C_ELSE
+%token C_SWITCH
+%token C_BREAK
+%token C_CONTINUE
+%token C_WHILE
+%token C_DO
+%token C_FOR
+%token C_DEFAULT
+%token C_CASE
+%token C_SIZEOF
+%token C_ENUM
+%token C_ELLIPSIS
+%token C_QUALIFIER
+%token C_FUNSPEC
+%token C_ASM
+
+/*
+ * Precedence
+ */
+%left ','
+%right '=' C_ASOP
+%right '?' ':'
+%left C_OROR
+%left C_ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left C_EQUOP
+%left C_RELOP
+%left C_SHIFTOP
+%left '+' '-'
+%left '*' C_DIVOP
+%right C_UNOP
+%right C_INCOP C_SIZEOF
+%left '[' '(' C_STROP
+%{
+# include "pass1.h"
+# include <stdarg.h>
+# include <string.h>
+
+static int fun_inline; /* Reading an inline function */
+int oldstyle; /* Current function being defined */
+int noretype;
+static struct symtab *xnf;
+#ifdef GCC_COMPAT
+char *renname; /* for renaming of variables */
+#endif
+
+
+static NODE *bdty(int op, ...);
+static void fend(void);
+static void fundef(NODE *tp, NODE *p);
+static void olddecl(NODE *p);
+static struct symtab *init_declarator(NODE *tn, NODE *p, int assign);
+static void resetbc(int mask);
+static void swend(void);
+static void addcase(NODE *p);
+static void adddef(void);
+static void savebc(void);
+static void swstart(int);
+static NODE * structref(NODE *p, int f, char *name);
+static char *mkpstr(char *str);
+static struct symtab *clbrace(NODE *);
+
+/*
+ * State for saving current switch state (when nested switches).
+ */
+struct savbc {
+ struct savbc *next;
+ int brklab;
+ int contlab;
+ int flostat;
+ int swx;
+} *savbc, *savctx;
+
+%}
+
+%union {
+ int intval;
+ NODE *nodep;
+ struct symtab *symp;
+ struct rstack *rp;
+ char *strp;
+}
+
+ /* define types */
+%start ext_def_list
+
+%type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
+ type_qualifier_list
+%type <nodep> e .e term enum_dcl struct_dcl cast_type funct_idn declarator
+ direct_declarator elist type_specifier merge_attribs
+ parameter_declaration abstract_declarator initializer
+ parameter_type_list parameter_list addrlbl
+ declaration_specifiers pointer direct_abstract_declarator
+ specifier_qualifier_list merge_specifiers nocon_e
+ identifier_list arg_param_list arg_declaration arg_dcl_list
+ designator_list designator
+%type <strp> string wstring C_STRING C_WSTRING
+%type <rp> enum_head str_head
+%type <symp> xnfdeclarator clbrace
+
+%type <intval> C_CLASS C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
+ C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
+%type <nodep> C_TYPE C_QUALIFIER C_ICON C_FCON
+%type <strp> C_NAME C_TYPENAME
+
+%%
+
+ext_def_list: ext_def_list external_def
+ | { ftnend(); }
+ ;
+
+external_def: function_definition { blevel = 0; }
+ | declaration { blevel = 0; symclear(0); }
+ | asmstatement ';'
+ | ';'
+ | error { blevel = 0; }
+ ;
+
+function_definition:
+ /* Ansi (or K&R header without parameter types) */
+ declaration_specifiers declarator {
+ fundef($1, $2);
+ } compoundstmt { fend(); }
+ /* Same as above but without declaring function type */
+ | declarator {
+ noretype = 1;
+ fundef(mkty(INT, 0, MKSUE(INT)), $1);
+ } compoundstmt { fend(); noretype = 0; }
+ /* K&R function without type declaration */
+ | declarator {
+ noretype = 1;
+ if (oldstyle == 0)
+ uerror("bad declaration in ansi function");
+ fundef(mkty(INT, 0, MKSUE(INT)), $1);
+ } arg_dcl_list compoundstmt { fend(); noretype = 0; }
+ /* K&R function with type declaration */
+ | declaration_specifiers declarator {
+ if (oldstyle == 0)
+ uerror("bad declaration in ansi function");
+ fundef($1, $2);
+ } arg_dcl_list compoundstmt { fend(); }
+ ;
+
+/*
+ * Returns a node pointer or NULL, if no types at all given.
+ * Type trees are checked for correctness and merged into one
+ * type node in typenode().
+ */
+declaration_specifiers:
+ merge_attribs { $$ = typenode($1); }
+ ;
+
+merge_attribs: C_CLASS { $$ = block(CLASS, NIL, NIL, $1, 0, 0); }
+ | C_CLASS merge_attribs { $$ = block(CLASS, $2, NIL, $1,0,0);}
+ | type_specifier { $$ = $1; }
+ | type_specifier merge_attribs { $1->n_left = $2; $$ = $1; }
+ | C_QUALIFIER { $$ = $1; }
+ | C_QUALIFIER merge_attribs { $1->n_left = $2; $$ = $1; }
+ | function_specifiers { $$ = NIL; }
+ | function_specifiers merge_attribs { $$ = $2; }
+ ;
+
+function_specifiers:
+ C_FUNSPEC {
+ if (fun_inline)
+ uerror("too many inline");
+ fun_inline = 1;
+ }
+ ;
+
+type_specifier: C_TYPE { $$ = $1; }
+ | C_TYPENAME {
+ struct symtab *sp = lookup($1, 0);
+ $$ = mkty(sp->stype, sp->sdf, sp->ssue);
+ $$->n_sp = sp;
+ }
+ | struct_dcl { $$ = $1; }
+ | enum_dcl { $$ = $1; }
+ ;
+
+/*
+ * Adds a pointer list to front of the declarators.
+ * Note the UMUL right node pointer usage.
+ */
+declarator: pointer direct_declarator {
+ $$ = $1; $1->n_right->n_left = $2;
+ }
+ | direct_declarator { $$ = $1; }
+ ;
+
+/*
+ * Return an UMUL node type linked list of indirections.
+ */
+pointer: '*' { $$ = bdty(UMUL, NIL); $$->n_right = $$; }
+ | '*' type_qualifier_list {
+ $$ = bdty(UMUL, NIL);
+ $$->n_qual = $2;
+ $$->n_right = $$;
+ }
+ | '*' pointer {
+ $$ = bdty(UMUL, $2);
+ $$->n_right = $2->n_right;
+ }
+ | '*' type_qualifier_list pointer {
+ $$ = bdty(UMUL, $3);
+ $$->n_qual = $2;
+ $$->n_right = $3->n_right;
+ }
+ ;
+
+type_qualifier_list:
+ C_QUALIFIER { $$ = $1->n_type; nfree($1); }
+ | type_qualifier_list C_QUALIFIER {
+ $$ = $1 | $2->n_type; nfree($2);
+ }
+ ;
+
+/*
+ * Sets up a function declarator. The call node will have its parameters
+ * connected to its right node pointer.
+ */
+direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
+ | '(' declarator ')' { $$ = $2; }
+ | direct_declarator '[' nocon_e ']' {
+ $$ = block(LB, $1, $3, INT, 0, MKSUE(INT));
+ }
+ | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
+ | direct_declarator '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ }
+ | direct_declarator '(' notype identifier_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ if (blevel != 0)
+ uerror("function declaration in bad context");
+ oldstyle = 1;
+ }
+ | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); }
+ ;
+
+notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ }
+ ;
+
+identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; }
+ | identifier_list ',' C_NAME {
+ $$ = bdty(NAME, $3);
+ $$->n_type = FARG;
+ $$ = block(CM, $1, $$, 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns as parameter_list, but can add an additional ELLIPSIS node.
+ * Calls revert() to get the parameter list in the forward order.
+ */
+parameter_type_list:
+ parameter_list { $$ = $1; }
+ | parameter_list ',' C_ELLIPSIS {
+ $$ = block(CM, $1, block(ELLIPSIS, NIL, NIL, 0, 0, 0),
+ 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns a linked lists of nodes of op CM with parameters on
+ * its right and additional CM nodes of its left pointer.
+ * No CM nodes if only one parameter.
+ */
+parameter_list: parameter_declaration { $$ = $1; }
+ | parameter_list ',' parameter_declaration {
+ $$ = block(CM, $1, $3, 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns a node pointer to the declaration.
+ */
+parameter_declaration:
+ declaration_specifiers declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ | declaration_specifiers abstract_declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ | declaration_specifiers {
+ $$ = tymerge($1, bdty(NAME, NULL));
+ nfree($1);
+ }
+ ;
+
+abstract_declarator:
+ pointer { $$ = $1; $1->n_right->n_left = bdty(NAME, NULL); }
+ | direct_abstract_declarator { $$ = $1; }
+ | pointer direct_abstract_declarator {
+ $$ = $1; $1->n_right->n_left = $2;
+ }
+ ;
+
+direct_abstract_declarator:
+ '(' abstract_declarator ')' { $$ = $2; }
+ | '[' ']' { $$ = bdty(LB, bdty(NAME, NULL), 0); }
+ | '[' con_e ']' { $$ = bdty(LB, bdty(NAME, NULL), $2); }
+ | direct_abstract_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
+ | direct_abstract_declarator '[' con_e ']' {
+ $$ = bdty(LB, $1, $3);
+ }
+ | '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
+ | '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, bdty(NAME, NULL), $3);
+ }
+ | direct_abstract_declarator '(' ')' {
+ $$ = bdty(UCALL, $1);
+ }
+ | direct_abstract_declarator '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ }
+ ;
+
+/*
+ * K&R arg declaration, between ) and {
+ */
+arg_dcl_list: arg_declaration
+ | arg_dcl_list arg_declaration
+ ;
+
+
+arg_declaration: declaration_specifiers arg_param_list ';' {
+ nfree($1);
+ }
+ ;
+
+arg_param_list: declarator { olddecl(tymerge($<nodep>0, $1)); }
+ | arg_param_list ',' declarator {
+ olddecl(tymerge($<nodep>0, $3));
+ }
+ ;
+
+/*
+ * Declarations in beginning of blocks.
+ */
+declaration_list: declaration
+ | declaration_list declaration
+ ;
+
+/*
+ * Here starts the old YACC code.
+ */
+
+stmt_list: stmt_list statement
+ | { bccode(); }
+ ;
+
+/*
+ * Variables are declared in init_declarator.
+ */
+declaration: declaration_specifiers ';' { nfree($1); goto inl; }
+ | declaration_specifiers init_declarator_list ';' {
+ nfree($1);
+ inl:
+ fun_inline = 0;
+ }
+ ;
+
+/*
+ * Normal declaration of variables. curtype contains the current type node.
+ * Returns nothing, variables are declared in init_declarator.
+ */
+init_declarator_list:
+ init_declarator
+ | init_declarator_list ',' { $<nodep>$ = $<nodep>0; } init_declarator
+ ;
+
+enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = dclstruct($1); }
+ | C_ENUM C_NAME { $$ = rstruct($2,0); }
+ | C_ENUM C_TYPENAME { $$ = rstruct($2,0); }
+ ;
+
+enum_head: C_ENUM { $$ = bstruct(NULL,0); }
+ | C_ENUM C_NAME { $$ = bstruct($2,0); }
+ | C_ENUM C_TYPENAME { $$ = bstruct($2,0); }
+ ;
+
+moe_list: moe
+ | moe_list ',' moe
+ ;
+
+moe: C_NAME { moedef( $1 ); }
+ | C_NAME '=' con_e { strucoff = $3; moedef( $1 ); }
+ ;
+
+struct_dcl: str_head '{' struct_dcl_list '}' { $$ = dclstruct($1); }
+ | C_STRUCT C_NAME { $$ = rstruct($2,$1); }
+ | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); }
+ | str_head '{' '}' {
+#ifndef GCC_COMPAT
+ werror("gcc extension");
+#endif
+ $$ = dclstruct($1);
+ }
+ ;
+
+str_head: C_STRUCT { $$ = bstruct(NULL, $1); }
+ | C_STRUCT C_NAME { $$ = bstruct($2,$1); }
+ | C_STRUCT C_TYPENAME { $$ = bstruct($2,$1); }
+ ;
+
+struct_dcl_list: struct_declaration
+ | struct_dcl_list struct_declaration
+ ;
+
+struct_declaration:
+ specifier_qualifier_list struct_declarator_list ';' {
+ nfree($1);
+ }
+ ;
+
+specifier_qualifier_list:
+ merge_specifiers { $$ = typenode($1); }
+ ;
+
+merge_specifiers: type_specifier merge_specifiers { $1->n_left = $2;$$ = $1; }
+ | type_specifier { $$ = $1; }
+ | C_QUALIFIER merge_specifiers { $1->n_left = $2; $$ = $1; }
+ | C_QUALIFIER { $$ = $1; }
+ ;
+
+struct_declarator_list:
+ struct_declarator { }
+ | struct_declarator_list ',' { $<nodep>$=$<nodep>0; }
+ struct_declarator { }
+ ;
+
+struct_declarator: declarator {
+ tymerge($<nodep>0, $1);
+ $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */
+ defid($1, $<nodep>0->n_lval);
+ nfree($1);
+ }
+ | ':' con_e {
+ if (!(instruct&INSTRUCT))
+ uerror( "field outside of structure" );
+ falloc(NULL, $2, -1, $<nodep>0);
+ }
+ | declarator ':' con_e {
+ if (!(instruct&INSTRUCT))
+ uerror( "field outside of structure" );
+ if( $3<0 || $3 >= FIELD ){
+ uerror( "illegal field size" );
+ $3 = 1;
+ }
+ if ($1->n_op == NAME) {
+ tymerge($<nodep>0, $1);
+ $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME);
+ defid($1, FIELD|$3);
+ nfree($1);
+ } else
+ uerror("illegal declarator");
+ }
+ ;
+
+ /* always preceeded by attributes */
+xnfdeclarator: declarator { $$ = xnf = init_declarator($<nodep>0, $1, 1); }
+ ;
+
+/*
+ * Handles declarations and assignments.
+ * Returns nothing.
+ */
+init_declarator: declarator { init_declarator($<nodep>0, $1, 0); }
+ | declarator C_ASM '(' string ')' {
+#ifdef GCC_COMPAT
+ renname = $4;
+ init_declarator($<nodep>0, $1, 0);
+#else
+ werror("gcc extension");
+ init_declarator($<nodep>0, $1, 0);
+#endif
+ }
+ | xnfdeclarator '=' e { simpleinit($1, $3); xnf = NULL; }
+ | xnfdeclarator '=' begbr init_list optcomma '}' {
+ endinit();
+ xnf = NULL;
+ }
+ | xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
+ ;
+
+begbr: '{' { beginit($<symp>-1); }
+ ;
+
+initializer: e %prec ',' { $$ = $1; }
+ | addrlbl { $$ = $1; }
+ | ibrace init_list optcomma '}' { $$ = NULL; }
+ ;
+
+init_list: designation initializer { asginit($2); }
+ | init_list ',' designation initializer { asginit($4); }
+ ;
+
+designation: designator_list '=' { desinit($1); }
+ | { /* empty */ }
+ ;
+
+designator_list: designator { $$ = $1; }
+ | designator_list designator { $$ = $2; $$->n_left = $1; }
+ ;
+
+designator: '[' con_e ']' { $$ = bdty(LB, NULL, $2); }
+ | C_STROP C_NAME { $$ = bdty(NAME, $2); }
+ ;
+
+optcomma : /* VOID */
+ | ','
+ ;
+
+ibrace: '{' { ilbrace(); }
+ ;
+
+/* STATEMENTS */
+
+compoundstmt: begin declaration_list stmt_list '}' {
+#ifdef STABS
+ if (gflag && blevel > 2)
+ stabs_rbrac(blevel);
+#endif
+ --blevel;
+ if( blevel == 1 )
+ blevel = 0;
+ symclear(blevel); /* Clean ut the symbol table */
+ if (autooff > maxautooff)
+ maxautooff = autooff;
+ autooff = savctx->contlab;
+ savctx = savctx->next;
+ }
+ | begin stmt_list '}' {
+#ifdef STABS
+ if (gflag && blevel > 2)
+ stabs_rbrac(blevel);
+#endif
+ --blevel;
+ if( blevel == 1 )
+ blevel = 0;
+ symclear(blevel); /* Clean ut the symbol table */
+ if (autooff > maxautooff)
+ maxautooff = autooff;
+ autooff = savctx->contlab;
+ savctx = savctx->next;
+ }
+ ;
+
+begin: '{' {
+ struct savbc *bc = tmpalloc(sizeof(struct savbc));
+ if (blevel == 1) {
+#ifdef STABS
+ if (gflag)
+ stabs_line(lineno);
+#endif
+ dclargs();
+ }
+#ifdef STABS
+ if (gflag && blevel > 1)
+ stabs_lbrac(blevel+1);
+#endif
+ ++blevel;
+ oldstyle = 0;
+ bc->contlab = autooff;
+ bc->next = savctx;
+ savctx = bc;
+ }
+ ;
+
+statement: e ';' { ecomp( $1 ); }
+ | compoundstmt
+ | ifprefix statement { plabel($1); reached = 1; }
+ | ifelprefix statement {
+ if ($1 != NOLAB) {
+ plabel( $1);
+ reached = 1;
+ }
+ }
+ | whprefix statement {
+ branch(contlab);
+ plabel( brklab );
+ if( (flostat&FBRK) || !(flostat&FLOOP))
+ reached = 1;
+ else
+ reached = 0;
+ resetbc(0);
+ }
+ | doprefix statement C_WHILE '(' e ')' ';' {
+ plabel(contlab);
+ if (flostat & FCONT)
+ reached = 1;
+ if (reached)
+ cbranch($5, bcon($1));
+ else
+ tfree($5);
+ plabel( brklab);
+ reached = 1;
+ resetbc(0);
+ }
+ | forprefix .e ')' statement
+ { plabel( contlab );
+ if( flostat&FCONT ) reached = 1;
+ if( $2 ) ecomp( $2 );
+ branch($1);
+ plabel( brklab );
+ if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
+ else reached = 0;
+ resetbc(0);
+ }
+ | switchpart statement
+ { if( reached ) branch( brklab );
+ plabel( $1 );
+ swend();
+ plabel( brklab);
+ if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
+ resetbc(FCONT);
+ }
+ | C_BREAK ';' {
+ if (brklab == NOLAB)
+ uerror("illegal break");
+ else if (reached)
+ branch(brklab);
+ flostat |= FBRK;
+ reached = 0;
+ }
+ | C_CONTINUE ';' {
+ if (contlab == NOLAB)
+ uerror("illegal continue");
+ else
+ branch(contlab);
+ flostat |= FCONT;
+ goto rch;
+ }
+ | C_RETURN ';' {
+ branch(retlab);
+ if (cftnsp->stype != VOID && noretype &&
+ cftnsp->stype != VOID+FTN)
+ uerror("return value required");
+ rch:
+ if (!reached)
+ werror( "statement is not reached");
+ reached = 0;
+ }
+ | C_RETURN e ';' {
+ register NODE *temp;
+
+ spname = cftnsp;
+ temp = buildtree( NAME, NIL, NIL );
+ temp->n_type = DECREF(temp->n_type);
+ temp = buildtree(RETURN, temp, $2);
+
+ if (temp->n_type == VOID)
+ ecomp(temp->n_right);
+ else
+ ecomp(buildtree(FORCE, temp->n_right, NIL));
+ nfree(temp->n_left);
+ nfree(temp);
+ branch(retlab);
+ reached = 0;
+ }
+ | C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
+ | C_GOTO '*' e ';' {
+ ecomp(block(GOTO, $3, NIL, INT, 0, 0));
+ }
+ | asmstatement ';'
+ | ';'
+ | error ';'
+ | error '}'
+ | label statement
+ ;
+
+asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); }
+ ;
+
+label: C_NAME ':' { deflabel($1); reached = 1; }
+ | C_CASE e ':' { addcase($2); reached = 1; }
+ | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
+ ;
+
+doprefix: C_DO {
+ savebc();
+ if (!reached)
+ werror("loop not entered at top");
+ brklab = getlab();
+ contlab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ }
+ ;
+ifprefix: C_IF '(' e ')' {
+ cbranch(buildtree(NOT, $3, NIL), bcon($$ = getlab()));
+ reached = 1;
+ }
+ ;
+ifelprefix: ifprefix statement C_ELSE {
+ if (reached)
+ branch($$ = getlab());
+ else
+ $$ = NOLAB;
+ plabel( $1);
+ reached = 1;
+ }
+ ;
+
+whprefix: C_WHILE '(' e ')' {
+ savebc();
+ if (!reached)
+ werror("loop not entered at top");
+ if ($3->n_op == ICON && $3->n_lval != 0)
+ flostat = FLOOP;
+ plabel( contlab = getlab());
+ reached = 1;
+ brklab = getlab();
+ if (flostat == FLOOP)
+ tfree($3);
+ else
+ cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
+ }
+ ;
+forprefix: C_FOR '(' .e ';' .e ';' {
+ if ($3)
+ ecomp($3);
+ else if (!reached)
+ werror("loop not entered at top");
+ savebc();
+ contlab = getlab();
+ brklab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ if ($5)
+ cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
+ else
+ flostat |= FLOOP;
+ }
+ ;
+switchpart: C_SWITCH '(' e ')' {
+ NODE *p;
+ int num;
+
+ savebc();
+ brklab = getlab();
+ if ($3->n_type != INT) {
+ /* must cast to integer */
+ p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(CAST, p, $3);
+ $3 = p->n_right;
+ nfree(p->n_left);
+ nfree(p);
+ }
+// ecomp( buildtree( FORCE, $3, NIL ) );
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ num = p->n_lval;
+ ecomp(buildtree(ASSIGN, p, $3));
+ branch( $$ = getlab());
+ swstart(num);
+ reached = 0;
+ }
+ ;
+/* EXPRESSIONS */
+con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
+ $$ = icons( $2 );
+ instruct=$<intval>1;
+ }
+ ;
+
+nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
+ instruct=$<intval>1;
+ $$ = $2;
+ }
+ ;
+
+.e: e
+ | { $$=0; }
+ ;
+
+elist: e %prec ','
+ | elist ',' e { $$ = buildtree(CM, $1, $3); }
+ ;
+
+/*
+ * Precedence order of operators.
+ */
+e: e ',' e { $$ = buildtree(COMOP, $1, $3); }
+ | e '=' e { $$ = buildtree(ASSIGN, $1, $3); }
+ | e C_ASOP e { $$ = buildtree($2, $1, $3); }
+ | e '?' e ':' e {
+ $$=buildtree(QUEST, $1, buildtree(COLON, $3, $5));
+ }
+ | e C_OROR e { $$ = buildtree($2, $1, $3); }
+ | e C_ANDAND e { $$ = buildtree($2, $1, $3); }
+ | e '|' e { $$ = buildtree(OR, $1, $3); }
+ | e '^' e { $$ = buildtree(ER, $1, $3); }
+ | e '&' e { $$ = buildtree(AND, $1, $3); }
+ | e C_EQUOP e { $$ = buildtree($2, $1, $3); }
+ | e C_RELOP e { $$ = buildtree($2, $1, $3); }
+ | e C_SHIFTOP e { $$ = buildtree($2, $1, $3); }
+ | e '+' e { $$ = buildtree(PLUS, $1, $3); }
+ | e '-' e { $$ = buildtree(MINUS, $1, $3); }
+ | e C_DIVOP e { $$ = buildtree($2, $1, $3); }
+ | e '*' e { $$ = buildtree(MUL, $1, $3); }
+ | e '=' addrlbl { $$ = buildtree(ASSIGN, $1, $3); }
+ | term
+ ;
+
+addrlbl: C_ANDAND C_NAME {
+#ifdef GCC_COMPAT
+ struct symtab *s = lookup($2, SLBLNAME);
+ if (s->soffset == 0)
+ s->soffset = -getlab();
+ spname = s;
+ $$ = buildtree(ADDROF, buildtree(NAME, NIL, NIL), NIL);
+#else
+ uerror("gcc extension");
+#endif
+ }
+ ;
+
+term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); }
+ | '*' term { $$ = buildtree(UMUL, $2, NIL); }
+ | '&' term {
+ if( ISFTN($2->n_type) || ISARY($2->n_type) ){
+#ifdef notdef
+ werror( "& before array or function: ignored" );
+#endif
+ $$ = $2;
+ } else
+ $$ = buildtree(ADDROF, $2, NIL);
+ }
+ | '-' term { $$ = buildtree(UMINUS, $2, NIL ); }
+ | '+' term { $$ = $2; }
+ | C_UNOP term { $$ = buildtree( $1, $2, NIL ); }
+ | C_INCOP term {
+ $$ = buildtree($1 == INCR ? PLUSEQ : MINUSEQ,
+ $2, bcon(1));
+ }
+ | C_SIZEOF term { $$ = doszof($2); }
+ | '(' cast_type ')' term %prec C_INCOP {
+ $$ = buildtree(CAST, $2, $4);
+ nfree($$->n_left);
+ nfree($$);
+ $$ = $$->n_right;
+ }
+ | C_SIZEOF '(' cast_type ')' %prec C_SIZEOF {
+ $$ = doszof($3);
+ }
+ | '(' cast_type ')' clbrace init_list '}' {
+ endinit();
+ spname = $4;
+ $$ = buildtree(NAME, NIL, NIL);
+ }
+ | term '[' e ']' {
+ $$ = buildtree( UMUL,
+ buildtree( PLUS, $1, $3 ), NIL );
+ }
+ | funct_idn ')' { $$ = doacall($1, NIL); }
+ | funct_idn elist ')' { $$ = doacall($1, $2); }
+ | term C_STROP C_NAME { $$ = structref($1, $2, $3); }
+ | term C_STROP C_TYPENAME { $$ = structref($1, $2, $3); }
+ | C_NAME {
+ spname = lookup($1, 0);
+ /* recognize identifiers in initializations */
+ if (blevel==0 && spname->stype == UNDEF) {
+ register NODE *q;
+ werror("undeclared initializer name %s",
+ spname->sname);
+ q = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ q->n_sp = spname;
+ defid(q, EXTERN);
+ nfree(q);
+ }
+ if (spname->sflags & SINLINE)
+ inline_ref($1);
+ $$ = buildtree(NAME, NIL, NIL);
+ spname->suse = -lineno;
+ if (spname->sflags & SDYNARRAY)
+ $$ = buildtree(UMUL, $$, NIL);
+ }
+ | C_ICON { $$ = $1; }
+ | C_FCON { $$ = $1; }
+ | string { $$ = strend($1); /* get string contents */ }
+ | wstring { $$ = wstrend($1); }
+ | '(' e ')' { $$=$2; }
+ ;
+
+clbrace: '{' { $$ = clbrace($<nodep>-1); }
+ ;
+
+string: C_STRING {
+ int len = strlen($1) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ }
+ | string C_STRING {
+ int len = strlen($1) + strlen($2) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ strlcat($$, $2, len);
+ }
+ ;
+
+wstring: C_WSTRING {
+ int len = strlen($1) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ }
+ | string C_WSTRING {
+ int len = strlen($1) + strlen($2) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ strlcat($$, $2, len);
+ }
+ ;
+
+cast_type: specifier_qualifier_list {
+ $$ = tymerge($1, bdty(NAME, NULL));
+ nfree($1);
+ }
+ | specifier_qualifier_list abstract_declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ ;
+
+funct_idn: C_NAME '(' {
+ struct symtab *s = lookup($1, 0);
+ if (s->stype == UNDEF) {
+ register NODE *q;
+ q = block(NAME, NIL, NIL, FTN|INT, 0, MKSUE(INT));
+ q->n_sp = s;
+ defid(q, EXTERN);
+ nfree(q);
+ }
+ if (s->sflags & SINLINE)
+ inline_ref($1);
+ spname = s;
+ $$ = buildtree(NAME, NIL, NIL);
+ s->suse = -lineno;
+ }
+ | term '('
+ ;
+%%
+
+NODE *
+mkty(TWORD t, union dimfun *d, struct suedef *sue)
+{
+ return block(TYPE, NIL, NIL, t, d, sue);
+}
+
+static NODE *
+bdty(int op, ...)
+{
+ va_list ap;
+ register NODE *q;
+
+ va_start(ap, op);
+ q = block(op, NIL, NIL, INT, 0, MKSUE(INT));
+
+ switch (op) {
+ case UMUL:
+ case UCALL:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_rval = 0;
+ break;
+
+ case CALL:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_right = va_arg(ap, NODE *);
+ break;
+
+ case LB:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_right = bcon(va_arg(ap, int));
+ break;
+
+ case NAME:
+ q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
+ break;
+
+ default:
+ cerror("bad bdty");
+ }
+ va_end(ap);
+
+ return q;
+}
+
+static void
+savebc(void)
+{
+ struct savbc *bc = tmpalloc(sizeof(struct savbc));
+
+ bc->brklab = brklab;
+ bc->contlab = contlab;
+ bc->flostat = flostat;
+ bc->next = savbc;
+ savbc = bc;
+ flostat = 0;
+}
+
+static void
+resetbc(int mask)
+{
+ flostat = savbc->flostat | (flostat&mask);
+ contlab = savbc->contlab;
+ brklab = savbc->brklab;
+ savbc = savbc->next;
+}
+
+struct swdef {
+ struct swdef *next; /* Next in list */
+ int deflbl; /* Label for "default" */
+ struct swents *ents; /* Linked sorted list of case entries */
+ int nents; /* # of entries in list */
+ int num; /* Node value will end up in */
+} *swpole;
+
+/*
+ * add case to switch
+ */
+static void
+addcase(NODE *p)
+{
+ struct swents *w, *sw = tmpalloc(sizeof(struct swents));
+
+ p = optim(p); /* change enum to ints */
+ if (p->n_op != ICON || p->n_sp != NULL) {
+ uerror( "non-constant case expression");
+ return;
+ }
+ if (swpole == NULL) {
+ uerror("case not in switch");
+ return;
+ }
+
+ sw->sval = p->n_lval;
+ plabel( sw->slab = getlab());
+ w = swpole->ents;
+ if (swpole->ents == NULL) {
+ sw->next = NULL;
+ swpole->ents = sw;
+ } else if (swpole->ents->next == NULL) {
+ if (swpole->ents->sval == sw->sval) {
+ uerror("duplicate case in switch");
+ } else if (swpole->ents->sval < sw->sval) {
+ sw->next = NULL;
+ swpole->ents->next = sw;
+ } else {
+ sw->next = swpole->ents;
+ swpole->ents = sw;
+ }
+ } else {
+ while (w->next->next != NULL && w->next->sval < sw->sval) {
+ w = w->next;
+ }
+ if (w->next->sval == sw->sval) {
+ uerror("duplicate case in switch");
+ } else if (w->next->sval > sw->sval) {
+ sw->next = w->next;
+ w->next = sw;
+ } else {
+ sw->next = NULL;
+ w->next->next = sw;
+ }
+ }
+ swpole->nents++;
+ tfree(p);
+}
+
+/*
+ * add default case to switch
+ */
+static void
+adddef(void)
+{
+ if (swpole == NULL)
+ uerror("default not inside switch");
+ else if (swpole->deflbl != 0)
+ uerror("duplicate default in switch");
+ else
+ plabel( swpole->deflbl = getlab());
+}
+
+static void
+swstart(int num)
+{
+ struct swdef *sw = tmpalloc(sizeof(struct swdef));
+
+ sw->deflbl = sw->nents = 0;
+ sw->ents = NULL;
+ sw->next = swpole;
+ sw->num = num;
+ swpole = sw;
+}
+
+/*
+ * end a switch block
+ */
+static void
+swend(void)
+{
+ struct swents *sw, **swp;
+ int i;
+
+ sw = tmpalloc(sizeof(struct swents));
+ swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1));
+
+ sw->slab = swpole->deflbl;
+ swp[0] = sw;
+
+ for (i = 1; i <= swpole->nents; i++) {
+ swp[i] = swpole->ents;
+ swpole->ents = swpole->ents->next;
+ }
+ genswitch(swpole->num, swp, swpole->nents);
+
+ swpole = swpole->next;
+}
+
+/*
+ * Declare a variable or prototype.
+ */
+static struct symtab *
+init_declarator(NODE *tn, NODE *p, int assign)
+{
+ int class = tn->n_lval;
+ NODE *typ;
+
+ typ = tymerge(tn, p);
+ typ->n_sp = lookup((char *)typ->n_sp, 0); /* XXX */
+
+ if (fun_inline && ISFTN(typ->n_type))
+ typ->n_sp->sflags |= SINLINE;
+
+ if (ISFTN(typ->n_type) == 0) {
+ setloc1(DATA);
+ if (assign) {
+ defid(typ, class);
+ typ->n_sp->sflags |= SASG;
+ lcommdel(typ->n_sp);
+ } else {
+ nidcl(typ, class);
+ }
+ } else {
+ if (assign)
+ uerror("cannot initialise function");
+ defid(typ, uclass(class));
+ }
+ nfree(p);
+ return typ->n_sp;
+}
+
+/*
+ * Declare a function.
+ */
+static void
+fundef(NODE *tp, NODE *p)
+{
+ extern int prolab;
+ struct symtab *s;
+ int class = tp->n_lval, oclass;
+ char *c;
+
+ setloc1(PROG);
+ /* Enter function args before they are clobbered in tymerge() */
+ /* Typecheck against prototype will be done in defid(). */
+ ftnarg(p);
+
+ tymerge(tp, p);
+ s = p->n_sp = lookup((char *)p->n_sp, 0); /* XXX */
+
+ oclass = s->sclass;
+ if (class == STATIC && oclass == EXTERN)
+ werror("%s was first declared extern, then static", s->sname);
+
+ if ((oclass == SNULL || oclass == USTATIC) &&
+ class == STATIC && fun_inline) {
+ /* Unreferenced, store it for (eventual) later use */
+ /* Ignore it if it not declared static */
+ s->sflags |= SINLINE;
+ inline_start(s->sname);
+ }
+ if (class == EXTERN)
+ class = SNULL; /* same result */
+
+ cftnsp = s;
+ defid(p, class);
+ prolab = getlab();
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+ send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
+ cftnsp->sclass == EXTDEF, prolab);
+ blevel = 1;
+#ifdef STABS
+ if (gflag)
+ stabs_func(s);
+#endif
+ nfree(tp);
+ nfree(p);
+
+}
+
+static void
+fend(void)
+{
+ if (blevel)
+ cerror("function level error");
+ ftnend();
+ fun_inline = 0;
+ cftnsp = NULL;
+}
+
+static NODE *
+structref(NODE *p, int f, char *name)
+{
+ NODE *r;
+
+ if (f == DOT)
+ p = buildtree(ADDROF, p, NIL);
+ r = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_name = name;
+ return buildtree(STREF, p, r);
+}
+
+static void
+olddecl(NODE *p)
+{
+ struct symtab *s;
+
+ s = lookup((char *)p->n_sp, 0);
+ if (s->slevel != 1 || s->stype == UNDEF)
+ uerror("parameter '%s' not defined", s->sname);
+ else if (s->stype != FARG)
+ uerror("parameter '%s' redefined", s->sname);
+ s->stype = p->n_type;
+ s->sdf = p->n_df;
+ s->ssue = p->n_sue;
+ nfree(p);
+}
+
+void
+branch(int lbl)
+{
+ int r = reached++;
+ ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0));
+ reached = r;
+}
+
+/*
+ * Create a printable string based on an encoded string.
+ */
+static char *
+mkpstr(char *str)
+{
+ char *s, *os;
+ int v, l = strlen(str)+1;
+
+ os = s = isinlining ? permalloc(l) : tmpalloc(l);
+ for (; *str; ) {
+ if (*str++ == '\\')
+ v = esccon(&str);
+ else
+ v = str[-1];
+ *s++ = v;
+ }
+ *s = 0;
+ return os;
+}
+
+static struct symtab *
+clbrace(NODE *p)
+{
+ struct symtab *sp;
+
+ if (blevel == 0 && xnf != NULL)
+ cerror("no level0 compound literals");
+
+ sp = getsymtab("cl", STEMP);
+ sp->stype = p->n_type;
+ sp->squal = p->n_qual;
+ sp->sdf = p->n_df;
+ sp->ssue = p->n_sue;
+ sp->sclass = blevel ? AUTO : STATIC;
+ if (!ISARY(sp->stype) || sp->sdf->ddim != 0) {
+ sp->soffset = NOOFFSET;
+ oalloc(sp, &autooff);
+ }
+ tfree(p);
+ beginit(sp);
+ return sp;
+}
diff --git a/usr.bin/pcc/cc/ccom/gcc_compat.c b/usr.bin/pcc/cc/ccom/gcc_compat.c
new file mode 100644
index 00000000000..56de6783bf0
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/gcc_compat.c
@@ -0,0 +1,126 @@
+/* $Id: gcc_compat.c,v 1.1 2007/09/15 18:12:33 otto Exp $ */
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Routines to support some of the gcc extensions to C.
+ */
+#ifdef GCC_COMPAT
+
+#include "pass1.h"
+#include "cgram.h"
+
+#include <string.h>
+
+static struct kw {
+ char *name, *ptr;
+ int rv;
+} kw[] = {
+ { "__asm", NULL, C_ASM },
+ { "__signed", NULL, 0 },
+ { "__inline", NULL, C_FUNSPEC },
+ { "__const", NULL, 0 },
+ { "__asm__", NULL, C_ASM },
+ { NULL, NULL, 0 },
+};
+
+void
+gcc_init()
+{
+ struct kw *kwp;
+
+ for (kwp = kw; kwp->name; kwp++)
+ kwp->ptr = addname(kwp->name);
+
+}
+
+/*
+ * See if a string matches a gcc keyword.
+ */
+int
+gcc_keyword(char *str, NODE **n)
+{
+ struct kw *kwp;
+ int i;
+
+ for (i = 0, kwp = kw; kwp->name; kwp++, i++)
+ if (str == kwp->ptr)
+ break;
+ if (kwp->name == NULL)
+ return 0;
+ if (kwp->rv)
+ return kwp->rv;
+ switch (i) {
+ case 1: /* __signed */
+ *n = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
+ return C_TYPE;
+ case 3: /* __const */
+ *n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
+ return C_QUALIFIER;
+ }
+ cerror("gcc_keyword");
+ return 0;
+}
+
+static struct ren {
+ struct ren *next;
+ char *old, *new;
+} *renp;
+/*
+ * Save a name for later renaming of a variable.
+ */
+void
+gcc_rename(struct symtab *sp, char *newname)
+{
+ struct ren *ren = permalloc(sizeof(struct ren));
+
+ sp->sflags |= SRENAME;
+ ren->old = sp->sname;
+ ren->new = newstring(newname, strlen(newname)+1);
+ ren->next = renp;
+ renp = ren;
+}
+
+/*
+ * Get a renamed variable.
+ */
+char *
+gcc_findname(struct symtab *sp)
+{
+ struct ren *w;
+
+ if ((sp->sflags & SRENAME) == 0)
+ return exname(sp->sname);
+
+ for (w = renp; w; w = w->next) {
+ if (w->old == sp->sname)
+ return exname(w->new);
+ }
+ cerror("gcc_findname %s", sp->sname);
+ return NULL;
+}
+#endif
diff --git a/usr.bin/pcc/cc/ccom/init.c b/usr.bin/pcc/cc/ccom/init.c
new file mode 100644
index 00000000000..58084f966f4
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/init.c
@@ -0,0 +1,951 @@
+/* $Id: init.c,v 1.1 2007/09/15 18:12:33 otto Exp $ */
+
+/*
+ * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * 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.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <string.h>
+
+/*
+ * Four machine-dependent routines may be called during initialization:
+ *
+ * instring(char *str) - Print out a string.
+ * zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
+ * infld(CONSZ off, int fsz, CONSZ val)
+ * - sets the bitfield val starting at off and size fsz.
+ * inval(CONSZ off, int fsz, NODE *)
+ * - prints an integer constant which may have
+ * a label associated with it, located at off and
+ * size fsz.
+ *
+ * Initialization may be of different kind:
+ * - Initialization at compile-time, all values are constants and laid
+ * out in memory. Static or extern variables outside functions.
+ * - Initialization at run-time, written to their values as code.
+ *
+ * Currently run-time-initialized variables are only initialized by using
+ * move instructions. An optimization might be to detect that it is
+ * initialized with constants and therefore copied from readonly memory.
+ */
+
+/*
+ * The base element(s) of an initialized variable is kept in a linked
+ * list, allocated while initialized.
+ *
+ * When a scalar is found, entries are popped of the instk until it's
+ * possible to find an entry for a new scalar; then onstk() is called
+ * to get the correct type and size of that scalar.
+ *
+ * If a right brace is found, pop the stack until a matching left brace
+ * were found while filling the elements with zeros. This left brace is
+ * also marking where the current level is for designated initializations.
+ *
+ * Position entries are increased when traversing back down into the stack.
+ */
+
+/*
+ * Good-to-know entries from symtab:
+ * soffset - # of bits from beginning of this structure.
+ */
+
+/*
+ * TO FIX:
+ * - Alignment of structs on like i386 char members.
+ */
+
+int idebug;
+
+/*
+ * Struct used in array initialisation.
+ */
+static struct instk {
+ struct instk *in_prev; /* linked list */
+ struct symtab **in_xp; /* member in structure initializations */
+ struct symtab *in_sym; /* stab index */
+ union dimfun *in_df; /* dimenston of array */
+ TWORD in_t; /* type for this level */
+ int in_n; /* number of arrays seen so far */
+ int in_fl; /* flag which says if this level is controlled by {} */
+} *pstk, pbase;
+
+static struct symtab *csym;
+
+#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
+
+#ifdef PCC_DEBUG
+static void prtstk(struct instk *in);
+#endif
+
+/*
+ * Linked lists for initializations.
+ */
+struct ilist {
+ struct ilist *next;
+ CONSZ off; /* bit offset of this entry */
+ int fsz; /* bit size of this entry */
+ NODE *n; /* node containing this data info */
+};
+
+struct llist {
+ SLIST_ENTRY(llist) next;
+ CONSZ begsz; /* bit offset of this entry */
+ struct ilist *il;
+} *curll;
+static SLIST_HEAD(, llist) lpole;
+static CONSZ basesz;
+static int numents; /* # of array entries allocated */
+
+static struct ilist *
+getil(struct ilist *next, CONSZ b, int sz, NODE *n)
+{
+ struct ilist *il = tmpalloc(sizeof(struct ilist));
+
+ il->off = b;
+ il->fsz = sz;
+ il->n = n;
+ il->next = next;
+ return il;
+}
+
+/*
+ * Allocate a new struct defining a block of initializers appended to the
+ * end of the llist. Return that entry.
+ */
+static struct llist *
+getll(void)
+{
+ struct llist *ll;
+
+ ll = tmpalloc(sizeof(struct llist));
+ ll->begsz = numents * basesz;
+ ll->il = NULL;
+ SLIST_INSERT_LAST(&lpole, ll, next);
+ numents++;
+ return ll;
+}
+
+/*
+ * Return structure containing off bitnumber.
+ * Allocate more entries, if needed.
+ * This is not bright implemented.
+ */
+static struct llist *
+setll(OFFSZ off)
+{
+ struct llist *ll;
+
+ /* Ensure that we have enough entries */
+ while (off >= basesz * numents)
+ (void)getll();
+ SLIST_FOREACH(ll, &lpole, next)
+ if (ll->begsz <= off && ll->begsz + basesz > off)
+ break;
+ return ll; /* ``cannot fail'' */
+}
+
+/*
+ * beginning of initialization; allocate space to store initialized data.
+ * remember storage class for writeout in endinit().
+ * p is the newly declarated type.
+ */
+void
+beginit(struct symtab *sp)
+{
+ struct instk *is = &pbase;
+ struct llist *ll;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("beginit(), sclass %s\n", scnames(sp->sclass));
+#endif
+
+ csym = sp;
+
+ numents = 0; /* no entries in array list */
+ if (ISARY(sp->stype))
+ basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->ssue);
+ else
+ basesz = tsize(DECREF(sp->stype), sp->sdf, sp->ssue);
+ SLIST_INIT(&lpole);
+ curll = ll = getll(); /* at least first entry in list */
+
+ /* first element */
+ is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_n = 0;
+ is->in_t = sp->stype;
+ is->in_sym = sp;
+ is->in_df = sp->sdf;
+ is->in_fl = 0;
+ is->in_prev = NULL;
+ pstk = is;
+}
+
+/*
+ * Push a new entry on the initializer stack.
+ * The new entry will be "decremented" to the new sub-type of the previous
+ * entry when called.
+ * Popping of entries is done elsewhere.
+ */
+static void
+stkpush(void)
+{
+ struct instk *is;
+ struct symtab *sq, *sp;
+ TWORD t;
+
+ if (pstk == NULL) {
+ sp = csym;
+ t = 0;
+ } else {
+ t = pstk->in_t;
+ sp = pstk->in_sym;
+ }
+
+#ifdef PCC_DEBUG
+ if (idebug) {
+ printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
+ tprint(stdout, t, 0);
+ }
+#endif
+
+ /*
+ * Figure out what the next initializer will be, and push it on
+ * the stack. If this is an array, just decrement type, if it
+ * is a struct or union, extract the next element.
+ */
+ is = tmpalloc(sizeof(struct instk));
+ is->in_fl = 0;
+ is->in_n = 0;
+ if (pstk == NULL) {
+ /* stack empty */
+ is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_t = sp->stype;
+ is->in_sym = sp;
+ is->in_df = sp->sdf;
+ } else if (ISSOU(t)) {
+ sq = *pstk->in_xp;
+ is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0;
+ is->in_t = sq->stype;
+ is->in_sym = sq;
+ is->in_df = sq->sdf;
+ } else if (ISARY(t)) {
+ is->in_xp = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->suelem : 0;
+ is->in_t = DECREF(t);
+ is->in_sym = sp;
+ if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) {
+ werror("excess of initializing elements");
+ pstk->in_n--;
+ }
+ if (ISARY(is->in_t))
+ is->in_df = pstk->in_df+1;
+ } else
+ cerror("onstk");
+ is->in_prev = pstk;
+ pstk = is;
+
+#ifdef PCC_DEBUG
+ if (idebug) {
+ printf(" newtype ");
+ tprint(stdout, is->in_t, 0);
+ printf("\n");
+ }
+#endif
+}
+
+/*
+ * pop down to either next level that can handle a new initializer or
+ * to the next braced level.
+ */
+static void
+stkpop(void)
+{
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("stkpop\n");
+#endif
+ for (; pstk; pstk = pstk->in_prev) {
+ if (pstk->in_t == STRTY) {
+ pstk->in_xp++;
+ if (*pstk->in_xp != NULL)
+ break;
+ }
+ if (ISSOU(pstk->in_t) && pstk->in_fl)
+ break; /* need } */
+ if (ISARY(pstk->in_t)) {
+ pstk->in_n++;
+ if (pstk->in_fl)
+ break;
+ if (pstk->in_df->ddim == 0 ||
+ pstk->in_n < pstk->in_df->ddim)
+ break; /* ger more elements */
+ }
+ }
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ prtstk(pstk);
+#endif
+}
+
+/*
+ * Count how many elements an array may consist of.
+ */
+static int
+acalc(struct instk *is, int n)
+{
+ if (is == NULL || !ISARY(is->in_t))
+ return 0;
+ return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
+}
+
+/*
+ * Find current bit offset of the top element on the stack from
+ * the beginning of the aggregate.
+ */
+static CONSZ
+findoff(void)
+{
+ struct instk *is;
+ OFFSZ off;
+
+#ifdef PCC_DEBUG
+ if (ISARY(pstk->in_t) || ISSOU(pstk->in_t))
+ cerror("findoff on bad type");
+#endif
+
+ /*
+ * Offset calculations. If:
+ * - previous type is STRTY, soffset has in-struct offset.
+ * - this type is ARY, offset is ninit*stsize.
+ */
+ for (off = 0, is = pstk; is; is = is->in_prev) {
+ if (is->in_prev && is->in_prev->in_t == STRTY)
+ off += is->in_sym->soffset;
+ if (ISARY(is->in_t)) {
+ /* suesize is the basic type, so adjust */
+ TWORD t = is->in_t;
+ OFFSZ o;
+ while (ISARY(t))
+ t = DECREF(t);
+ o = ISPTR(t) ? SZPOINT(t) : is->in_sym->ssue->suesize;
+ off += o * acalc(is, 1);
+ while (is->in_prev && ISARY(is->in_prev->in_t))
+ is = is->in_prev;
+ }
+ }
+ if (idebug>1) {
+ printf("findoff: off %lld\n", off);
+ prtstk(pstk);
+ }
+ return off;
+}
+
+/*
+ * Insert the node p with size fsz at position off.
+ * Bit fields are already dealt with, so a node of correct type
+ * with correct alignment and correct bit offset is given.
+ */
+static void
+nsetval(CONSZ off, int fsz, NODE *p)
+{
+ struct llist *ll;
+ struct ilist *il;
+
+ if (idebug>1)
+ printf("setval: off %lld fsz %d p %p\n", off, fsz, p);
+
+ if (fsz == 0)
+ return;
+
+ ll = setll(off);
+ off -= ll->begsz;
+ if (ll->il == NULL) {
+ ll->il = getil(NULL, off, fsz, p);
+ } else {
+ il = ll->il;
+ if (il->off > off) {
+ ll->il = getil(ll->il, off, fsz, p);
+ } else {
+ for (il = ll->il; il->next; il = il->next)
+ if (il->off <= off && il->next->off > off)
+ break;
+ if (il->off == off) {
+ /* replace */
+ nfree(il->n);
+ il->n = p;
+ } else
+ il->next = getil(il->next, off, fsz, p);
+ }
+ }
+}
+
+/*
+ * Align data and set correct location.
+ */
+static void
+setscl(struct symtab *sp)
+{
+ setloc1((sp->squal << TSHIFT) & CON ? RDATA : DATA);
+ defalign(talign(sp->stype, sp->ssue));
+ if (sp->sclass == EXTDEF ||
+ (sp->sclass == STATIC && sp->slevel == 0)) {
+ defnam(sp);
+ } else {
+ if (sp->soffset == NOOFFSET)
+ cerror("setscl");
+ deflab1(sp->soffset);
+ }
+}
+
+/*
+ * take care of generating a value for the initializer p
+ * inoff has the current offset (last bit written)
+ * in the current word being generated
+ */
+void
+scalinit(NODE *p)
+{
+ CONSZ woff;
+ NODE *q;
+ int fsz;
+
+#ifdef PCC_DEBUG
+ if (idebug > 2) {
+ printf("scalinit(%p)\n", p);
+ fwalk(p, eprint, 0);
+ prtstk(pstk);
+ }
+#endif
+
+ if (nerrors)
+ return;
+
+ p = optim(p);
+
+ if (csym->sclass != AUTO && p->n_op != ICON &&
+ p->n_op != FCON && p->n_op != NAME)
+ cerror("scalinit not leaf");
+
+ /* Out of elements? */
+ if (pstk == NULL) {
+ uerror("excess of initializing elements");
+ return;
+ }
+
+ /*
+ * Get to the simple type if needed.
+ */
+ while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
+ stkpush();
+
+ /* let buildtree do typechecking (and casting) */
+ q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_sym->sdf,
+ pstk->in_sym->ssue);
+ p = buildtree(ASSIGN, q, p);
+ nfree(p->n_left);
+ q = optim(p->n_right);
+ nfree(p);
+
+ /* bitfield sizes are special */
+ if (pstk->in_sym->sclass & FIELD)
+ fsz = -(pstk->in_sym->sclass & FLDSIZ);
+ else
+ fsz = tsize(pstk->in_t, pstk->in_sym->sdf, pstk->in_sym->ssue);
+ woff = findoff();
+
+ nsetval(woff, fsz, q);
+
+ stkpop();
+#ifdef PCC_DEBUG
+ if (idebug > 2) {
+ printf("scalinit e(%p)\n", p);
+ }
+#endif
+}
+
+/*
+ * Generate code to insert a value into a bitfield.
+ */
+static void
+insbf(OFFSZ off, int fsz, int val)
+{
+ struct symtab sym;
+ NODE *p, *r;
+ TWORD typ;
+
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ printf("insbf: off %lld fsz %d val %d\n", off, fsz, val);
+#endif
+
+ if (fsz == 0)
+ return;
+
+ /* small opt: do char instead of bf asg */
+ if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
+ typ = CHAR;
+ else
+ typ = INT;
+ /* Fake a struct reference */
+ spname = csym;
+ p = buildtree(ADDROF,
+ buildtree(NAME, NIL, NIL), NIL);
+ r = block(ICON, NIL, NIL, typ, 0, MKSUE(typ));
+ sym.stype = typ;
+ sym.squal = 0;
+ sym.sdf = 0;
+ sym.ssue = MKSUE(typ);
+ sym.soffset = off;
+ sym.sclass = typ == INT ? FIELD | fsz : MOU;
+ r->n_sp = &sym;
+ p = block(STREF, p, r, INT, 0, MKSUE(INT));
+ ecode(buildtree(ASSIGN, stref(p), bcon(val)));
+}
+
+/*
+ * Clear a bitfield, starting at off and size fsz.
+ */
+static void
+clearbf(OFFSZ off, OFFSZ fsz)
+{
+ /* Pad up to the next even initializer */
+ if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
+ int ba = ((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off;
+ if (ba > fsz)
+ ba = fsz;
+ insbf(off, ba, 0);
+ off += ba;
+ fsz -= ba;
+ }
+ while (fsz >= SZCHAR) {
+ insbf(off, SZCHAR, 0);
+ off += SZCHAR;
+ fsz -= SZCHAR;
+ }
+ if (fsz)
+ insbf(off, fsz, 0);
+}
+
+/*
+ * final step of initialization.
+ * print out init nodes and generate copy code (if needed).
+ */
+void
+endinit(void)
+{
+ struct llist *ll;
+ struct ilist *il;
+ int fsz;
+ OFFSZ lastoff, tbit;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("endinit()\n");
+#endif
+
+ if (csym->sclass != AUTO)
+ setscl(csym);
+
+ /* Calculate total block size */
+ if (ISARY(csym->stype) && csym->sdf->ddim == 0) {
+ tbit = numents*basesz; /* open-ended arrays */
+ csym->sdf->ddim = numents;
+ if (csym->sclass == AUTO) { /* Get stack space */
+ csym->soffset = NOOFFSET;
+ oalloc(csym, &autooff);
+ }
+ } else
+ tbit = tsize(csym->stype, csym->sdf, csym->ssue);
+
+ /* Traverse all entries and print'em out */
+ lastoff = 0;
+ SLIST_FOREACH(ll, &lpole, next) {
+ for (il = ll->il; il; il = il->next) {
+#ifdef PCC_DEBUG
+ if (idebug > 1) {
+ printf("off %lld size %d val %lld type ",
+ ll->begsz+il->off, il->fsz, il->n->n_lval);
+ tprint(stdout, il->n->n_type, 0);
+ printf("\n");
+ }
+#endif
+ fsz = il->fsz;
+ if (csym->sclass == AUTO) {
+ struct symtab sym;
+ NODE *p, *r, *n;
+
+ if (ll->begsz + il->off > lastoff)
+ clearbf(lastoff,
+ (ll->begsz + il->off) - lastoff);
+
+ /* Fake a struct reference */
+ spname = csym;
+ p = buildtree(ADDROF,
+ buildtree(NAME, NIL, NIL), NIL);
+ n = il->n;
+ r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ sym.stype = n->n_type;
+ sym.squal = n->n_qual;
+ sym.sdf = n->n_df;
+ sym.ssue = n->n_sue;
+ sym.soffset = ll->begsz + il->off;
+ sym.sclass = fsz < 0 ? FIELD | -fsz : 0;
+ r->n_sp = &sym;
+ p = block(STREF, p, r, INT, 0, MKSUE(INT));
+ ecode(buildtree(ASSIGN, stref(p), il->n));
+ if (fsz < 0)
+ fsz = -fsz;
+
+ } else {
+ if (ll->begsz + il->off > lastoff)
+ zbits(lastoff,
+ (ll->begsz + il->off) - lastoff);
+ if (fsz < 0) {
+ fsz = -fsz;
+ infld(il->off, fsz, il->n->n_lval);
+ } else
+ ninval(il->off, fsz, il->n);
+ nfree(il->n);
+ }
+ lastoff = ll->begsz + il->off + fsz;
+ }
+ }
+ if (csym->sclass == AUTO) {
+ clearbf(lastoff, tbit-lastoff);
+ } else
+ zbits(lastoff, tbit-lastoff);
+}
+
+/*
+ * process an initializer's left brace
+ */
+void
+ilbrace()
+{
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("ilbrace()\n");
+#endif
+
+ if (pstk == NULL)
+ return;
+
+ stkpush();
+ pstk->in_fl = 1; /* mark lbrace */
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ prtstk(pstk);
+#endif
+}
+
+/*
+ * called when a '}' is seen
+ */
+void
+irbrace()
+{
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("irbrace()\n");
+ if (idebug > 2)
+ prtstk(pstk);
+#endif
+
+ if (pstk == NULL)
+ return;
+
+ /* Got right brace, search for corresponding in the stack */
+ for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
+ if(!pstk->in_fl)
+ continue;
+
+ /* we have one now */
+
+ pstk->in_fl = 0; /* cancel { */
+ if (ISARY(pstk->in_t))
+ pstk->in_n = pstk->in_df->ddim;
+ else if (pstk->in_t == STRTY) {
+ while (pstk->in_xp[1] != NULL)
+ pstk->in_xp++;
+ }
+ stkpop();
+ return;
+ }
+}
+
+/*
+ * Create a new init stack based on given elements.
+ */
+static void
+mkstack(NODE *p)
+{
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("mkstack: %p\n", p);
+#endif
+
+ if (p == NULL)
+ return;
+ mkstack(p->n_left);
+
+ switch (p->n_op) {
+ case LB: /* Array index */
+ if (p->n_right->n_op != ICON)
+ cerror("mkstack");
+ if (!ISARY(pstk->in_t))
+ uerror("array indexing non-array");
+ pstk->in_n = p->n_right->n_lval;
+ nfree(p->n_right);
+ break;
+
+ case NAME:
+ if (pstk->in_xp) {
+ for (; pstk->in_xp[0]; pstk->in_xp++)
+ if (pstk->in_xp[0]->sname == (char *)p->n_sp)
+ break;
+ if (pstk->in_xp[0] == NULL)
+ uerror("member missing");
+ } else {
+ uerror("not a struct/union");
+ }
+ break;
+ default:
+ cerror("mkstack2");
+ }
+ nfree(p);
+ stkpush();
+
+}
+
+/*
+ * Initialize a specific element, as per C99.
+ */
+void
+desinit(NODE *p)
+{
+ int op = p->n_op;
+
+ if (pstk == NULL)
+ stkpush(); /* passed end of array */
+ while (pstk->in_prev && pstk->in_fl == 0)
+ pstk = pstk->in_prev; /* Empty stack */
+
+ if (ISSOU(pstk->in_t))
+ pstk->in_xp = pstk->in_sym->ssue->suelem;
+
+ mkstack(p); /* Setup for assignment */
+
+ /* pop one step if SOU, ilbrace will push */
+ if (op == NAME)
+ pstk = pstk->in_prev;
+
+#ifdef PCC_DEBUG
+ if (idebug > 1) {
+ printf("desinit e\n");
+ prtstk(pstk);
+ }
+#endif
+}
+
+/*
+ * Convert a string to an array of char/wchar for asginit.
+ */
+static void
+strcvt(NODE *p)
+{
+ char *s;
+ int i;
+
+ for (s = p->n_sp->sname; *s != 0; ) {
+ if (*s++ == '\\') {
+ i = esccon(&s);
+ } else
+ i = (unsigned char)s[-1];
+ asginit(bcon(i));
+ }
+ nfree(p);
+}
+
+/*
+ * Do an assignment to a struct element.
+ */
+void
+asginit(NODE *p)
+{
+ int g;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("asginit %p\n", p);
+ if (idebug > 1 && p)
+ fwalk(p, eprint, 0);
+#endif
+
+ /* convert string to array of char */
+ if (p && DEUNSIGN(p->n_type) == ARY+CHAR) {
+ /*
+ * ...but only if next element is ARY+CHAR, otherwise
+ * just fall through.
+ */
+
+ /* HACKHACKHACK */
+ struct instk *is = pstk;
+
+ while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
+ stkpush();
+ if (pstk->in_prev &&
+ DEUNSIGN(pstk->in_prev->in_t) == ARY+CHAR) {
+ pstk = pstk->in_prev;
+ if ((g = pstk->in_fl) == 0)
+ pstk->in_fl = 1; /* simulate ilbrace */
+
+ strcvt(p);
+ if (g == 0)
+ irbrace();
+ return;
+ } else
+ pstk = is; /* no array of char */
+ /* END HACKHACKHACK */
+ }
+
+ if (p == NULL) { /* only end of compound stmt */
+ irbrace();
+ } else /* assign next element */
+ scalinit(p);
+}
+
+#ifdef PCC_DEBUG
+void
+prtstk(struct instk *in)
+{
+ int i, o = 0;
+
+ printf("init stack:\n");
+ for (; in != NULL; in = in->in_prev) {
+ for (i = 0; i < o; i++)
+ printf(" ");
+ printf("%p) '%s' ", in, in->in_sym->sname);
+ tprint(stdout, in->in_t, 0);
+ printf(" %s ", scnames(in->in_sym->sclass));
+ if (in->in_df && in->in_df->ddim)
+ printf("arydim=%d ", in->in_df->ddim);
+ printf("ninit=%d ", in->in_n);
+ if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
+ printf("stsize=%d ", in->in_sym->ssue->suesize);
+ if (in->in_fl) printf("{ ");
+ printf("soff=%d ", in->in_sym->soffset);
+ if (in->in_t == STRTY) {
+ if (in->in_xp && in->in_xp[0])
+ printf("curel %s ", in->in_xp[0]->sname);
+ else
+ printf("END struct");
+ }
+ printf("\n");
+ o++;
+ }
+}
+#endif
+
+/*
+ * Do a simple initialization.
+ * At block 0, just print out the value, at higher levels generate
+ * appropriate code.
+ */
+void
+simpleinit(struct symtab *sp, NODE *p)
+{
+ /* May be an initialization of an array of char by a string */
+ if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
+ DEUNSIGN(sp->stype) == ARY+CHAR) ||
+ (DEUNSIGN(p->n_type) == ARY+WCHAR_TYPE &&
+ DEUNSIGN(sp->stype) == ARY+WCHAR_TYPE)) {
+ /* Handle "aaa" as { 'a', 'a', 'a' } */
+ beginit(sp);
+ strcvt(p);
+ if (csym->sdf->ddim == 0)
+ scalinit(bcon(0)); /* Null-term arrays */
+ endinit();
+ return;
+ }
+
+ switch (sp->sclass) {
+ case STATIC:
+ case EXTDEF:
+ spname = sp;
+ p = optim(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
+ setscl(sp);
+ ninval(0, p->n_right->n_sue->suesize, p->n_right);
+ tfree(p);
+ break;
+
+ case AUTO:
+ case REGISTER:
+ if (ISARY(sp->stype))
+ cerror("no array init");
+ spname = sp;
+ ecomp(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
+ break;
+
+ default:
+ uerror("illegal initialization");
+ }
+}
diff --git a/usr.bin/pcc/cc/ccom/inline.c b/usr.bin/pcc/cc/ccom/inline.c
new file mode 100644
index 00000000000..b0567573487
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/inline.c
@@ -0,0 +1,209 @@
+/* $Id: inline.c,v 1.1 2007/09/15 18:12:33 otto Exp $ */
+/*
+ * 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 <stdarg.h>
+
+/*
+ * ilink from ipole points to the next struct in the list of functions.
+ */
+static struct istat {
+ struct istat *ilink;
+ char *name;
+ int type;
+#define NOTYETR 0 /* saved but not yet referenced */
+#define NOTYETW 1 /* saved and referenced but not yet written out */
+#define WRITTEN 2 /* is written out */
+#define NOTYETD 3 /* referenced but not yet saved */
+ struct interpass shead;
+} *ipole, *cifun;
+
+#define IP_REF (MAXIP+1)
+
+int isinlining, recovernodes;
+int inlnodecnt, inlstatcnt;
+
+#define ialloc() permalloc(sizeof(struct istat)); inlstatcnt++
+#define nalloc() permalloc(sizeof(NODE))
+
+static void
+tcnt(NODE *p)
+{
+ inlnodecnt++;
+}
+
+static struct istat *
+findfun(char *name)
+{
+ struct istat *is = ipole;
+ while (is) {
+ if (is->name == name)
+ return is;
+ is = is->ilink;
+ }
+ return NULL;
+}
+
+static void
+refnode(char *str)
+{
+ struct interpass *ip;
+
+ if (sdebug)
+ printf("refnode(%s)\n", str);
+
+ ip = permalloc(sizeof(*ip));
+ ip->type = IP_REF;
+ ip->ip_name = str;
+ inline_addarg(ip);
+}
+
+void
+inline_addarg(struct interpass *ip)
+{
+ DLIST_INSERT_BEFORE(&cifun->shead, ip, qelem);
+ if (ip->type == IP_NODE)
+ walkf(ip->ip_node, tcnt); /* Count as saved */
+}
+
+/*
+ * Called to setup for inlining of a new function.
+ */
+void
+inline_start(char *name)
+{
+ struct istat *is;
+
+ if (sdebug)
+ printf("inline_start(\"%s\")\n", name);
+
+ if (isinlining)
+ cerror("already inlining function");
+
+ if ((is = findfun(name)) == 0) {
+ is = ialloc();
+ is->ilink = ipole;
+ ipole = is;
+ is->name = name;
+ is->type = NOTYETR;
+ } else {
+ if (is->type != NOTYETD)
+ cerror("inline function already defined");
+ is->type = NOTYETW;
+ }
+ DLIST_INIT(&is->shead, qelem);
+ cifun = is;
+ isinlining++;
+}
+
+void
+inline_end()
+{
+ if (sdebug)
+ printf("inline_end()\n");
+
+ isinlining = 0;
+}
+
+/*
+ * Called when an inline function is found, to be sure that it will
+ * be written out.
+ * The function may not be defined when inline_ref() is called.
+ */
+void
+inline_ref(char *name)
+{
+ struct istat *w = ipole;
+
+ if (sdebug)
+ printf("inline_ref(\"%s\")\n", name);
+ if (isinlining) {
+ refnode(name);
+ } else {
+ while (w != NULL) {
+ if (w->name == name) {
+ if (w->type == NOTYETR)
+ w->type = NOTYETW;
+ return; /* setup for writeout */
+ }
+ w = w->ilink;
+ }
+ /* function not yet defined, print out when found */
+ w = ialloc();
+ w->ilink = ipole;
+ ipole = w;
+ w->name = name;
+ w->type = NOTYETD;
+ }
+}
+
+static void
+puto(struct istat *w)
+{
+ struct interpass *ip, *nip;
+
+ /* if -O, list will be saved again so foreach cannot be used */
+ ip = DLIST_NEXT(&w->shead, qelem);
+ while (ip != (&w->shead)) {
+ nip = DLIST_NEXT(ip, qelem);
+ DLIST_REMOVE(ip, qelem);
+ if (ip->type == IP_REF)
+ inline_ref(ip->ip_name);
+ else
+ pass2_compile(ip);
+ ip = nip;
+ }
+ DLIST_INIT(&w->shead, qelem);
+}
+
+/*
+ * printout functions that are referenced.
+ */
+void
+inline_prtout()
+{
+ struct istat *w = ipole;
+ int gotone = 0;
+
+ if (w == NULL)
+ return;
+ recovernodes++;
+ while (w != NULL) {
+ if (w->type == NOTYETW) {
+ puto(w);
+ w->type = WRITTEN;
+ gotone++;
+ }
+ w = w->ilink;
+ }
+ if (gotone)
+ inline_prtout();
+ recovernodes--;
+}
diff --git a/usr.bin/pcc/cc/ccom/main.c b/usr.bin/pcc/cc/ccom/main.c
new file mode 100644
index 00000000000..40560e455d0
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/main.c
@@ -0,0 +1,313 @@
+/* $Id: main.c,v 1.1 2007/09/15 18:12:33 otto Exp $ */
+
+/*
+ * Copyright (c) 2002 Anders Magnusson. 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 <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pass1.h"
+#include "pass2.h"
+
+int sflag, nflag, oflag, kflag;
+int lflag, odebug, rdebug, radebug, vdebug, s2debug, udebug, x2debug;
+#if !defined(MULTIPASS) || defined(PASST)
+int iTflag, oTflag;
+#endif
+int xdebug, mdebug, sdebug, gflag, c2debug, pdebug;
+int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
+ Wimplicit_function_declaration;
+int xssaflag, xtailcallflag, xtemps, xdeljumps;
+
+int e2debug, t2debug, f2debug, b2debug;
+
+struct suedef btdims[24];
+char *prgname;
+
+static void prtstats(void);
+
+static struct {
+ char *n; int *f;
+} flagstr[] = {
+ { "strict-prototypes", &Wstrict_prototypes, },
+ { "missing-prototypes", &Wmissing_prototypes, },
+ { "implicit-int", &Wimplicit_int, },
+ { "implicit-function-declaration", &Wimplicit_function_declaration, },
+ { NULL, NULL, },
+};
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s [option] [infile] [outfile]...\n",
+ prgname);
+ exit(1);
+}
+
+static void
+segvcatch(int a)
+{
+ fprintf(stderr, "%sinternal compiler error: %s, line %d\n",
+ nerrors ? "" : "major ", ftitle, lineno);
+ fflush(stderr);
+ exit(1);
+}
+
+/*
+ * "emulate" the gcc warning flags.
+ */
+static void
+Wflags(char *str)
+{
+ int i, found = 0, all;
+
+ if (strcmp(str, "implicit") == 0) {
+ Wimplicit_int = Wimplicit_function_declaration = 1;
+ return;
+ }
+ all = strcmp(str, "W") == 0;
+ for (i = 0; flagstr[i].n; i++)
+ if (all || strcmp(flagstr[i].n, str) == 0) {
+ *flagstr[i].f = 1;
+ found++;
+ }
+ if (found == 0)
+ usage();
+}
+
+
+/* control multiple files */
+int
+main(int argc, char *argv[])
+{
+
+ int ch;
+
+ prgname = argv[0];
+
+ while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:k")) != -1)
+ switch (ch) {
+#if !defined(MULTIPASS) || defined(PASS1)
+ case 'X':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'd': ++ddebug; break; /* declarations */
+ case 'i': ++idebug; break; /* initializations */
+ case 'b': ++bdebug; break;
+ case 't': ++tdebug; break;
+ case 'e': ++edebug; break; /* pass1 exit */
+ case 'x': ++xdebug; break; /* MD code */
+ case 's': ++sdebug; break;
+ case 'n': ++nflag; break;
+ case 'o': ++oflag; break;
+ case 'p': ++pdebug; break; /* prototype */
+ default:
+ fprintf(stderr, "unknown X flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+#if !defined(MULTIPASS) || defined(PASST)
+ case 'T':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'i': ++iTflag; break;
+ case 'o': ++oTflag; break;
+ case 'n': ++nflag; break;
+ default:
+ fprintf(stderr, "unknown T flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+#if !defined(MULTIPASS) || defined(PASS2)
+ case 'Z':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'f': /* instruction matching */
+ ++f2debug;
+ break;
+ case 'e': /* print tree upon pass2 enter */
+ ++e2debug;
+ break;
+ case 'o': ++odebug; break;
+ case 'r': /* register alloc/graph coloring */
+ ++rdebug;
+ break;
+ case 'a': ++radebug; break;
+ case 'b': /* basic block and SSA building */
+ ++b2debug;
+ break;
+ case 'c': /* code printout */
+ ++c2debug;
+ break;
+ case 'm': ++mdebug; break;
+ case 'v': ++vdebug; break;
+ case 't': ++t2debug; break;
+ case 's': /* shape matching */
+ ++s2debug;
+ break;
+ case 'u': /* Sethi-Ullman debugging */
+ ++udebug;
+ break;
+ case 'x': ++x2debug; break;
+ case 'n': ++nflag; break;
+ default:
+ fprintf(stderr, "unknown Z flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+
+ case 'k': /* PIC code */
+ ++kflag;
+ break;
+
+ case 'l': /* linenos */
+ ++lflag;
+ break;
+
+ case 'g': /* Debugging */
+ gflag = 1;
+ break;
+
+ case 's': /* Statistics */
+ ++sflag;
+ break;
+
+ case 'W': /* Enable different warnings */
+ Wflags(optarg);
+ break;
+
+ case 'x': /* Different optimizations */
+ if (strcmp(optarg, "ssa") == 0)
+ xssaflag++;
+ else if (strcmp(optarg, "tailcall") == 0)
+ xtailcallflag++;
+ else if (strcmp(optarg, "temps") == 0)
+ xtemps++;
+ else if (strcmp(optarg, "deljumps") == 0)
+ xdeljumps++;
+ else
+ usage();
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0) {
+ if (freopen(argv[0], "r", stdin) == NULL) {
+ fprintf(stderr, "open input file '%s':",
+ argv[0]);
+ perror(NULL);
+ exit(1);
+ }
+ if (argc != 1)
+ if (freopen(argv[1], "w", stdout) == NULL) {
+ fprintf(stderr, "open output file '%s':",
+ argv[1]);
+ perror(NULL);
+ exit(1);
+ }
+ }
+
+ mkdope();
+ signal(SIGSEGV, segvcatch);
+ fregs = FREGS; /* number of free registers */
+ lineno = 1;
+#ifdef GCC_COMPAT
+ gcc_init();
+#endif
+
+ /* dimension table initialization */
+
+ btdims[VOID].suesize = 0;
+ btdims[BOOL].suesize = SZBOOL;
+ btdims[CHAR].suesize = SZCHAR;
+ btdims[INT].suesize = SZINT;
+ btdims[FLOAT].suesize = SZFLOAT;
+ btdims[DOUBLE].suesize = SZDOUBLE;
+ btdims[LDOUBLE].suesize = SZLDOUBLE;
+ btdims[LONG].suesize = SZLONG;
+ btdims[LONGLONG].suesize = SZLONGLONG;
+ btdims[SHORT].suesize = SZSHORT;
+ btdims[UCHAR].suesize = SZCHAR;
+ btdims[USHORT].suesize = SZSHORT;
+ btdims[UNSIGNED].suesize = SZINT;
+ btdims[ULONG].suesize = SZLONG;
+ btdims[ULONGLONG].suesize = SZLONGLONG;
+ /* starts past any of the above */
+ reached = 1;
+
+ bjobcode();
+
+#ifdef STABS
+ if (gflag) {
+ stabs_file(argc ? argv[0] : "");
+ stabs_init();
+ }
+#endif
+
+ (void) yyparse();
+ yyaccpt();
+
+ ejobcode( nerrors ? 1 : 0 );
+ lcommprint();
+
+ if (sflag)
+ prtstats();
+ return(nerrors?1:0);
+
+}
+
+void
+prtstats(void)
+{
+ extern int nametabs, namestrlen, tmpallocsize, permallocsize;
+ extern int lostmem, arglistcnt, dimfuncnt, inlnodecnt, inlstatcnt;
+ extern int symtabcnt, suedefcnt;
+
+ fprintf(stderr, "Name table entries: %d pcs\n", nametabs);
+ fprintf(stderr, "Name string size: %d B\n", namestrlen);
+ fprintf(stderr, "Permanent allocated memory: %d B\n", permallocsize);
+ fprintf(stderr, "Temporary allocated memory: %d B\n", tmpallocsize);
+ fprintf(stderr, "Lost memory: %d B\n", lostmem);
+ fprintf(stderr, "Argument list unions: %d pcs\n", arglistcnt);
+ fprintf(stderr, "Dimension/function unions: %d pcs\n", dimfuncnt);
+ fprintf(stderr, "Struct/union/enum blocks: %d pcs\n", suedefcnt);
+ fprintf(stderr, "Inline node count: %d pcs\n", inlnodecnt);
+ fprintf(stderr, "Inline control blocks: %d pcs\n", inlstatcnt);
+ fprintf(stderr, "Permanent symtab entries: %d pcs\n", symtabcnt);
+}
diff --git a/usr.bin/pcc/cc/ccom/optim.c b/usr.bin/pcc/cc/ccom/optim.c
new file mode 100644
index 00000000000..848e8535659
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/optim.c
@@ -0,0 +1,355 @@
+/* $Id: optim.c,v 1.1 2007/09/15 18:12:34 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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"
+
+# define SWAP(p,q) {sp=p; p=q; q=sp;}
+# define RCON(p) (p->n_right->n_op==ICON)
+# define RO(p) p->n_right->n_op
+# define RV(p) p->n_right->n_lval
+# define LCON(p) (p->n_left->n_op==ICON)
+# define LO(p) p->n_left->n_op
+# define LV(p) p->n_left->n_lval
+
+static int nncon(NODE *);
+
+int oflag = 0;
+
+/* remove left node */
+static NODE *
+zapleft(NODE *p)
+{
+ NODE *q;
+
+ q = p->n_left;
+ nfree(p->n_right);
+ nfree(p);
+ return q;
+}
+
+/*
+ * fortran function arguments
+ */
+static NODE *
+fortarg(NODE *p)
+{
+ if( p->n_op == CM ){
+ p->n_left = fortarg( p->n_left );
+ p->n_right = fortarg( p->n_right );
+ return(p);
+ }
+
+ while( ISPTR(p->n_type) ){
+ p = buildtree( UMUL, p, NIL );
+ }
+ return( optim(p) );
+}
+
+ /* mapping relationals when the sides are reversed */
+short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
+
+/*
+ * local optimizations, most of which are probably
+ * machine independent
+ */
+NODE *
+optim(NODE *p)
+{
+ int o, ty;
+ NODE *sp, *q;
+ int i;
+ TWORD t;
+
+ if( (t=BTYPE(p->n_type))==ENUMTY || t==MOETY ) econvert(p);
+ if( oflag ) return(p);
+
+ ty = coptype(p->n_op);
+ if( ty == LTYPE ) return(p);
+
+ if( ty == BITYPE ) p->n_right = optim(p->n_right);
+ p->n_left = optim(p->n_left);
+
+ /* collect constants */
+again: o = p->n_op;
+ switch(o){
+
+ case SCONV:
+ case PCONV:
+ return( clocal(p) );
+
+ case FORTCALL:
+ p->n_right = fortarg( p->n_right );
+ break;
+
+ case ADDROF:
+ if (LO(p) == TEMP)
+ return p;
+ if( LO(p) != NAME ) cerror( "& error" );
+
+ if( !andable(p->n_left) ) return(p);
+
+ LO(p) = ICON;
+
+ setuleft:
+ /* paint over the type of the left hand side with the type of the top */
+ p->n_left->n_type = p->n_type;
+ p->n_left->n_df = p->n_df;
+ p->n_left->n_sue = p->n_sue;
+ q = p->n_left;
+ nfree(p);
+ return q;
+
+ case UMUL:
+ if( LO(p) != ICON ) break;
+ LO(p) = NAME;
+ goto setuleft;
+
+ case RS:
+ if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
+ /* two right-shift by constants */
+ RV(p) += RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#if 0
+ else if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
+ RV(p) -= RV(p->n_left);
+ if (RV(p) < 0)
+ o = p->n_op = LS, RV(p) = -RV(p);
+ p->n_left = zapleft(p->n_left);
+ }
+#endif
+ if (RO(p) == ICON) {
+ if (RV(p) < 0) {
+ RV(p) = -RV(p);
+ p->n_op = LS;
+ goto again;
+ }
+#ifdef notyet /* must check for side effects, --a >> 32; */
+ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue) &&
+ ISUNSIGNED(p->n_type)) { /* ignore signed shifts */
+ /* too many shifts */
+ tfree(p->n_left);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
+ } else
+#endif
+ /* avoid larger shifts than type size */
+ if (RV(p) >= p->n_sue->suesize) {
+ RV(p) = RV(p) % p->n_sue->suesize;
+ werror("shift larger than type");
+ }
+ if (RV(p) == 0)
+ p = zapleft(p);
+ }
+ break;
+
+ case LS:
+ if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
+ /* two left-shift by constants */
+ RV(p) += RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#if 0
+ else if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
+ RV(p) -= RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#endif
+ if (RO(p) == ICON) {
+ if (RV(p) < 0) {
+ RV(p) = -RV(p);
+ p->n_op = RS;
+ goto again;
+ }
+#ifdef notyet /* must check for side effects */
+ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue)) {
+ /* too many shifts */
+ tfree(p->n_left);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
+ } else
+#endif
+ /* avoid larger shifts than type size */
+ if (RV(p) >= p->n_sue->suesize) {
+ RV(p) = RV(p) % p->n_sue->suesize;
+ werror("shift larger than type");
+ }
+ if (RV(p) == 0)
+ p = zapleft(p);
+ }
+ break;
+
+ case MINUS:
+ if (LCON(p) && RCON(p) && p->n_left->n_sp == p->n_right->n_sp) {
+ /* link-time constants, but both are the same */
+ /* solve it now by forgetting the symbols */
+ p->n_left->n_sp = p->n_right->n_sp = NULL;
+ }
+ if( !nncon(p->n_right) ) break;
+ RV(p) = -RV(p);
+ o = p->n_op = PLUS;
+
+ case MUL:
+ case PLUS:
+ case AND:
+ case OR:
+ case ER:
+ /* commutative ops; for now, just collect constants */
+ /* someday, do it right */
+ if( nncon(p->n_left) || ( LCON(p) && !RCON(p) ) )
+ SWAP( p->n_left, p->n_right );
+ /* make ops tower to the left, not the right */
+ if( RO(p) == o ){
+ NODE *t1, *t2, *t3;
+ t1 = p->n_left;
+ sp = p->n_right;
+ t2 = sp->n_left;
+ t3 = sp->n_right;
+ /* now, put together again */
+ p->n_left = sp;
+ sp->n_left = t1;
+ sp->n_right = t2;
+ p->n_right = t3;
+ }
+ if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->n_left) &&
+ conval(p->n_right, MINUS, p->n_left->n_right)){
+ zapleft:
+
+ q = p->n_left->n_left;
+ nfree(p->n_left->n_right);
+ nfree(p->n_left);
+ p->n_left = q;
+ }
+ if( RCON(p) && LO(p)==o && RCON(p->n_left) &&
+ conval( p->n_right, o, p->n_left->n_right ) ){
+ goto zapleft;
+ }
+ else if( LCON(p) && RCON(p) && conval( p->n_left, o, p->n_right ) ){
+ zapright:
+ nfree(p->n_right);
+ q = makety(p->n_left, p->n_type, p->n_qual,
+ p->n_df, p->n_sue);
+ nfree(p);
+ return clocal(q);
+ }
+
+ /* change muls to shifts */
+
+ if( o == MUL && nncon(p->n_right) && (i=ispow2(RV(p)))>=0){
+ if( i == 0 ) { /* multiplication by 1 */
+ goto zapright;
+ }
+ o = p->n_op = LS;
+ p->n_right->n_type = INT;
+ p->n_right->n_df = NULL;
+ RV(p) = i;
+ }
+
+ /* change +'s of negative consts back to - */
+ if( o==PLUS && nncon(p->n_right) && RV(p)<0 ){
+ RV(p) = -RV(p);
+ o = p->n_op = MINUS;
+ }
+
+ /* remove ops with RHS 0 */
+ if ((o == PLUS || o == MINUS || o == OR || o == ER) &&
+ nncon(p->n_right) && RV(p) == 0) {
+ goto zapright;
+ }
+ break;
+
+ case DIV:
+ if( nncon( p->n_right ) && p->n_right->n_lval == 1 )
+ goto zapright;
+ if (LCON(p) && RCON(p) && conval(p->n_left, DIV, p->n_right))
+ goto zapright;
+ if (RCON(p) && ISUNSIGNED(p->n_type) && (i=ispow2(RV(p))) > 0) {
+ p->n_op = RS;
+ RV(p) = i;
+ q = p->n_right;
+ if(tsize(q->n_type, q->n_df, q->n_sue) > SZINT)
+ p->n_right = makety(q, INT, 0, 0, MKSUE(INT));
+
+ break;
+ }
+ break;
+
+ case MOD:
+ if (RCON(p) && ISUNSIGNED(p->n_type) && ispow2(RV(p)) > 0) {
+ p->n_op = AND;
+ RV(p) = RV(p) -1;
+ break;
+ }
+ break;
+
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ case ULT:
+ case ULE:
+ case UGT:
+ case UGE:
+ if( !LCON(p) ) break;
+
+ /* exchange operands */
+
+ sp = p->n_left;
+ p->n_left = p->n_right;
+ p->n_right = sp;
+ p->n_op = revrel[p->n_op - EQ ];
+ break;
+
+ }
+
+ return(p);
+ }
+
+int
+ispow2(CONSZ c)
+{
+ int i;
+ if( c <= 0 || (c&(c-1)) ) return(-1);
+ for( i=0; c>1; ++i) c >>= 1;
+ return(i);
+}
+
+int
+nncon( p ) NODE *p; {
+ /* is p a constant without a name */
+ return( p->n_op == ICON && p->n_sp == NULL );
+ }
diff --git a/usr.bin/pcc/cc/ccom/pass1.h b/usr.bin/pcc/cc/ccom/pass1.h
new file mode 100644
index 00000000000..8513888fff5
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/pass1.h
@@ -0,0 +1,394 @@
+/* $Id: pass1.h,v 1.1 2007/09/15 18:12:34 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <sys/types.h>
+#include <stdarg.h>
+
+#include "manifest.h"
+
+#include "protos.h"
+#include "ccconfig.h"
+
+/*
+ * Storage classes
+ */
+#define SNULL 0
+#define AUTO 1
+#define EXTERN 2
+#define STATIC 3
+#define REGISTER 4
+#define EXTDEF 5
+/* #define LABEL 6*/
+/* #define ULABEL 7*/
+#define MOS 8
+#define PARAM 9
+#define STNAME 10
+#define MOU 11
+#define UNAME 12
+#define TYPEDEF 13
+#define FORTRAN 14
+#define ENAME 15
+#define MOE 16
+#define UFORTRAN 17
+#define USTATIC 18
+#define ILABEL 19
+
+ /* field size is ORed in */
+#define FIELD 0100
+#define FLDSIZ 077
+extern char *scnames(int);
+
+/*
+ * Symbol table flags
+ */
+#define SNORMAL 0
+#define STAGNAME 01
+#define SLBLNAME 02
+#define SMOSNAME 03
+#define SSTRING 04
+#define NSTYPES 05
+#define SMASK 07
+
+#define SSET 00010
+#define SREF 00020
+#define SNOCREAT 00040
+#define STEMP 00100
+#define SDYNARRAY 00200
+#define SINLINE 00400
+#define STNODE 01000
+#ifdef GCC_COMPAT
+#define SRENAME 02000 /* Node is renamed */
+#endif
+#define SASG 04000
+
+#ifndef FIXDEF
+#define FIXDEF(p)
+#endif
+
+ /* alignment of initialized quantities */
+#ifndef AL_INIT
+#define AL_INIT ALINT
+#endif
+
+struct rstack;
+struct symtab;
+union arglist;
+
+/*
+ * Dimension/prototype information.
+ * ddim > 0 holds the dimension of an array.
+ * ddim < 0 is a dynamic array and refers to a tempnode.
+ */
+union dimfun {
+ int ddim; /* Dimension of an array */
+ union arglist *dfun; /* Prototype index */
+};
+
+/*
+ * Struct/union/enum definition.
+ * The first element (size) is used for other types as well.
+ */
+struct suedef {
+ int suesize; /* Size of the struct */
+ struct symtab **suelem;/* points to the list of elements */
+ int suealign; /* Alignment of this struct */
+};
+
+/*
+ * Argument list member info when storing prototypes.
+ */
+union arglist {
+ TWORD type;
+ union dimfun *df;
+ struct suedef *sue;
+};
+#define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
+#define TELLIPSIS INCREF(INCREF(MOETY))
+
+/*
+ * Symbol table definition.
+ *
+ * The symtab_hdr struct is used to save label info in NAME and ICON nodes.
+ */
+struct symtab_hdr {
+ struct symtab *h_next; /* link to other symbols in the same scope */
+ int h_offset; /* offset or value */
+ char h_sclass; /* storage class */
+ char h_slevel; /* scope level */
+ short h_sflags; /* flags, see below */
+};
+
+struct symtab {
+ struct symtab_hdr hdr;
+ char *sname;
+ TWORD stype; /* type word */
+ TWORD squal; /* qualifier word */
+ union dimfun *sdf; /* ptr to the dimension/prototype array */
+ struct suedef *ssue; /* ptr to the definition table */
+ int suse; /* line number of last use of the variable */
+};
+
+#define snext hdr.h_next
+#define soffset hdr.h_offset
+#define sclass hdr.h_sclass
+#define slevel hdr.h_slevel
+#define sflags hdr.h_sflags
+
+#define MKSUE(type) &btdims[type]
+extern struct suedef btdims[];
+
+/*
+ * External definitions
+ */
+struct swents { /* switch table */
+ struct swents *next; /* Next struct in linked list */
+ CONSZ sval; /* case value */
+ int slab; /* associated label */
+};
+void genswitch(int, struct swents **, int);
+
+extern int blevel;
+extern int instruct, got_type;
+extern int oldstyle;
+
+extern int lineno, nerrors;
+
+extern char *ftitle;
+extern struct symtab *cftnsp;
+extern int autooff, maxautooff, argoff, strucoff;
+extern int brkflag;
+extern int lastloc;
+
+extern OFFSZ inoff;
+
+extern int reached;
+extern int isinlining;
+
+/* tunnel to buildtree for name id's */
+
+extern struct symtab *spname;
+
+extern int sdebug, idebug, pdebug;
+
+/* various labels */
+extern int brklab;
+extern int contlab;
+extern int flostat;
+extern int retlab;
+
+/*
+ * Flags used in structures/unions
+ */
+#define INSTRUCT 02
+#define INUNION 04
+
+/*
+ * Flags used in the (elementary) flow analysis ...
+ */
+#define FBRK 02
+#define FCONT 04
+#define FDEF 010
+#define FLOOP 020
+
+/* mark an offset which is undefined */
+
+#define NOOFFSET (-10201)
+
+/* declarations of various functions */
+extern NODE
+ *buildtree(int, NODE *l, NODE *r),
+ *mkty(unsigned, union dimfun *, struct suedef *),
+ *rstruct(char *, int),
+ *dclstruct(struct rstack *),
+ *strend(char *),
+ *wstrend(char *),
+ *tymerge(NODE *typ, NODE *idp),
+ *stref(NODE *),
+ *offcon(OFFSZ, TWORD, union dimfun *, struct suedef *),
+ *bcon(int),
+ *bpsize(NODE *),
+ *convert(NODE *, int),
+ *pconvert(NODE *),
+ *oconvert(NODE *),
+ *ptmatch(NODE *),
+ *tymatch(NODE *),
+ *makety(NODE *, TWORD, TWORD, union dimfun *, struct suedef *),
+ *block(int, NODE *, NODE *r, TWORD, union dimfun *, struct suedef *),
+ *doszof(NODE *),
+ *talloc(void),
+ *optim(NODE *),
+ *clocal(NODE *),
+ *ccopy(NODE *),
+ *btsize(TWORD, union dimfun *, struct suedef *),
+ *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue),
+ *doacall(NODE *f, NODE *a);
+OFFSZ tsize(TWORD, union dimfun *, struct suedef *),
+ psize(NODE *);
+NODE * typenode(NODE *new);
+void spalloc(NODE *, NODE *, OFFSZ);
+char *exname(char *);
+
+int oalloc(struct symtab *p, int *poff);
+void deflabel(char *);
+void deflab1(int);
+void setloc1(int);
+void gotolabel(char *);
+unsigned int esccon(char **sptr);
+void inline_start(char *name);
+void inline_end(void);
+void inline_addarg(struct interpass *);
+void inline_ref(char *);
+void inline_prtout(void);
+void ftnarg(NODE *);
+struct rstack *bstruct(char *, int);
+void moedef(char *);
+void beginit(struct symtab *);
+void simpleinit(struct symtab *, NODE *);
+struct symtab *lookup(char *name, int s);
+struct symtab *getsymtab(char *name, int flags);
+char *addstring(char *);
+char *addname(char *);
+char *newstring(char *, int len);
+void symclear(int level);
+void schedremove(struct symtab *p);
+struct symtab *hide(struct symtab *p);
+int talign(unsigned int, struct suedef *);
+void bfcode(struct symtab **, int);
+int chkftn(union arglist *, union arglist *);
+void branch(int);
+void cbranch(NODE *p, NODE *q);
+void extdec(struct symtab *);
+void commdec(struct symtab *);
+void lcommdec(struct symtab *);
+int falloc(struct symtab *p, int w, int new, NODE *pty);
+TWORD ctype(TWORD);
+void ninval(CONSZ off, int fsz, NODE *);
+void infld(CONSZ off, int fsz, CONSZ);
+void zbits(CONSZ off, int fsz);
+void indata(CONSZ, int);
+void instring(char *);
+void defnam(struct symtab *);
+void plabel(int lab);
+void bjobcode(void);
+void ejobcode(int);
+void calldec(NODE *, NODE *);
+int cisreg(TWORD);
+char *tmpsprintf(char *fmt, ...);
+char *tmpvsprintf(char *fmt, va_list ap);
+void asginit(NODE *);
+void desinit(NODE *);
+void endinit(void);
+void ilbrace(void);
+void irbrace(void);
+void scalinit(NODE *p);
+int ftoint(NODE *, CONSZ **);
+void p1print(char *fmt, ...);
+char *copst(int);
+int cdope(int);
+void myp2tree(NODE *);
+void lcommprint(void);
+void lcommdel(struct symtab *);
+
+#ifdef GCC_COMPAT
+void gcc_init(void);
+int gcc_keyword(char *, NODE **);
+void gcc_rename(struct symtab *sp, char *newname);
+char *gcc_findname(struct symtab *sp);
+#endif
+
+#ifdef STABS
+void stabs_init(void);
+void stabs_file(char *);
+void stabs_line(int);
+void stabs_rbrac(int);
+void stabs_lbrac(int);
+void stabs_func(struct symtab *);
+void stabs_newsym(struct symtab *);
+void stabs_chgsym(struct symtab *);
+void stabs_struct(struct symtab *p, struct suedef *sue);
+#endif
+
+#ifndef CHARCAST
+/* to make character constants into character connstants */
+/* this is a macro to defend against cross-compilers, etc. */
+#define CHARCAST(x) (char)(x)
+#endif
+
+/*
+ * C compiler first pass extra defines.
+ */
+#define QUALIFIER (MAXOP+1)
+#define CLASS (MAXOP+2)
+#define RB (MAXOP+3)
+#define DOT (MAXOP+4)
+#define ELLIPSIS (MAXOP+5)
+#define TYPE (MAXOP+6)
+#define LB (MAXOP+7)
+#define COMOP (MAXOP+8)
+#define QUEST (MAXOP+9)
+#define COLON (MAXOP+10)
+#define ANDAND (MAXOP+11)
+#define OROR (MAXOP+12)
+#define NOT (MAXOP+13)
+#define CAST (MAXOP+14)
+/* #define STRING (MAXOP+15) */
+
+/* The following must be in the same order as their NOASG counterparts */
+#define PLUSEQ (MAXOP+16)
+#define MINUSEQ (MAXOP+17)
+#define DIVEQ (MAXOP+18)
+#define MODEQ (MAXOP+19)
+#define MULEQ (MAXOP+20)
+#define ANDEQ (MAXOP+21)
+#define OREQ (MAXOP+22)
+#define EREQ (MAXOP+23)
+#define LSEQ (MAXOP+24)
+#define RSEQ (MAXOP+25)
+
+#define UNASG (-(PLUSEQ-PLUS))+
+
+#define INCR (MAXOP+26)
+#define DECR (MAXOP+27)
+/*
+ * The following types are only used in pass1.
+ */
+#define SIGNED (MAXTYPES+1)
+#define BOOL (MAXTYPES+2)
+
+
+#define coptype(o) (cdope(o)&TYFLG)
+#define clogop(o) (cdope(o)&LOGFLG)
+#define casgop(o) (cdope(o)&ASGFLG)
+
diff --git a/usr.bin/pcc/cc/ccom/pftn.c b/usr.bin/pcc/cc/ccom/pftn.c
new file mode 100644
index 00000000000..f5be111dc2c
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/pftn.c
@@ -0,0 +1,2549 @@
+/* $Id: pftn.c,v 1.1 2007/09/15 18:12:34 otto Exp $ */
+/*
+ * 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.
+ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+/*
+ * Many changes from the 32V sources, among them:
+ * - New symbol table manager (moved to another file).
+ * - Prototype saving/checks.
+ */
+
+# include "pass1.h"
+
+#include <string.h> /* XXX - for strcmp */
+
+struct symtab *spname;
+struct symtab *cftnsp;
+static int strunem; /* currently parsed member type */
+int arglistcnt, dimfuncnt; /* statistics */
+int symtabcnt, suedefcnt; /* statistics */
+int autooff, /* the next unused automatic offset */
+ maxautooff, /* highest used automatic offset in function */
+ argoff, /* the next unused argument offset */
+ strucoff; /* the next structure offset position */
+int retlab = NOLAB; /* return label for subroutine */
+int brklab;
+int contlab;
+int flostat;
+int instruct, blevel;
+int reached, prolab;
+
+struct params;
+
+#define ISSTR(ty) (ty == STRTY || ty == UNIONTY || ty == ENUMTY)
+#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
+#define MKTY(p, t, d, s) r = talloc(); *r = *p; \
+ r = argcast(r, t, d, s); *p = *r; nfree(r);
+
+/*
+ * Info stored for delaying string printouts.
+ */
+struct strsched {
+ struct strsched *next;
+ int locctr;
+ struct symtab *sym;
+} *strpole;
+
+/*
+ * Linked list stack while reading in structs.
+ */
+struct rstack {
+ struct rstack *rnext;
+ int rinstruct;
+ int rclass;
+ int rstrucoff;
+ struct params *rlparam;
+ struct symtab *rsym;
+};
+
+/*
+ * Linked list for parameter (and struct elements) declaration.
+ */
+static struct params {
+ struct params *next, *prev;
+ struct symtab *sym;
+} *lpole, *lparam;
+static int nparams;
+
+/* defines used for getting things off of the initialization stack */
+
+static NODE *arrstk[10];
+static int arrstkp;
+static int intcompare;
+
+void fixtype(NODE *p, int class);
+int fixclass(int class, TWORD type);
+int falloc(struct symtab *p, int w, int new, NODE *pty);
+static void dynalloc(struct symtab *p, int *poff);
+void inforce(OFFSZ n);
+void vfdalign(int n);
+static void ssave(struct symtab *);
+static void strprint(void);
+static void alprint(union arglist *al, int in);
+static void lcommadd(struct symtab *sp);
+
+int ddebug = 0;
+
+/*
+ * Declaration of an identifier. Handles redeclarations, hiding,
+ * incomplete types and forward declarations.
+ */
+
+void
+defid(NODE *q, int class)
+{
+ struct symtab *p;
+ TWORD type, qual;
+ TWORD stp, stq;
+ int scl;
+ union dimfun *dsym, *ddef;
+ int slev, temp, changed;
+
+ if (q == NIL)
+ return; /* an error was detected */
+
+ p = q->n_sp;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf("defid(%s (%p), ", p->sname, p);
+ tprint(stdout, q->n_type, q->n_qual);
+ printf(", %s, (%p,%p)), level %d\n", scnames(class),
+ q->n_df, q->n_sue, blevel);
+ }
+#endif
+
+ fixtype(q, class);
+
+ type = q->n_type;
+ qual = q->n_qual;
+ class = fixclass(class, type);
+
+ stp = p->stype;
+ stq = p->squal;
+ slev = p->slevel;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf(" modified to ");
+ tprint(stdout, type, qual);
+ printf(", %s\n", scnames(class));
+ printf(" previous def'n: ");
+ tprint(stdout, stp, stq);
+ printf(", %s, (%p,%p)), level %d\n",
+ scnames(p->sclass), p->sdf, p->ssue, slev);
+ }
+#endif
+
+ if (blevel == 1) {
+ switch (class) {
+ default:
+ if (!(class&FIELD))
+ uerror("declared argument %s missing",
+ p->sname );
+ case MOS:
+ case STNAME:
+ case MOU:
+ case UNAME:
+ case MOE:
+ case ENAME:
+ case TYPEDEF:
+ ;
+ }
+ }
+
+ if (stp == UNDEF)
+ goto enter; /* New symbol */
+
+ if (type != stp)
+ goto mismatch;
+
+ if (blevel > slev && (class == AUTO || class == REGISTER))
+ /* new scope */
+ goto mismatch;
+
+ /*
+ * test (and possibly adjust) dimensions.
+ * also check that prototypes are correct.
+ */
+ dsym = p->sdf;
+ ddef = q->n_df;
+ changed = 0;
+ for (temp = type; temp & TMASK; temp = DECREF(temp)) {
+ if (ISARY(temp)) {
+ if (dsym->ddim == 0) {
+ dsym->ddim = ddef->ddim;
+ changed = 1;
+ } else if (ddef->ddim != 0 && dsym->ddim!=ddef->ddim) {
+ goto mismatch;
+ }
+ ++dsym;
+ ++ddef;
+ } else if (ISFTN(temp)) {
+ /* add a late-defined prototype here */
+ if (cftnsp == NULL && dsym->dfun == NULL)
+ dsym->dfun = ddef->dfun;
+ if (!oldstyle && ddef->dfun != NULL &&
+ chkftn(dsym->dfun, ddef->dfun))
+ uerror("declaration doesn't match prototype");
+ dsym++, ddef++;
+ }
+ }
+#ifdef STABS
+ if (changed && gflag)
+ stabs_chgsym(p); /* symbol changed */
+#endif
+
+ /* check that redeclarations are to the same structure */
+ if ((temp == STRTY || temp == UNIONTY || temp == ENUMTY) &&
+ p->ssue != q->n_sue &&
+ class != STNAME && class != UNAME && class != ENAME) {
+ goto mismatch;
+ }
+
+ scl = p->sclass;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf(" previous class: %s\n", scnames(scl));
+#endif
+
+ if (class&FIELD) {
+ /* redefinition */
+ if (!falloc(p, class&FLDSIZ, 1, NIL)) {
+ /* successful allocation */
+ ssave(p);
+ return;
+ }
+ /* blew it: resume at end of switch... */
+ } else switch(class) {
+
+ case EXTERN:
+ switch( scl ){
+ case STATIC:
+ case USTATIC:
+ if( slev==0 ) return;
+ break;
+ case EXTDEF:
+ case EXTERN:
+ case FORTRAN:
+ case UFORTRAN:
+ return;
+ }
+ break;
+
+ case STATIC:
+ if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
+ p->sclass = STATIC;
+ return;
+ }
+ if (changed || (scl == STATIC && blevel == slev))
+ return; /* identical redeclaration */
+ break;
+
+ case USTATIC:
+ if (scl==STATIC || scl==USTATIC)
+ return;
+ break;
+
+ case TYPEDEF:
+ if (scl == class)
+ return;
+ break;
+
+ case UFORTRAN:
+ if (scl == UFORTRAN || scl == FORTRAN)
+ return;
+ break;
+
+ case FORTRAN:
+ if (scl == UFORTRAN) {
+ p->sclass = FORTRAN;
+ return;
+ }
+ break;
+
+ case MOU:
+ case MOS:
+ if (scl == class) {
+ if (oalloc(p, &strucoff))
+ break;
+ if (class == MOU)
+ strucoff = 0;
+ ssave(p);
+ return;
+ }
+ break;
+
+ case MOE:
+ break;
+
+ case EXTDEF:
+ switch (scl) {
+ case EXTERN:
+ p->sclass = EXTDEF;
+ return;
+ case USTATIC:
+ p->sclass = STATIC;
+ return;
+ }
+ break;
+
+ case STNAME:
+ case UNAME:
+ case ENAME:
+ if (scl != class)
+ break;
+ if (p->ssue->suesize == 0)
+ return; /* previous entry just a mention */
+ break;
+
+ case AUTO:
+ case REGISTER:
+ ; /* mismatch.. */
+ }
+
+ mismatch:
+
+ /*
+ * Only allowed for automatic variables.
+ */
+ if (blevel == slev || class == EXTERN || class == FORTRAN ||
+ class == UFORTRAN) {
+ if (ISSTR(class) && !ISSTR(p->sclass)) {
+ uerror("redeclaration of %s", p->sname);
+ return;
+ }
+ }
+ if (blevel == 0)
+ uerror("redeclaration of %s", p->sname);
+ q->n_sp = p = hide(p);
+
+ enter: /* make a new entry */
+
+#ifdef PCC_DEBUG
+ if(ddebug)
+ printf(" new entry made\n");
+#endif
+ p->stype = type;
+ p->squal = qual;
+ p->sclass = class;
+ p->slevel = blevel;
+ p->soffset = NOOFFSET;
+ p->suse = lineno;
+ if (class == STNAME || class == UNAME || class == ENAME) {
+ p->ssue = permalloc(sizeof(struct suedef));
+ suedefcnt++;
+ p->ssue->suesize = 0;
+ p->ssue->suelem = NULL;
+ p->ssue->suealign = ALSTRUCT;
+ } else {
+ switch (BTYPE(type)) {
+ case STRTY:
+ case UNIONTY:
+ case ENUMTY:
+ p->ssue = q->n_sue;
+ break;
+ default:
+ p->ssue = MKSUE(BTYPE(type));
+ }
+ }
+
+ /* copy dimensions */
+ p->sdf = q->n_df;
+ /* Do not save param info for old-style functions */
+ if (ISFTN(type) && oldstyle)
+ p->sdf->dfun = NULL;
+
+ /* allocate offsets */
+ if (class&FIELD) {
+ (void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */
+ ssave(p);
+ } else switch (class) {
+
+ case REGISTER:
+ cerror("register var");
+
+ case AUTO:
+ if (arrstkp)
+ dynalloc(p, &autooff);
+ else
+ oalloc(p, &autooff);
+ break;
+ case STATIC:
+ case EXTDEF:
+ p->soffset = getlab();
+#ifdef GCC_COMPAT
+ { extern char *renname;
+ if (renname)
+ gcc_rename(p, renname);
+ renname = NULL;
+ }
+#endif
+ break;
+
+ case EXTERN:
+ case UFORTRAN:
+ case FORTRAN:
+ p->soffset = getlab();
+#ifdef notdef
+ /* Cannot reset level here. What does the standard say??? */
+ p->slevel = 0;
+#endif
+#ifdef GCC_COMPAT
+ { extern char *renname;
+ if (renname)
+ gcc_rename(p, renname);
+ renname = NULL;
+ }
+#endif
+ break;
+ case MOU:
+ case MOS:
+ oalloc(p, &strucoff);
+ if (class == MOU)
+ strucoff = 0;
+ ssave(p);
+ break;
+
+ case MOE:
+ p->soffset = strucoff++;
+ ssave(p);
+ break;
+
+ }
+
+#ifdef STABS
+ if (gflag)
+ stabs_newsym(p);
+#endif
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf( " sdf, ssue, offset: %p, %p, %d\n",
+ p->sdf, p->ssue, p->soffset);
+#endif
+
+}
+
+void
+ssave(struct symtab *sym)
+{
+ struct params *p;
+
+ p = tmpalloc(sizeof(struct params));
+ p->next = NULL;
+ p->sym = sym;
+
+ if (lparam == NULL) {
+ p->prev = (struct params *)&lpole;
+ lpole = p;
+ } else {
+ lparam->next = p;
+ p->prev = lparam;
+ }
+ lparam = p;
+}
+
+/*
+ * end of function
+ */
+void
+ftnend()
+{
+ extern struct savbc *savbc;
+ extern struct swdef *swpole;
+ char *c;
+
+ if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
+ plabel(retlab);
+ efcode(); /* struct return handled here */
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+ SETOFF(maxautooff, ALCHAR);
+ send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c,
+ cftnsp->stype, cftnsp->sclass == EXTDEF, retlab);
+ }
+
+ tcheck();
+ brklab = contlab = retlab = NOLAB;
+ flostat = 0;
+ if (nerrors == 0) {
+ if (savbc != NULL)
+ cerror("bcsave error");
+ if (lparam != NULL)
+ cerror("parameter reset error");
+ if (swpole != NULL)
+ cerror("switch error");
+ }
+ savbc = NULL;
+ lparam = NULL;
+ maxautooff = autooff = AUTOINIT;
+ reached = 1;
+
+ if (isinlining)
+ inline_end();
+ inline_prtout();
+
+ strprint();
+
+ tmpfree(); /* Release memory resources */
+}
+
+void
+dclargs()
+{
+ union dimfun *df;
+ union arglist *al, *al2, *alb;
+ struct params *a;
+ struct symtab *p, **parr = NULL; /* XXX gcc */
+ char *c;
+ int i;
+
+ argoff = ARGINIT;
+
+ /*
+ * Deal with fun(void) properly.
+ */
+ if (nparams == 1 && lparam->sym->stype == VOID)
+ goto done;
+
+ /*
+ * Generate a list for bfcode().
+ * Parameters were pushed in reverse order.
+ */
+ if (nparams != 0)
+ parr = tmpalloc(sizeof(struct symtab *) * nparams);
+
+ if (nparams)
+ for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole;
+ a = a->prev) {
+
+ p = a->sym;
+ parr[i++] = p;
+ if (p->stype == FARG) {
+ p->stype = INT;
+ p->ssue = MKSUE(INT);
+ }
+ if (ISARY(p->stype)) {
+ p->stype += (PTR-ARY);
+ p->sdf++;
+ } else if (ISFTN(p->stype)) {
+ werror("function declared as argument");
+ p->stype = INCREF(p->stype);
+ }
+ /* always set aside space, even for register arguments */
+ oalloc(p, &argoff);
+#ifdef STABS
+ if (gflag)
+ stabs_newsym(p);
+#endif
+ }
+ if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
+ /*
+ * Check against prototype of oldstyle function.
+ */
+ alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
+ for (i = 0; i < nparams; i++) {
+ TWORD type = parr[i]->stype;
+ (al2++)->type = type;
+ if (ISSTR(BTYPE(type)))
+ (al2++)->sue = parr[i]->ssue;
+ while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
+ type = DECREF(type);
+ if (type > BTMASK)
+ (al2++)->df = parr[i]->sdf;
+ }
+ al2->type = TNULL;
+ intcompare = 1;
+ if (chkftn(al, alb))
+ uerror("function doesn't match prototype");
+ intcompare = 0;
+ }
+done: cendarg();
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+#if 0
+ prolab = getlab();
+ send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
+ cftnsp->sclass == EXTDEF, prolab);
+#endif
+ plabel(prolab); /* after prolog, used in optimization */
+ retlab = getlab();
+ bfcode(parr, nparams);
+ if (xtemps) {
+ /* put arguments in temporaries */
+ for (i = 0; i < nparams; i++) {
+ NODE *q, *r, *s;
+
+ p = parr[i];
+ if (p->stype == STRTY || p->stype == UNIONTY ||
+ cisreg(p->stype) == 0)
+ continue;
+ spname = p;
+ q = buildtree(NAME, 0, 0);
+ r = tempnode(0, p->stype, p->sdf, p->ssue);
+ s = buildtree(ASSIGN, r, q);
+ p->soffset = r->n_lval;
+ p->sflags |= STNODE;
+ ecomp(s);
+ }
+ plabel(getlab()); /* used when spilling */
+ }
+ lparam = NULL;
+ nparams = 0;
+}
+
+/*
+ * reference to a structure or union, with no definition
+ */
+NODE *
+rstruct(char *tag, int soru)
+{
+ struct symtab *p;
+ NODE *q;
+
+ p = (struct symtab *)lookup(tag, STAGNAME);
+ switch (p->stype) {
+
+ case UNDEF:
+ def:
+ q = block(NAME, NIL, NIL, 0, 0, 0);
+ q->n_sp = p;
+ q->n_type = (soru&INSTRUCT) ? STRTY :
+ ((soru&INUNION) ? UNIONTY : ENUMTY);
+ defid(q, (soru&INSTRUCT) ? STNAME :
+ ((soru&INUNION) ? UNAME : ENAME));
+ nfree(q);
+ break;
+
+ case STRTY:
+ if (soru & INSTRUCT)
+ break;
+ goto def;
+
+ case UNIONTY:
+ if (soru & INUNION)
+ break;
+ goto def;
+
+ case ENUMTY:
+ if (!(soru&(INUNION|INSTRUCT)))
+ break;
+ goto def;
+
+ }
+ q = mkty(p->stype, 0, p->ssue);
+ q->n_sue = p->ssue;
+ return q;
+}
+
+void
+moedef(char *name)
+{
+ NODE *q;
+
+ q = block(NAME, NIL, NIL, MOETY, 0, 0);
+ q->n_sp = lookup(name, 0);
+ defid(q, MOE);
+ nfree(q);
+}
+
+/*
+ * begining of structure or union declaration
+ */
+struct rstack *
+bstruct(char *name, int soru)
+{
+ struct rstack *r;
+ struct symtab *s;
+ NODE *q;
+
+ if (name != NULL)
+ s = lookup(name, STAGNAME);
+ else
+ s = NULL;
+
+ r = tmpalloc(sizeof(struct rstack));
+ r->rinstruct = instruct;
+ r->rclass = strunem;
+ r->rstrucoff = strucoff;
+
+ strucoff = 0;
+ instruct = soru;
+ q = block(NAME, NIL, NIL, 0, 0, 0);
+ q->n_sp = s;
+ if (instruct==INSTRUCT) {
+ strunem = MOS;
+ q->n_type = STRTY;
+ if (s != NULL)
+ defid(q, STNAME);
+ } else if(instruct == INUNION) {
+ strunem = MOU;
+ q->n_type = UNIONTY;
+ if (s != NULL)
+ defid(q, UNAME);
+ } else { /* enum */
+ strunem = MOE;
+ q->n_type = ENUMTY;
+ if (s != NULL)
+ defid(q, ENAME);
+ }
+ r->rsym = q->n_sp;
+ r->rlparam = lparam;
+ nfree(q);
+
+ return r;
+}
+
+/*
+ * Called after a struct is declared to restore the environment.
+ */
+NODE *
+dclstruct(struct rstack *r)
+{
+ NODE *n;
+ struct params *l, *m;
+ struct suedef *sue;
+ struct symtab *p;
+ int al, sa, sz;
+ TWORD temp;
+ int i, high, low;
+
+ if (r->rsym == NULL) {
+ sue = permalloc(sizeof(struct suedef));
+ suedefcnt++;
+ sue->suesize = 0;
+ sue->suealign = ALSTRUCT;
+ } else
+ sue = r->rsym->ssue;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??");
+#endif
+ temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
+ instruct = r->rinstruct;
+ strunem = r->rclass;
+ al = ALSTRUCT;
+
+ high = low = 0;
+
+ if ((l = r->rlparam) == NULL)
+ l = lpole;
+ else
+ l = l->next;
+
+ /* memory for the element array must be allocated first */
+ for (m = l, i = 1; m != NULL; m = m->next)
+ i++;
+ sue->suelem = permalloc(sizeof(struct symtab *) * i);
+
+ for (i = 0; l != NULL; l = l->next) {
+ sue->suelem[i++] = p = l->sym;
+
+ if (p == NULL)
+ cerror("gummy structure member");
+ if (temp == ENUMTY) {
+ if (p->soffset < low)
+ low = p->soffset;
+ if (p->soffset > high)
+ high = p->soffset;
+ p->ssue = sue;
+ continue;
+ }
+ sa = talign(p->stype, p->ssue);
+ if (p->sclass & FIELD) {
+ sz = p->sclass&FLDSIZ;
+ } else {
+ sz = tsize(p->stype, p->sdf, p->ssue);
+ }
+ if (sz > strucoff)
+ strucoff = sz; /* for use with unions */
+ /*
+ * set al, the alignment, to the lcm of the alignments
+ * of the members.
+ */
+ SETOFF(al, sa);
+ }
+ sue->suelem[i] = NULL;
+ SETOFF(strucoff, al);
+
+ if (temp == ENUMTY) {
+ TWORD ty;
+
+#ifdef ENUMSIZE
+ ty = ENUMSIZE(high,low);
+#else
+ if ((char)high == high && (char)low == low)
+ ty = ctype(CHAR);
+ else if ((short)high == high && (short)low == low)
+ ty = ctype(SHORT);
+ else
+ ty = ctype(INT);
+#endif
+ strucoff = tsize(ty, 0, MKSUE(ty));
+ sue->suealign = al = talign(ty, MKSUE(ty));
+ }
+
+ sue->suesize = strucoff;
+ sue->suealign = al;
+
+#ifdef STABS
+ if (gflag)
+ stabs_struct(r->rsym, sue);
+#endif
+
+#ifdef PCC_DEBUG
+ if (ddebug>1) {
+ int i;
+
+ printf("\tsize %d align %d elem %p\n",
+ sue->suesize, sue->suealign, sue->suelem);
+ for (i = 0; sue->suelem[i] != NULL; ++i) {
+ printf("\tmember %s(%p)\n",
+ sue->suelem[i]->sname, sue->suelem[i]);
+ }
+ }
+#endif
+
+ strucoff = r->rstrucoff;
+ if ((lparam = r->rlparam) != NULL)
+ lparam->next = NULL;
+ n = mkty(temp, 0, sue);
+ return n;
+}
+
+/*
+ * error printing routine in parser
+ */
+void yyerror(char *s);
+void
+yyerror(char *s)
+{
+ uerror(s);
+}
+
+void yyaccpt(void);
+void
+yyaccpt(void)
+{
+ ftnend();
+}
+
+/*
+ * p is top of type list given to tymerge later.
+ * Find correct CALL node and declare parameters from there.
+ */
+void
+ftnarg(NODE *p)
+{
+ NODE *q;
+ struct symtab *s;
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf("ftnarg(%p)\n", p);
+#endif
+ /*
+ * Enter argument onto param stack.
+ * Do not declare parameters until later (in dclargs);
+ * the function must be declared first.
+ * put it on the param stack in reverse order, due to the
+ * nature of the stack it will be reclaimed correct.
+ */
+ for (; p->n_op != NAME; p = p->n_left) {
+ if (p->n_op == (UCALL) && p->n_left->n_op == NAME)
+ return; /* Nothing to enter */
+ if (p->n_op == CALL && p->n_left->n_op == NAME)
+ break;
+ }
+
+ p = p->n_right;
+ blevel = 1;
+
+ while (p->n_op == CM) {
+ q = p->n_right;
+ if (q->n_op != ELLIPSIS) {
+ s = lookup((char *)q->n_sp, 0);
+ if (s->stype != UNDEF) {
+ if (s->slevel > 0)
+ uerror("parameter '%s' redefined",
+ s->sname);
+ s = hide(s);
+ }
+ s->soffset = NOOFFSET;
+ s->sclass = PARAM;
+ s->stype = q->n_type;
+ s->sdf = q->n_df;
+ s->ssue = q->n_sue;
+ ssave(s);
+ nparams++;
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf(" saving sym %s (%p) from (%p)\n",
+ s->sname, s, q);
+#endif
+ }
+ p = p->n_left;
+ }
+ s = lookup((char *)p->n_sp, 0);
+ if (s->stype != UNDEF) {
+ if (s->slevel > 0)
+ uerror("parameter '%s' redefined", s->sname);
+ s = hide(s);
+ }
+ s->soffset = NOOFFSET;
+ s->sclass = PARAM;
+ s->stype = p->n_type;
+ s->sdf = p->n_df;
+ s->ssue = p->n_sue;
+ ssave(s);
+ if (p->n_type != VOID)
+ nparams++;
+ blevel = 0;
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf(" saving sym %s (%p) from (%p)\n",
+ s->sname, s, p);
+#endif
+}
+
+/*
+ * compute the alignment of an object with type ty, sizeoff index s
+ */
+int
+talign(unsigned int ty, struct suedef *sue)
+{
+ int i;
+
+ if (ISPTR(ty))
+ return(ALPOINT); /* shortcut */
+
+ if(sue == NULL && ty!=INT && ty!=CHAR && ty!=SHORT &&
+ ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT) {
+ return(fldal(ty));
+ }
+
+ for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+ switch( (ty>>i)&TMASK ){
+
+ case FTN:
+ cerror("compiler takes alignment of function");
+ case PTR:
+ return(ALPOINT);
+ case ARY:
+ continue;
+ case 0:
+ break;
+ }
+ }
+
+ switch( BTYPE(ty) ){
+
+ case UNIONTY:
+ case ENUMTY:
+ case STRTY:
+ return((unsigned int)sue->suealign);
+ case BOOL:
+ return (ALBOOL);
+ case CHAR:
+ case UCHAR:
+ return (ALCHAR);
+ case FLOAT:
+ return (ALFLOAT);
+ case LDOUBLE:
+ return (ALLDOUBLE);
+ case DOUBLE:
+ return (ALDOUBLE);
+ case LONGLONG:
+ case ULONGLONG:
+ return (ALLONGLONG);
+ case LONG:
+ case ULONG:
+ return (ALLONG);
+ case SHORT:
+ case USHORT:
+ return (ALSHORT);
+ default:
+ return (ALINT);
+ }
+}
+
+/* compute the size associated with type ty,
+ * dimoff d, and sizoff s */
+/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
+OFFSZ
+tsize(TWORD ty, union dimfun *d, struct suedef *sue)
+{
+
+ int i;
+ OFFSZ mult, sz;
+
+ mult = 1;
+
+ for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+ switch( (ty>>i)&TMASK ){
+
+ case FTN:
+ uerror( "cannot take size of function");
+ case PTR:
+ return( SZPOINT(ty) * mult );
+ case ARY:
+ mult *= d->ddim;
+ d++;
+ continue;
+ case 0:
+ break;
+
+ }
+ }
+
+ if (sue == NULL)
+ cerror("bad tsize sue");
+ sz = sue->suesize;
+#ifdef GCC_COMPAT
+ if (ty == VOID)
+ sz = SZCHAR;
+#endif
+ if (ty != STRTY && ty != UNIONTY) {
+ if (sz == 0) {
+ uerror("unknown size");
+ return(SZINT);
+ }
+ } else {
+ if (sue->suelem == NULL)
+ uerror("unknown structure/union/enum");
+ }
+
+ return((unsigned int)sz * mult);
+}
+
+/*
+ * Write last part of wide string.
+ * Do not bother to save wide strings.
+ */
+NODE *
+wstrend(char *str)
+{
+ struct symtab *sp = getsymtab(str, SSTRING|STEMP);
+ struct strsched *sc = tmpalloc(sizeof(struct strsched));
+ NODE *p = block(NAME, NIL, NIL, WCHAR_TYPE+ARY,
+ tmpalloc(sizeof(union dimfun)), MKSUE(WCHAR_TYPE));
+ int i;
+ char *c;
+
+ sp->sclass = ILABEL;
+ sp->soffset = getlab();
+ sp->stype = WCHAR_TYPE+ARY;
+
+ sc = tmpalloc(sizeof(struct strsched));
+ sc->locctr = STRNG;
+ sc->sym = sp;
+ sc->next = strpole;
+ strpole = sc;
+
+ /* length calculation, used only for sizeof */
+ for (i = 0, c = str; *c; ) {
+ if (*c++ == '\\')
+ (void)esccon(&c);
+ i++;
+ }
+ p->n_df->ddim = (i+1) * ((MKSUE(WCHAR_TYPE))->suesize/SZCHAR);
+ p->n_sp = sp;
+ return(p);
+}
+
+/*
+ * Write last part of string.
+ */
+NODE *
+strend(char *str)
+{
+// extern int maystr;
+ struct symtab *s;
+ NODE *p;
+ int i;
+ char *c;
+
+ /* If an identical string is already emitted, just forget this one */
+ str = addstring(str); /* enter string in string table */
+ s = lookup(str, SSTRING); /* check for existance */
+
+ if (s->soffset == 0 /* && maystr == 0 */) { /* No string */
+ struct strsched *sc;
+ s->sclass = ILABEL;
+
+ /*
+ * Delay printout of this string until after the current
+ * function, or the end of the statement.
+ */
+ sc = tmpalloc(sizeof(struct strsched));
+ sc->locctr = STRNG;
+ sc->sym = s;
+ sc->next = strpole;
+ strpole = sc;
+ s->soffset = getlab();
+ }
+
+ p = block(NAME, NIL, NIL, CHAR+ARY,
+ tmpalloc(sizeof(union dimfun)), MKSUE(CHAR));
+#ifdef CHAR_UNSIGNED
+ p->n_type = UCHAR+ARY;
+#endif
+ /* length calculation, used only for sizeof */
+ for (i = 0, c = str; *c; ) {
+ if (*c++ == '\\')
+ (void)esccon(&c);
+ i++;
+ }
+ p->n_df->ddim = i+1;
+ p->n_sp = s;
+ return(p);
+}
+
+/*
+ * Print out new strings, before temp memory is cleared.
+ */
+void
+strprint()
+{
+ char *wr;
+ int i, val, isw;
+ NODE *p = bcon(0);
+
+ while (strpole != NULL) {
+ setloc1(STRNG);
+ deflab1(strpole->sym->soffset);
+ isw = strpole->sym->stype == WCHAR_TYPE+ARY;
+
+ i = 0;
+ wr = strpole->sym->sname;
+ while (*wr != 0) {
+ if (*wr++ == '\\')
+ val = esccon(&wr);
+ else
+ val = (unsigned char)wr[-1];
+ if (isw) {
+ p->n_lval = val;
+ p->n_type = WCHAR_TYPE;
+ ninval(i*(WCHAR_TYPE/SZCHAR),
+ (MKSUE(WCHAR_TYPE))->suesize, p);
+ } else
+ bycode(val, i);
+ i++;
+ }
+ if (isw) {
+ p->n_lval = 0;
+ ninval(i*(WCHAR_TYPE/SZCHAR),
+ (MKSUE(WCHAR_TYPE))->suesize, p);
+ } else {
+ bycode(0, i++);
+ bycode(-1, i);
+ }
+ strpole = strpole->next;
+ }
+ nfree(p);
+}
+
+#if 0
+/*
+ * simulate byte v appearing in a list of integer values
+ */
+void
+putbyte(int v)
+{
+ NODE *p;
+ p = bcon(v);
+ incode( p, SZCHAR );
+ tfree( p );
+// gotscal();
+}
+#endif
+
+/*
+ * update the offset pointed to by poff; return the
+ * offset of a value of size `size', alignment `alignment',
+ * given that off is increasing
+ */
+int
+upoff(int size, int alignment, int *poff)
+{
+ int off;
+
+ off = *poff;
+ SETOFF(off, alignment);
+ if (off < 0)
+ cerror("structure or stack overgrown"); /* wrapped */
+ *poff = off+size;
+ return (off);
+}
+
+/*
+ * allocate p with offset *poff, and update *poff
+ */
+int
+oalloc(struct symtab *p, int *poff )
+{
+ int al, off, tsz;
+ int noff;
+
+ /*
+ * Only generate tempnodes if we are optimizing,
+ * and only for integers, floats or pointers,
+ * and not if the basic type is volatile.
+ */
+/* XXX OLDSTYLE */
+ if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
+ (p->stype < STRTY || ISPTR(p->stype)) &&
+ !ISVOL((p->squal << TSHIFT)) && cisreg(p->stype)) {
+ NODE *tn = tempnode(0, p->stype, p->sdf, p->ssue);
+ p->soffset = tn->n_lval;
+ p->sflags |= STNODE;
+ nfree(tn);
+ return 0;
+ }
+
+ al = talign(p->stype, p->ssue);
+ noff = off = *poff;
+ tsz = tsize(p->stype, p->sdf, p->ssue);
+#ifdef BACKAUTO
+ if (p->sclass == AUTO) {
+ noff = off + tsz;
+ if (noff < 0)
+ cerror("stack overflow");
+ SETOFF(noff, al);
+ off = -noff;
+ } else
+#endif
+ if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
+ p->stype == SHORT || p->stype == USHORT)) {
+ off = upoff(SZINT, ALINT, &noff);
+#ifndef RTOLBYTES
+ off = noff - tsz;
+#endif
+ } else {
+ off = upoff(tsz, al, &noff);
+ }
+
+ if (p->sclass != REGISTER) {
+ /* in case we are allocating stack space for register arguments */
+ if (p->soffset == NOOFFSET)
+ p->soffset = off;
+ else if(off != p->soffset)
+ return(1);
+ }
+
+ *poff = noff;
+ return(0);
+}
+
+/*
+ * Allocate space on the stack for dynamic arrays.
+ * Strategy is as follows:
+ * - first entry is a pointer to the dynamic datatype.
+ * - if it's a one-dimensional array this will be the only entry used.
+ * - if it's a multi-dimensional array the following (numdim-1) integers
+ * will contain the sizes to multiply the indexes with.
+ * - code to write the dimension sizes this will be generated here.
+ * - code to allocate space on the stack will be generated here.
+ */
+static void
+dynalloc(struct symtab *p, int *poff)
+{
+ union dimfun *df;
+ NODE *n, *nn, *tn, *pol;
+ TWORD t;
+ int i, no;
+
+ /*
+ * The pointer to the array is stored in a TEMP node, which number
+ * is in the soffset field;
+ */
+ t = p->stype;
+ p->sflags |= (STNODE|SDYNARRAY);
+ p->stype = INCREF(p->stype); /* Make this an indirect pointer */
+ tn = tempnode(0, p->stype, p->sdf, p->ssue);
+ p->soffset = tn->n_lval;
+
+ df = p->sdf;
+
+ pol = NIL;
+ for (i = 0; ISARY(t); t = DECREF(t), df++) {
+ if (df->ddim >= 0)
+ continue;
+ n = arrstk[i++];
+ nn = tempnode(0, INT, 0, MKSUE(INT));
+ no = nn->n_lval;
+ ecomp(buildtree(ASSIGN, nn, n)); /* Save size */
+
+ df->ddim = -no;
+ n = tempnode(no, INT, 0, MKSUE(INT));
+ if (pol == NIL)
+ pol = n;
+ else
+ pol = buildtree(MUL, pol, n);
+ }
+ /* Create stack gap */
+ spalloc(tn, pol, tsize(t, 0, p->ssue));
+ arrstkp = 0;
+}
+
+/*
+ * allocate a field of width w
+ * new is 0 if new entry, 1 if redefinition, -1 if alignment
+ */
+int
+falloc(struct symtab *p, int w, int new, NODE *pty)
+{
+ int al,sz,type;
+
+ type = (new<0)? pty->n_type : p->stype;
+
+ /* this must be fixed to use the current type in alignments */
+ switch( new<0?pty->n_type:p->stype ){
+
+ case ENUMTY: {
+ struct suedef *sue;
+ sue = new < 0 ? pty->n_sue : p->ssue;
+ al = sue->suealign;
+ sz = sue->suesize;
+ break;
+ }
+
+ case CHAR:
+ case UCHAR:
+ al = ALCHAR;
+ sz = SZCHAR;
+ break;
+
+ case SHORT:
+ case USHORT:
+ al = ALSHORT;
+ sz = SZSHORT;
+ break;
+
+ case INT:
+ case UNSIGNED:
+ al = ALINT;
+ sz = SZINT;
+ break;
+
+ default:
+ if( new < 0 ) {
+ uerror( "illegal field type" );
+ al = ALINT;
+ } else
+ al = fldal( p->stype );
+ sz =SZINT;
+ }
+
+ if( w > sz ) {
+ uerror( "field too big");
+ w = sz;
+ }
+
+ if( w == 0 ){ /* align only */
+ SETOFF( strucoff, al );
+ if( new >= 0 ) uerror( "zero size field");
+ return(0);
+ }
+
+ if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+ if( new < 0 ) {
+ strucoff += w; /* we know it will fit */
+ return(0);
+ }
+
+ /* establish the field */
+
+ if( new == 1 ) { /* previous definition */
+ if( p->soffset != strucoff || p->sclass != (FIELD|w) ) return(1);
+ }
+ p->soffset = strucoff;
+ strucoff += w;
+ p->stype = type;
+ fldty( p );
+ return(0);
+}
+
+/*
+ * handle unitialized declarations assumed to be not functions:
+ * int a;
+ * extern int a;
+ * static int a;
+ */
+void
+nidcl(NODE *p, int class)
+{
+ struct symtab *sp;
+ int commflag = 0;
+
+ /* compute class */
+ if (class == SNULL) {
+ if (blevel > 1)
+ class = AUTO;
+ else if (blevel != 0 || instruct)
+ cerror( "nidcl error" );
+ else /* blevel = 0 */
+ commflag = 1, class = EXTERN;
+ }
+
+ defid(p, class);
+
+ sp = p->n_sp;
+ /* check if forward decl */
+ if (ISARY(sp->stype) && sp->sdf->ddim == 0)
+ return;
+
+ if (sp->sflags & SASG)
+ return; /* already initialized */
+
+ switch (class) {
+ case EXTDEF:
+ /* simulate initialization by 0 */
+ simpleinit(p->n_sp, bcon(0));
+ break;
+ case EXTERN:
+ if (commflag)
+ lcommadd(p->n_sp);
+ else
+ extdec(p->n_sp);
+ break;
+ case STATIC:
+ if (blevel == 0)
+ lcommadd(p->n_sp);
+ else
+ lcommdec(p->n_sp);
+ break;
+ }
+}
+
+struct lcd {
+ SLIST_ENTRY(lcd) next;
+ struct symtab *sp;
+};
+
+static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
+
+/*
+ * Add a local common statement to the printout list.
+ */
+void
+lcommadd(struct symtab *sp)
+{
+ struct lcd *lc, *lcp;
+
+ lcp = NULL;
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp == sp)
+ return; /* already exists */
+ if (lc->sp == NULL && lcp == NULL)
+ lcp = lc;
+ }
+ if (lcp == NULL) {
+ lc = permalloc(sizeof(struct lcd));
+ lc->sp = sp;
+ SLIST_INSERT_LAST(&lhead, lc, next);
+ } else
+ lcp->sp = sp;
+}
+
+/*
+ * Delete a local common statement.
+ */
+void
+lcommdel(struct symtab *sp)
+{
+ struct lcd *lc;
+
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp == sp) {
+ lc->sp = NULL;
+ return;
+ }
+ }
+}
+
+/*
+ * Print out the remaining common statements.
+ */
+void
+lcommprint(void)
+{
+ struct lcd *lc;
+
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp != NULL) {
+ if (lc->sp->sclass == STATIC)
+ lcommdec(lc->sp);
+ else
+ commdec(lc->sp);
+ }
+ }
+}
+
+/*
+ * Merges a type tree into one type. Returns one type node with merged types
+ * and class stored in the su field. Frees all other nodes.
+ * XXX - classes in typedefs?
+ */
+NODE *
+typenode(NODE *p)
+{
+ NODE *l, *sp = NULL;
+ int class = 0, adj, noun, sign;
+ TWORD qual = 0;
+
+ adj = INT; /* INT, LONG or SHORT */
+ noun = UNDEF; /* INT, CHAR or FLOAT */
+ sign = 0; /* 0, SIGNED or UNSIGNED */
+
+ /* Remove initial QUALIFIERs */
+ if (p && p->n_op == QUALIFIER) {
+ qual = p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ /* Handle initial classes special */
+ if (p && p->n_op == CLASS) {
+ class = p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ /* Remove more QUALIFIERs */
+ if (p && p->n_op == QUALIFIER) {
+ qual |= p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ag: if (p && p->n_op == TYPE) {
+ if (p->n_left == NIL) {
+#ifdef CHAR_UNSIGNED
+ if (p->n_type == CHAR)
+ p->n_type = UCHAR;
+#endif
+ if (p->n_type == SIGNED)
+ p->n_type = INT;
+uni: p->n_lval = class;
+ p->n_qual = qual >> TSHIFT;
+ return p;
+ } else if (p->n_left->n_op == QUALIFIER) {
+ qual |= p->n_left->n_type;
+ l = p->n_left;
+ p->n_left = l->n_left;
+ nfree(l);
+ goto ag;
+ } else if (ISSTR(p->n_type)) {
+ /* Save node; needed for return */
+ sp = p;
+ p = p->n_left;
+ }
+ }
+
+ while (p != NIL) {
+ if (p->n_op == QUALIFIER) {
+ qual |= p->n_type;
+ goto next;
+ }
+ if (p->n_op == CLASS) {
+ if (class != 0)
+ uerror("too many storage classes");
+ class = p->n_type;
+ goto next;
+ }
+ if (p->n_op != TYPE)
+ cerror("typenode got notype %d", p->n_op);
+ switch (p->n_type) {
+ case UCHAR:
+ case USHORT: /* may come from typedef */
+ if (sign != 0 || adj != INT)
+ goto bad;
+ noun = p->n_type;
+ break;
+ case SIGNED:
+ case UNSIGNED:
+ if (sign != 0)
+ goto bad;
+ sign = p->n_type;
+ break;
+ case LONG:
+ if (adj == LONG) {
+ adj = LONGLONG;
+ break;
+ }
+ /* FALLTHROUGH */
+ case SHORT:
+ if (adj != INT)
+ goto bad;
+ adj = p->n_type;
+ break;
+ case INT:
+ case CHAR:
+ case FLOAT:
+ case DOUBLE:
+ if (noun != UNDEF)
+ goto bad;
+ noun = p->n_type;
+ break;
+ case VOID:
+ if (noun != UNDEF || adj != INT)
+ goto bad;
+ adj = noun = VOID;
+ break;
+ case STRTY:
+ case UNIONTY:
+ break;
+ default:
+ goto bad;
+ }
+ next:
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ if (sp) {
+ p = sp;
+ goto uni;
+ }
+
+#ifdef CHAR_UNSIGNED
+ if (noun == CHAR && sign == 0)
+ sign = UNSIGNED;
+#endif
+ if (noun == UNDEF) {
+ noun = INT;
+ } else if (noun == FLOAT) {
+ if (sign != 0 || adj == SHORT)
+ goto bad;
+ noun = (adj == LONG ? DOUBLE : FLOAT);
+ } else if (noun == DOUBLE) {
+ if (sign != 0 || adj == SHORT)
+ goto bad;
+ noun = (adj == LONG ? LDOUBLE : DOUBLE);
+ } else if (noun == CHAR && adj != INT)
+ goto bad;
+
+ if (adj != INT && (noun != DOUBLE && noun != LDOUBLE))
+ noun = adj;
+ if (sign == UNSIGNED)
+ noun += (UNSIGNED-INT);
+
+ p = block(TYPE, NIL, NIL, noun, 0, 0);
+ p->n_qual = qual >> TSHIFT;
+ if (strunem != 0)
+ class = strunem;
+ p->n_lval = class;
+ return p;
+
+bad: uerror("illegal type combination");
+ return mkty(INT, 0, 0);
+}
+
+struct tylnk {
+ struct tylnk *next;
+ union dimfun df;
+};
+
+static void tyreduce(NODE *p, struct tylnk **, int *);
+
+static void
+tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
+{
+ (*tylkp)->next = tmpalloc(sizeof(struct tylnk));
+ *tylkp = (*tylkp)->next;
+ (*tylkp)->next = NULL;
+ (*tylkp)->df = dim;
+ (*ntdim)++;
+}
+
+/* merge type typ with identifier idp */
+NODE *
+tymerge(NODE *typ, NODE *idp)
+{
+ NODE *p;
+ union dimfun *j;
+ struct tylnk *base, tylnk, *tylkp;
+ unsigned int t;
+ int ntdim, i;
+
+ if (typ->n_op != TYPE)
+ cerror("tymerge: arg 1");
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2) {
+ printf("tymerge(%p,%p)\n", typ, idp);
+ fwalk(typ, eprint, 0);
+ fwalk(idp, eprint, 0);
+ }
+#endif
+
+ idp->n_type = typ->n_type;
+ idp->n_qual = (typ->n_qual << TSHIFT) | idp->n_qual; /* XXX ??? */
+
+ tylkp = &tylnk;
+ tylkp->next = NULL;
+ ntdim = 0;
+
+ tyreduce(idp, &tylkp, &ntdim);
+ idp->n_sue = typ->n_sue;
+
+ for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
+ if (ISARY(t) || ISFTN(t))
+ tylkadd(*j++, &tylkp, &ntdim);
+
+ if (ntdim) {
+ union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
+ dimfuncnt += ntdim;
+ for (i = 0, base = tylnk.next; base; base = base->next, i++)
+ a[i] = base->df;
+ idp->n_df = a;
+ } else
+ idp->n_df = NULL;
+
+ /* now idp is a single node: fix up type */
+
+ idp->n_type = ctype(idp->n_type);
+ idp->n_qual = DECQAL(idp->n_qual);
+
+ /* in case ctype has rewritten things */
+ if ((t = BTYPE(idp->n_type)) != STRTY && t != UNIONTY && t != ENUMTY)
+ idp->n_sue = MKSUE(t);
+
+ if (idp->n_op != NAME) {
+ for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
+ nfree(p);
+ nfree(p);
+ idp->n_op = NAME;
+ }
+
+ return(idp);
+}
+
+/*
+ * Retrieve all CM-separated argument types, sizes and dimensions and
+ * put them in an array.
+ * XXX - can only check first type level, side effects?
+ */
+static union arglist *
+arglist(NODE *n)
+{
+ union arglist *al;
+ NODE *w = n, **ap;
+ int num, cnt, i, j, k;
+ TWORD ty;
+
+#ifdef PCC_DEBUG
+ if (pdebug) {
+ printf("arglist %p\n", n);
+ fwalk(n, eprint, 0);
+ }
+#endif
+ /* First: how much to allocate */
+ for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
+ cnt++; /* Number of levels */
+ num++; /* At least one per step */
+ if (w->n_right->n_op == ELLIPSIS)
+ continue;
+ ty = w->n_right->n_type;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ num++;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ num++;
+ }
+ cnt++;
+ ty = w->n_type;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ num++;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ num++;
+ num += 2; /* TEND + last arg type */
+
+ /* Second: Create list to work on */
+ ap = tmpalloc(sizeof(NODE *) * cnt);
+ al = permalloc(sizeof(union arglist) * num);
+ arglistcnt += num;
+
+ for (w = n, i = 0; w->n_op == CM; w = w->n_left)
+ ap[i++] = w->n_right;
+ ap[i] = w;
+
+ /* Third: Create actual arg list */
+ for (k = 0, j = i; j >= 0; j--) {
+ if (ap[j]->n_op == ELLIPSIS) {
+ al[k++].type = TELLIPSIS;
+ ap[j]->n_op = ICON; /* for tfree() */
+ continue;
+ }
+ /* Convert arrays to pointers */
+ if (ISARY(ap[j]->n_type)) {
+ ap[j]->n_type += (PTR-ARY);
+ ap[j]->n_df++;
+ }
+ /* Convert (silently) functions to pointers */
+ if (ISFTN(ap[j]->n_type))
+ ap[j]->n_type = INCREF(ap[j]->n_type);
+ ty = ap[j]->n_type;
+ al[k++].type = ty;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ al[k++].sue = ap[j]->n_sue;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ al[k++].df = ap[j]->n_df;
+ }
+ al[k++].type = TNULL;
+ if (k > num)
+ cerror("arglist: k%d > num%d", k, num);
+ tfree(n);
+ if (pdebug)
+ alprint(al, 0);
+ return al;
+}
+
+/*
+ * build a type, and stash away dimensions,
+ * from a parse tree of the declaration
+ * the type is build top down, the dimensions bottom up
+ */
+void
+tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
+{
+ union dimfun dim;
+ NODE *r = NULL;
+ int o;
+ TWORD t, q;
+
+ o = p->n_op;
+ if (o == NAME)
+ return;
+
+ t = INCREF(p->n_type);
+ q = p->n_qual;
+ switch (o) {
+ case CALL:
+ t += (FTN-PTR);
+ dim.dfun = arglist(p->n_right);
+ break;
+ case UCALL:
+ t += (FTN-PTR);
+ dim.dfun = NULL;
+ break;
+ case LB:
+ t += (ARY-PTR);
+ if (p->n_right->n_op != ICON) {
+ r = p->n_right;
+ o = RB;
+ } else {
+ dim.ddim = p->n_right->n_lval;
+ nfree(p->n_right);
+#ifdef notdef
+ /* XXX - check dimensions at usage time */
+ if (dim.ddim == 0 && p->n_left->n_op == LB)
+ uerror("null dimension");
+#endif
+ }
+ break;
+ }
+
+ p->n_left->n_type = t;
+ p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
+ tyreduce(p->n_left, tylkp, ntdim);
+
+ if (o == LB || o == (UCALL) || o == CALL)
+ tylkadd(dim, tylkp, ntdim);
+ if (o == RB) {
+ dim.ddim = -1;
+ tylkadd(dim, tylkp, ntdim);
+ arrstk[arrstkp++] = r;
+ }
+
+ p->n_sp = p->n_left->n_sp;
+ p->n_type = p->n_left->n_type;
+ p->n_qual = p->n_left->n_qual;
+}
+
+static NODE *
+argcast(NODE *p, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ NODE *u, *r = talloc();
+
+ r->n_op = NAME;
+ r->n_type = t;
+ r->n_qual = 0; /* XXX */
+ r->n_df = d;
+ r->n_sue = sue;
+
+ u = buildtree(CAST, r, p);
+ nfree(u->n_left);
+ r = u->n_right;
+ nfree(u);
+ return r;
+}
+
+#ifndef NO_C_BUILTINS
+/*
+ * replace an alloca function with direct allocation on stack.
+ * return a destination temp node.
+ */
+static NODE *
+builtin_alloca(NODE *f, NODE *a)
+{
+ struct symtab *sp;
+ NODE *t, *u;
+
+#ifdef notyet
+ if (xnobuiltins)
+ return NULL;
+#endif
+
+ if (f->n_op != NAME)
+ return NULL; /* not direct call */
+ sp = f->n_sp;
+
+ /* XXX - strcmp is bad, use pointer comparision, redo someday */
+ if (strcmp(sp->sname, "__builtin_alloca")) /* use GCC name */
+ return NULL; /* not alloca */
+
+ if (a == NULL || a->n_op == CM) {
+ uerror("wrong arg count for alloca");
+ return NULL;
+ }
+ t = tempnode(0, VOID|PTR, 0, MKSUE(INT) /* XXX */);
+ u = tempnode(t->n_lval, VOID|PTR, 0, MKSUE(INT) /* XXX */);
+ spalloc(t, a, SZCHAR);
+ tfree(f);
+ return u;
+}
+#endif
+
+#ifdef PCC_DEBUG
+/*
+ * Print a prototype.
+ */
+static void
+alprint(union arglist *al, int in)
+{
+ int i = 0, j;
+
+ for (; al->type != TNULL; al++) {
+ for (j = in; j > 0; j--)
+ printf(" ");
+ printf("arg %d: ", i++);
+ tprint(stdout, al->type, 0);
+ if (BTYPE(al->type) == STRTY ||
+ BTYPE(al->type) == UNIONTY || BTYPE(al->type) == ENUMTY) {
+ al++;
+ printf("dim %d\n", al->df->ddim);
+ }
+ printf("\n");
+ if (ISFTN(DECREF(al->type))) {
+ al++;
+ alprint(al->df->dfun, in+1);
+ }
+ }
+ if (in == 0)
+ printf("end arglist\n");
+}
+#endif
+/*
+ * Do prototype checking and add conversions before calling a function.
+ * Argument f is function and a is a CM-separated list of arguments.
+ * Returns a merged node (via buildtree() of function and arguments.
+ */
+NODE *
+doacall(NODE *f, NODE *a)
+{
+ NODE *w, *r;
+ union arglist *al;
+ struct ap {
+ struct ap *next;
+ NODE *node;
+ } *at, *apole = NULL;
+ int argidx/* , hasarray = 0*/;
+ TWORD type, arrt;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf("doacall.\n");
+ fwalk(f, eprint, 0);
+ fwalk(a, eprint, 0);
+ }
+#endif
+
+ /* First let MD code do something */
+ calldec(f, a);
+/* XXX XXX hack */
+ if ((f->n_op == CALL || f->n_op == CALL) &&
+ f->n_left->n_op == ADDROF &&
+ f->n_left->n_left->n_op == NAME &&
+ (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
+ goto build;
+/* XXX XXX hack */
+
+#ifndef NO_C_BUILTINS
+ /* check for alloca */
+ if ((w = builtin_alloca(f, a)))
+ return w;
+#endif
+ /*
+ * Do some basic checks.
+ */
+ if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
+ if (Wimplicit_function_declaration) {
+ if (f->n_sp != NULL)
+ werror("no prototype for function '%s()'",
+ f->n_sp->sname);
+ else
+ werror("no prototype for function pointer");
+ }
+ /* floats must be cast to double */
+ if (a == NULL)
+ goto build;
+ for (w = a; w->n_op == CM; w = w->n_left) {
+ if (w->n_right->n_type != FLOAT)
+ continue;
+ w->n_right = argcast(w->n_right, DOUBLE,
+ NULL, MKSUE(DOUBLE));
+ }
+ if (a->n_type == FLOAT) {
+ MKTY(a, DOUBLE, 0, 0);
+ }
+ goto build;
+ }
+ if (al->type == VOID) {
+ if (a != NULL)
+ uerror("function takes no arguments");
+ goto build; /* void function */
+ } else {
+ if (a == NULL) {
+ uerror("function needs arguments");
+ goto build;
+ }
+ }
+#ifdef PCC_DEBUG
+ if (pdebug) {
+ printf("arglist for %p\n",
+ f->n_sp != NULL ? f->n_sp->sname : "function pointer");
+ alprint(al, 0);
+ }
+#endif
+
+ /*
+ * Create a list of pointers to the nodes given as arg.
+ */
+ for (w = a; w->n_op == CM; w = w->n_left) {
+ at = tmpalloc(sizeof(struct ap));
+ at->node = w->n_right;
+ at->next = apole;
+ apole = at;
+ }
+ at = tmpalloc(sizeof(struct ap));
+ at->node = w;
+ at->next = apole;
+ apole = at;
+
+ /*
+ * Do the typechecking by walking up the list.
+ */
+ argidx = 1;
+ while (al->type != TNULL) {
+ if (al->type == TELLIPSIS) {
+ /* convert the rest of float to double */
+ for (; apole; apole = apole->next) {
+ if (apole->node->n_type != FLOAT)
+ continue;
+ MKTY(apole->node, DOUBLE, 0, 0);
+ }
+ goto build;
+ }
+ if (apole == NULL) {
+ uerror("too few arguments to function");
+ goto build;
+ }
+/* al = prototyp, apole = argument till ftn */
+/* type = argumentets typ, arrt = prototypens typ */
+ type = apole->node->n_type;
+ arrt = al->type;
+#if 0
+ if ((hasarray = ISARY(arrt)))
+ arrt += (PTR-ARY);
+#endif
+ if (ISARY(type))
+ type += (PTR-ARY);
+
+ /* Check structs */
+ if (type <= BTMASK && arrt <= BTMASK) {
+ if (type != arrt) {
+ if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
+incomp: uerror("incompatible types for arg %d",
+ argidx);
+ } else {
+ MKTY(apole->node, arrt, 0, 0)
+ }
+ } else if (ISSOU(BTYPE(type))) {
+ if (apole->node->n_sue != al[1].sue)
+ goto incomp;
+ }
+ goto out;
+ }
+
+ /* Hereafter its only pointers (or arrays) left */
+ /* Check for struct/union intermixing with other types */
+ if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
+ ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
+ goto incomp;
+
+ /* Check for struct/union compatibility */
+ if (type == arrt) {
+ if (ISSOU(BTYPE(type))) {
+ if (apole->node->n_sue == al[1].sue)
+ goto out;
+ } else
+ goto out;
+ }
+ if (BTYPE(arrt) == ENUMTY && BTYPE(type) == INT &&
+ (arrt & ~BTMASK) == (type & ~BTMASK))
+ goto skip; /* XXX enumty destroyed in optim() */
+ if (BTYPE(arrt) == VOID && type > BTMASK)
+ goto skip; /* void *f = some pointer */
+ if (arrt > BTMASK && BTYPE(type) == VOID)
+ goto skip; /* some *f = void pointer */
+ if (apole->node->n_op == ICON && apole->node->n_lval == 0)
+ goto skip; /* Anything assigned a zero */
+
+ if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
+ /* do not complain for intermixed char/uchar */
+ if ((BTYPE(type) == CHAR || BTYPE(type) == UCHAR) &&
+ (BTYPE(arrt) == CHAR || BTYPE(arrt) == UCHAR))
+ goto skip;
+ }
+
+ werror("implicit conversion of argument %d due to prototype",
+ argidx);
+
+skip: if (ISSTR(BTYPE(arrt))) {
+ MKTY(apole->node, arrt, 0, al[1].sue)
+ } else {
+ MKTY(apole->node, arrt, 0, 0)
+ }
+
+out: al++;
+ if (ISSTR(BTYPE(arrt)))
+ al++;
+#if 0
+ while (arrt > BTMASK && !ISFTN(arrt))
+ arrt = DECREF(arrt);
+ if (ISFTN(arrt) || hasarray)
+ al++;
+#else
+ while (arrt > BTMASK) {
+ if (ISARY(arrt) || ISFTN(arrt)) {
+ al++;
+ break;
+ }
+ arrt = DECREF(arrt);
+ }
+#endif
+ apole = apole->next;
+ argidx++;
+ }
+ if (apole != NULL)
+ uerror("too many arguments to function");
+
+build: return buildtree(a == NIL ? UCALL : CALL, f, a);
+}
+
+static int
+chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
+{
+ while (type > BTMASK) {
+ switch (type & TMASK) {
+ case ARY:
+ /* may be declared without dimension */
+ if (dsym->ddim == 0)
+ dsym->ddim = ddef->ddim;
+ if (ddef->ddim && dsym->ddim != ddef->ddim)
+ return 1;
+ dsym++, ddef++;
+ break;
+ case FTN:
+ /* old-style function headers with function pointers
+ * will most likely not have a prototype.
+ * This is not considered an error. */
+ if (ddef->dfun == NULL) {
+#ifdef notyet
+ werror("declaration not a prototype");
+#endif
+ } else if (chkftn(dsym->dfun, ddef->dfun))
+ return 1;
+ dsym++, ddef++;
+ break;
+ }
+ type = DECREF(type);
+ }
+ return 0;
+}
+
+/*
+ * Compare two function argument lists to see if they match.
+ */
+int
+chkftn(union arglist *usym, union arglist *udef)
+{
+ TWORD t2;
+ int ty, tyn;
+
+ if (usym == NULL)
+ return 0;
+ if (cftnsp != NULL && udef == NULL && usym->type == VOID)
+ return 0; /* foo() { function with foo(void); prototype */
+ if (udef == NULL && usym->type != TNULL)
+ return 1;
+ while (usym->type != TNULL) {
+ if (usym->type == udef->type)
+ goto done;
+ /*
+ * If an old-style declaration, then all types smaller than
+ * int are given as int parameters.
+ */
+ if (intcompare) {
+ ty = BTYPE(usym->type);
+ tyn = BTYPE(udef->type);
+ if (ty == tyn || ty != INT)
+ return 1;
+ if (tyn == CHAR || tyn == UCHAR ||
+ tyn == SHORT || tyn == USHORT)
+ goto done;
+ return 1;
+ } else
+ return 1;
+
+done: ty = BTYPE(usym->type);
+ t2 = usym->type;
+ if (ISSTR(ty)) {
+ usym++, udef++;
+ if (usym->sue != udef->sue)
+ return 1;
+ }
+
+ while (ISFTN(t2) == 0 && ISARY(t2) == 0 && t2 > BTMASK)
+ t2 = DECREF(t2);
+ if (t2 > BTMASK) {
+ usym++, udef++;
+ if (chk2(t2, usym->df, udef->df))
+ return 1;
+ }
+ usym++, udef++;
+ }
+ if (usym->type != udef->type)
+ return 1;
+ return 0;
+}
+
+void
+fixtype(NODE *p, int class)
+{
+ unsigned int t, type;
+ int mod1, mod2;
+ /* fix up the types, and check for legality */
+
+ if( (type = p->n_type) == UNDEF ) return;
+ if ((mod2 = (type&TMASK))) {
+ t = DECREF(type);
+ while( mod1=mod2, mod2 = (t&TMASK) ){
+ if( mod1 == ARY && mod2 == FTN ){
+ uerror( "array of functions is illegal" );
+ type = 0;
+ }
+ else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
+ uerror( "function returns illegal type" );
+ type = 0;
+ }
+ t = DECREF(t);
+ }
+ }
+
+ /* detect function arguments, watching out for structure declarations */
+ if (instruct && ISFTN(type)) {
+ uerror("function illegal in structure or union");
+ type = INCREF(type);
+ }
+ p->n_type = type;
+}
+
+/*
+ * give undefined version of class
+ */
+int
+uclass(int class)
+{
+ if (class == SNULL)
+ return(EXTERN);
+ else if (class == STATIC)
+ return(USTATIC);
+ else if (class == FORTRAN)
+ return(UFORTRAN);
+ else
+ return(class);
+}
+
+int
+fixclass(int class, TWORD type)
+{
+ /* first, fix null class */
+ if (class == SNULL) {
+ if (instruct&INSTRUCT)
+ class = MOS;
+ else if (instruct&INUNION)
+ class = MOU;
+ else if (blevel == 0)
+ class = EXTDEF;
+ else
+ class = AUTO;
+ }
+
+ /* now, do general checking */
+
+ if( ISFTN( type ) ){
+ switch( class ) {
+ default:
+ uerror( "function has illegal storage class" );
+ case AUTO:
+ class = EXTERN;
+ case EXTERN:
+ case EXTDEF:
+ case FORTRAN:
+ case TYPEDEF:
+ case STATIC:
+ case UFORTRAN:
+ case USTATIC:
+ ;
+ }
+ }
+
+ if( class&FIELD ){
+ if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
+ return( class );
+ }
+
+ switch( class ){
+
+ case MOU:
+ if( !(instruct&INUNION) ) uerror( "illegal MOU class" );
+ return( class );
+
+ case MOS:
+ if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" );
+ return( class );
+
+ case MOE:
+ if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal MOE class" );
+ return( class );
+
+ case REGISTER:
+ if (blevel == 0)
+ uerror( "illegal register declaration" );
+ if (blevel == 1)
+ return(PARAM);
+ else
+ return(AUTO);
+
+ case AUTO:
+ if( blevel < 2 ) uerror( "illegal ULABEL class" );
+ return( class );
+
+ case UFORTRAN:
+ case FORTRAN:
+# ifdef NOFORTRAN
+ NOFORTRAN; /* a condition which can regulate the FORTRAN usage */
+# endif
+ if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
+ else {
+ type = DECREF(type);
+ if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
+ uerror( "fortran function has wrong type" );
+ }
+ }
+ case STNAME:
+ case UNAME:
+ case ENAME:
+ case EXTERN:
+ case STATIC:
+ case EXTDEF:
+ case TYPEDEF:
+ case USTATIC:
+ return( class );
+
+ default:
+ cerror( "illegal class: %d", class );
+ /* NOTREACHED */
+
+ }
+ return 0; /* XXX */
+}
+
+/*
+ * Generates a goto statement; sets up label number etc.
+ */
+void
+gotolabel(char *name)
+{
+ struct symtab *s = lookup(name, SLBLNAME);
+
+ if (s->soffset == 0)
+ s->soffset = -getlab();
+ branch(s->soffset < 0 ? -s->soffset : s->soffset);
+}
+
+/*
+ * Sets a label for gotos.
+ */
+void
+deflabel(char *name)
+{
+ struct symtab *s = lookup(name, SLBLNAME);
+
+ if (s->soffset > 0)
+ uerror("label '%s' redefined", name);
+ if (s->soffset == 0)
+ s->soffset = getlab();
+ if (s->soffset < 0)
+ s->soffset = -s->soffset;
+ plabel( s->soffset);
+}
+
+struct symtab *
+getsymtab(char *name, int flags)
+{
+ struct symtab *s;
+
+ if (flags & STEMP) {
+ s = tmpalloc(sizeof(struct symtab));
+ } else {
+ s = permalloc(sizeof(struct symtab));
+ symtabcnt++;
+ }
+ s->sname = name;
+ s->snext = NULL;
+ s->stype = UNDEF;
+ s->squal = 0;
+ s->sclass = SNULL;
+ s->sflags = flags & SMASK;
+ s->soffset = 0;
+ s->slevel = blevel;
+ return s;
+}
+
+#ifdef PCC_DEBUG
+static char *
+ccnames[] = { /* names of storage classes */
+ "SNULL",
+ "AUTO",
+ "EXTERN",
+ "STATIC",
+ "REGISTER",
+ "EXTDEF",
+ "LABEL",
+ "ULABEL",
+ "MOS",
+ "PARAM",
+ "STNAME",
+ "MOU",
+ "UNAME",
+ "TYPEDEF",
+ "FORTRAN",
+ "ENAME",
+ "MOE",
+ "UFORTRAN",
+ "USTATIC",
+ };
+
+char *
+scnames(int c)
+{
+ /* return the name for storage class c */
+ static char buf[12];
+ if( c&FIELD ){
+ snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
+ return( buf );
+ }
+ return( ccnames[c] );
+ }
+#endif
diff --git a/usr.bin/pcc/cc/ccom/scan.l b/usr.bin/pcc/cc/ccom/scan.l
new file mode 100644
index 00000000000..0a5470bb829
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/scan.l
@@ -0,0 +1,465 @@
+%{
+/* $Id: scan.l,v 1.1 2007/09/15 18:12:34 otto Exp $ */
+
+/*
+ * Copyright (c) 2002 Anders Magnusson. 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.
+ */
+%}
+
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+P [Pp][+-]?{D}+
+FS (f|F|l|L)
+IS (u|U|l|L)*
+
+%{
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "pass1.h"
+#include "cgram.h"
+
+static NODE *cvtdig(int radix);
+static NODE *charcon(void);
+static void control(int);
+static NODE *floatcon(void);
+static NODE *fhexcon(void);
+int notype, parbal;
+
+#define CPP_PRAGMA 1
+#define CPP_IDENT 2
+#define CPP_LINE 3
+#define CPP_HASH 4
+
+#ifdef STABS
+#define STABS_LINE(x) if (gflag && blevel) stabs_line(x)
+#else
+#define STABS_LINE(x)
+#endif
+#if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION >= 31
+/* Hack to avoid unneccessary warnings */
+FILE *yyget_in (void);
+FILE *yyget_out (void);
+int yyget_leng (void);
+char *yyget_text (void);
+void yyset_in (FILE * in_str );
+void yyset_out (FILE * out_str );
+int yyget_debug (void);
+void yyset_debug (int bdebug );
+int yylex_destroy (void);
+#endif
+
+%}
+
+%%
+
+"__func__" {
+ if (cftnsp == NULL)
+ uerror("__func__ outside function");
+ yylval.strp = cftnsp->sname; /* XXX - not C99 */
+ return(C_STRING);
+ }
+"asm" { return(C_ASM); }
+"auto" { yylval.intval = AUTO; return(C_CLASS); }
+"_Bool" { yylval.nodep = mkty((TWORD)BOOL, 0, MKSUE(BOOL));
+ return(C_TYPE); }
+"break" { return(C_BREAK); }
+"case" { return(C_CASE); }
+"char" { yylval.nodep = mkty((TWORD)CHAR, 0, MKSUE(CHAR));
+ notype=1; return(C_TYPE); }
+"const" { yylval.nodep =
+ block(QUALIFIER, NIL, NIL, CON, 0, 0);
+ return(C_QUALIFIER); }
+"continue" { return(C_CONTINUE); }
+"default" { return(C_DEFAULT); }
+"do" { return(C_DO); }
+"double" { yylval.nodep = mkty((TWORD)DOUBLE, 0, MKSUE(DOUBLE));
+ notype=1; return(C_TYPE); }
+"else" { return(C_ELSE); }
+"enum" { notype=1; return(C_ENUM); }
+"extern" { yylval.intval = EXTERN; return(C_CLASS); }
+"float" { yylval.nodep = mkty((TWORD)FLOAT, 0, MKSUE(FLOAT));
+ notype=1; return(C_TYPE); }
+"for" { return(C_FOR); }
+"goto" { return(C_GOTO); }
+"if" { return(C_IF); }
+"inline" { return(C_FUNSPEC); }
+"int" { yylval.nodep = mkty((TWORD)INT, 0, MKSUE(INT));
+ notype=1; return(C_TYPE); }
+"long" { yylval.nodep = mkty((TWORD)LONG, 0, MKSUE(LONG));
+ notype=1; return(C_TYPE); }
+"register" { yylval.intval = REGISTER; return(C_CLASS); }
+"restrict" { ; /* just ignore */ }
+"return" { return(C_RETURN); }
+"short" { yylval.nodep = mkty((TWORD)SHORT, 0, MKSUE(SHORT));
+ notype=1; return(C_TYPE); }
+"signed" { yylval.nodep = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
+ notype=1; return(C_TYPE); }
+"sizeof" { return(C_SIZEOF); }
+"static" { yylval.intval = STATIC; return(C_CLASS); }
+"struct" { yylval.intval = INSTRUCT; notype=1; return(C_STRUCT); }
+"switch" { return(C_SWITCH); }
+"typedef" { yylval.intval = TYPEDEF; return(C_CLASS); }
+"union" { yylval.intval = INUNION; notype=1; return(C_STRUCT); }
+"unsigned" { yylval.nodep = mkty((TWORD)UNSIGNED, 0, MKSUE(UNSIGNED));
+ notype=1; return(C_TYPE); }
+"void" { yylval.nodep = mkty((TWORD)VOID, 0, MKSUE(VOID));
+ notype=1; return(C_TYPE); }
+"volatile" { yylval.nodep =
+ block(QUALIFIER, NIL, NIL, VOL, 0, 0);
+ return(C_QUALIFIER); }
+"while" { return(C_WHILE); }
+
+{L}({L}|{D})* { struct symtab *s;
+ int i;
+
+ yylval.strp = addname(yytext);
+ if ((i = gcc_keyword(yylval.strp,
+ &yylval.nodep)) != 0)
+ return i;
+// printf("str: %s notype %d parbal %d\n", yytext, notype, parbal);
+ if (!notype) {
+ s = lookup(yylval.strp, SNOCREAT);
+ if (s && s->sclass == TYPEDEF)
+ return notype=1, C_TYPENAME;
+ }
+ return(C_NAME);
+ }
+
+0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
+0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
+{D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); }
+L?'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); }
+
+{D}+{E}{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+
+L?\"(\\.|[^\\"])*\" {
+ char *c = yytext;
+ int i = yyleng-2, rv;
+
+ if (*c++ == 'L') {
+ c++, i--;
+ rv = C_WSTRING;
+ } else
+ rv = C_STRING;
+ c[i] = 0; /* last " */
+ yylval.strp = c;
+ return rv;
+ }
+"..." { return(C_ELLIPSIS); }
+">>=" { yylval.intval = RSEQ; return(C_ASOP); }
+"<<=" { yylval.intval = LSEQ; return(C_ASOP); }
+"+=" { yylval.intval = PLUSEQ; return(C_ASOP); }
+"-=" { yylval.intval = MINUSEQ; return(C_ASOP); }
+"*=" { yylval.intval = MULEQ; return(C_ASOP); }
+"/=" { yylval.intval = DIVEQ; return(C_ASOP); }
+"%=" { yylval.intval = MODEQ; return(C_ASOP); }
+"&=" { yylval.intval = ANDEQ; return(C_ASOP); }
+"^=" { yylval.intval = EREQ; return(C_ASOP); }
+"|=" { yylval.intval = OREQ; return(C_ASOP); }
+">>" { yylval.intval = RS; return(C_SHIFTOP); }
+"<<" { yylval.intval = LS; return(C_SHIFTOP); }
+"++" { yylval.intval = INCR; return(C_INCOP); }
+"--" { yylval.intval = DECR; return(C_INCOP); }
+"->" { yylval.intval = STREF; return(C_STROP); }
+"&&" { yylval.intval = ANDAND; return(C_ANDAND); }
+"||" { yylval.intval = OROR; return(C_OROR); }
+"<=" { yylval.intval = LE; return(C_RELOP); }
+">=" { yylval.intval = GE; return(C_RELOP); }
+"==" { yylval.intval = EQ; return(C_EQUOP); }
+"!=" { yylval.intval = NE; return(C_EQUOP); }
+";" { notype = 0; return(';'); }
+("{"|"<%") { notype = 0; return('{'); }
+("}"|"%>") { return('}'); }
+"," { if (parbal) notype = 0; return(','); }
+":" { return(':'); }
+"=" { return('='); }
+"(" { parbal++; notype = 0; return('('); }
+")" { parbal--; if (parbal==0) { notype = 0; } return(')'); }
+("["|"<:") { return('['); }
+("]"|":>") { return(']'); }
+"." { yylval.intval = DOT; return(C_STROP); }
+"&" { return('&'); }
+"!" { yylval.intval = NOT; return(C_UNOP); }
+"~" { yylval.intval = COMPL; return(C_UNOP); }
+"-" { return('-'); }
+"+" { return('+'); }
+"*" { return('*'); }
+"/" { yylval.intval = DIV; return(C_DIVOP); }
+"%" { yylval.intval = MOD; return(C_DIVOP); }
+"<" { yylval.intval = LT; return(C_RELOP); }
+">" { yylval.intval = GT; return(C_RELOP); }
+"^" { return('^'); }
+"|" { return('|'); }
+"?" { return('?'); }
+^#pragma[ \t].* { control(CPP_PRAGMA); }
+^#ident[ \t].* { control(CPP_IDENT); }
+^#line[ \t].* { control(CPP_LINE); }
+^#.* { control(CPP_HASH); }
+
+[ \t\v\f] { }
+"\n" { ++lineno; STABS_LINE(lineno); }
+. { /* ignore bad characters */ }
+
+%%
+
+int lineno;
+char *ftitle = "<stdin>";
+
+int
+yywrap(void)
+{
+ if (0) unput(0); /* quiet gcc */
+ return(1);
+}
+
+/*
+ * XXX floatcon() and fhexcon() should be in support libraries for
+ * the target floating point.
+ */
+static NODE *
+f2(char *str)
+{
+ TWORD tw;
+ NODE *p;
+ double dc;
+ char *eptr;
+
+ dc = strtod(str, &eptr); /* XXX - avoid strtod() */
+ tw = (*eptr == 'f' || *eptr == 'F' ? FLOAT : DOUBLE);
+ p = block(FCON, NIL, NIL, tw, 0, MKSUE(tw));
+ p->n_dcon = dc;
+ return p;
+}
+
+NODE *
+floatcon(void)
+{
+ return f2(yytext);
+}
+
+static int
+h2n(int ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ return ch - 'A' + 10;
+
+}
+
+NODE *
+fhexcon(void)
+{
+ char buf[500];
+ char *c = yytext;
+ unsigned long long num1, num2;
+
+ /* XXX - convert it to a decimal float number and use strtod */
+ c+= 2; /* skip 0x */
+ for (num1 = 0; *c != '.' && *c != 'p' && *c != 'P'; c++)
+ num1 = (num1 << 4) | h2n(*c);
+ if (*c != '.' && *c != 'p' && *c != 'P')
+ cerror("fhexcon");
+ num2 = 0;
+ if (*c == '.') {
+ c++;
+ for (; *c != 'p' && *c != 'P'; c++)
+ num2 = (num2 << 4) | h2n(*c);
+ }
+ if (*c != 'P' && *c != 'p')
+ cerror("fhexcon2");
+ c++;
+ snprintf(buf, sizeof(buf), "%llu.%lluE%s", num1, num2, c);
+ return f2(buf);
+}
+
+unsigned int
+esccon(char **sptr)
+{
+ char *wr = *sptr;
+ unsigned int val;
+
+ switch (*wr++) {
+ case 'a': val = '\a'; break;
+ case 'b': val = '\b'; break;
+ case 'f': val = '\f'; break;
+ case 'n': val = '\n'; break;
+ case 'r': val = '\r'; break;
+ case 't': val = '\t'; break;
+ case 'v': val = '\v'; break;
+ case '\"': val = '\"'; break;
+ case 'x': val = strtoul(wr, &wr, 16); break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ wr--;
+ val = strtoul(wr, &wr, 8);
+ break;
+ default: val = wr[-1];
+ }
+ *sptr = wr;
+ return val;
+}
+
+NODE *
+cvtdig(int radix)
+{
+ NODE *p;
+ TWORD ntype;
+ unsigned long long v;
+ char *ch = yytext;
+ int n, numl, numu;
+
+ if (radix == 16)
+ ch += 2; /* Skip 0x */
+
+ v = 0;
+ while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') ||
+ (*ch >= 'A' && *ch <= 'F')) {
+ v *= radix;
+ n = *ch;
+ n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10);
+ ch++;
+ v += n;
+ }
+ /* Parse trailing chars */
+ ntype = INT;
+ numl = numu = 0;
+ for (n = 0; n < 3; n++) {
+ if (*ch == 0)
+ break;
+ if ((*ch == 'l' || *ch == 'L') && numl < 2)
+ ntype+=2, numl++;
+ else if ((*ch == 'u' || *ch == 'U') && numu < 1)
+ ntype = ENUNSIGN(ntype), numu++;
+ else
+ break;
+ ch++;
+ }
+ if (*ch)
+ uerror("constant has too many '%c'", *ch);
+
+ if (ntype == INT) {
+ /* v contains a number. Get type correct */
+ if (v > MAX_LONGLONG && radix != 10)
+ ntype = ULONGLONG;
+ else if (v > MAX_ULONG)
+ ntype = LONGLONG;
+ else if (v > MAX_LONG && radix != 10)
+ ntype = ULONG;
+ else if (v > MAX_UNSIGNED)
+ ntype = LONG;
+ else if (v > MAX_INT && radix != 10)
+ ntype = UNSIGNED;
+ }
+ ntype = ctype(ntype);
+ p = block(ICON, NIL, NIL, ntype, 0, MKSUE(ntype));
+ p->n_lval = v;
+ ASGLVAL(p->n_slval, v);
+
+ return p;
+}
+
+/*
+ * Convert a character constant to an integer.
+ */
+NODE *
+charcon(void)
+{
+ int lastcon = 0;
+ int val, i = 0;
+ char *pp = yytext;
+
+ if (*pp == 'L')
+ pp++;
+ pp++;
+ while (*pp != '\'') {
+ if (*pp++ == '\\') {
+ val = esccon(&pp);
+ } else
+ val = pp[-1];
+ makecc(val, i);
+ i++;
+ }
+
+ if (i == 0)
+ uerror("empty character constant");
+ if (i > (SZINT/SZCHAR) || (i>1))
+ werror("too many characters in character constant");
+ return bcon(lastcon);
+}
+
+void
+control(int t)
+{
+ char *wr = yytext;
+ char *eptr;
+ int val;
+
+ wr++; /* Skip initial '#' */
+ switch (t) {
+ case CPP_PRAGMA:
+ case CPP_IDENT:
+ return; /* Just skip these for now. */
+
+ case CPP_LINE:
+ wr += 4;
+ /* FALLTHROUGH */
+ case CPP_HASH:
+ val = strtol(wr, &eptr, 10);
+ if (wr == eptr) /* Illegal string */
+ goto bad;
+ wr = eptr;
+ lineno = val - 1;
+ while (*wr && *wr != '\"')
+ wr++;
+ if (*wr++ != '\"')
+ goto bad;
+ eptr = wr;
+ while (*wr && *wr != '\"')
+ wr++;
+ if (*wr != '\"')
+ goto bad;
+ *wr = 0;
+ ftitle = addstring(eptr);
+#ifdef STABS
+ if (gflag)
+ stabs_file(ftitle);
+#endif
+ }
+ return;
+bad:
+ werror("%s: illegal control", yytext);
+}
diff --git a/usr.bin/pcc/cc/ccom/stabs.c b/usr.bin/pcc/cc/ccom/stabs.c
new file mode 100644
index 00000000000..122da85d3f3
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/stabs.c
@@ -0,0 +1,374 @@
+/* $Id: stabs.c,v 1.1 2007/09/15 18:12:34 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Simple implementation of the "stabs" debugging format.
+ * Not complete but at least makes it possible to set breakpoints,
+ * examine simple variables and do stack traces.
+ * Based on the stabs documentation that follows gdb.
+ */
+
+#include "pass1.h"
+
+#ifdef STABS
+
+#include <sys/types.h>
+#include <stab.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define STABHASH 256
+#define INTNUM 1 /* internal number of type "int" */
+#define BIT2BYTE(x) ((x)/SZCHAR)
+
+#ifndef STABLBL
+#error macdefs.h must define STABLBL
+#endif
+
+/*
+ * Local type mapping
+ * Types are defined as a typeword, a dimension pointer (in the case
+ * of arrays) and struct/union/enum declarations.
+ * Function prototypes are ignored.
+ */
+static struct stabtype {
+ struct stabtype *next; /* linked list */
+ TWORD type; /* pcc type number */
+ union dimfun *df; /* dimension of arrays */
+ struct suedef *sue; /* struct/union/enum declarations */
+ int num; /* local type number */
+} *stabhash[STABHASH];
+static int ntypes;
+static char *curfun;
+static int stablbl = 10;
+
+void ptype(char *name, int num, int inhnum, long long min, long long max);
+struct stabtype *addtype(TWORD, union dimfun *, struct suedef *);
+struct stabtype *findtype(TWORD t, union dimfun *df, struct suedef *sue);
+void printtype(struct symtab *s, char *str, int len);
+void cprint(int p2, char *fmt, ...);
+
+#define MAXPSTR 100
+
+extern int isinlining;
+#define savestabs isinlining
+
+/*
+ * Output type definitions for the stab debugging format.
+ * Note that "int" is always internal number 1.
+ */
+void
+stabs_init()
+{
+ struct stabtype *st;
+
+#define ADDTYPE(y) addtype(y, NULL, MKSUE(y))
+
+ ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT);
+
+ st = ADDTYPE(CHAR);
+ ptype("char", st->num, st->num, 0, MAX_CHAR);
+ ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT);
+ ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG);
+ ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM,
+ MIN_LONGLONG, MAX_LONGLONG);
+ ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR);
+ ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT);
+ ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED);
+ ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG);
+ ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM,
+ 0, MAX_ULONGLONG);
+
+ ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0);
+ ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
+ ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
+ st = ADDTYPE(VOID);
+ cprint(savestabs, ".stabs \"void:t%d=r%d\",%d,0,0,0\n",
+ st->num, st->num, N_LSYM);
+
+}
+
+/*
+ * Print a type in stabs format
+ */
+void
+ptype(char *name, int num, int inhnum, long long min, long long max)
+{
+ cprint(savestabs, ".stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0",
+ name, num, inhnum, min, max, N_LSYM);
+}
+
+/*
+ * Add a new local type to the hash table.
+ * The search key is the (type, df, sue) triple.
+ */
+struct stabtype *
+addtype(TWORD t, union dimfun *df, struct suedef *sue)
+{
+ struct stabtype *st;
+
+ st = permalloc(sizeof(struct stabtype));
+ st->type = t;
+ st->df = df;
+ st->sue = sue;
+ st->num = ++ntypes;
+ st->next = stabhash[t & (STABHASH-1)];
+ stabhash[t & (STABHASH-1)] = st;
+ return st;
+}
+
+/*
+ * Search for a given type and return a type pointer (or NULL).
+ */
+struct stabtype *
+findtype(TWORD t, union dimfun *df, struct suedef *sue)
+{
+ struct stabtype *st;
+ union dimfun *dw, *dx;
+ TWORD tw;
+
+ st = stabhash[t & (STABHASH-1)];
+ for (; st; st = st->next) {
+ if (t != st->type || sue != st->sue)
+ continue;
+ /* Ok, type and sue matches, check dimensions */
+ if (st->df == NULL)
+ return st; /* no arrays, got match */
+ dw = st->df;
+ dx = df;
+ tw = t;
+ for (; tw > BTMASK; tw = DECREF(tw)) {
+ if (ISARY(tw)) {
+ if (dw->ddim == dx->ddim)
+ dw++, dx++;
+ else
+ break;
+ }
+ }
+ if (tw <= BTMASK)
+ return st;
+ }
+ return NULL;
+}
+
+/*
+ * Print current line number.
+ */
+void
+stabs_line(int line)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * Start of block.
+ */
+void
+stabs_lbrac(int blklvl)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s",
+ N_LBRAC, blklvl, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * End of block.
+ */
+void
+stabs_rbrac(int blklvl)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n",
+ N_RBRAC, blklvl, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * Print current file and set mark.
+ */
+void
+stabs_file(char *fname)
+{
+ static char *mainfile;
+
+ if (mainfile == NULL)
+ mainfile = fname; /* first call */
+ cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL,
+ fname, fname == mainfile ? N_SO : N_SOL, stablbl);
+ cprint(savestabs, STABLBL ":", stablbl++);
+}
+
+/*
+ * Print beginning of function.
+ */
+void
+stabs_func(struct symtab *s)
+{
+ char str[MAXPSTR];
+
+ curfun = s->sname;
+#ifdef GCC_COMPAT
+ curfun = gcc_findname(cftnsp);
+#endif
+ printtype(s, str, sizeof(str));
+ cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s",
+ curfun, s->sclass == STATIC ? 'f' : 'F', str,
+ N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun));
+}
+
+/*
+ * Print a (complex) type.
+ * Will also create subtypes.
+ * Printed string is like "20=*21=*1".
+ */
+void
+printtype(struct symtab *s, char *ostr, int len)
+{
+ struct stabtype *st;
+ union dimfun *df = s->sdf;
+ struct suedef *sue = s->ssue;
+ TWORD t = s->stype;
+ int op = 0;
+
+ /* Print out not-yet-found types */
+ if (ISFTN(t))
+ t = DECREF(t);
+ st = findtype(t, df, sue);
+ while (st == NULL && t > BTMASK) {
+ st = addtype(t, df, sue);
+ op+=snprintf(ostr+op, len - op, "%d=", st->num);
+ if (ISFTN(t))
+ ostr[op++] = 'f';
+ else if (ISPTR(t))
+ ostr[op++] = '*';
+ else if (ISARY(t)) {
+ op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1);
+ } else
+ cerror("printtype: notype");
+ if (ISARY(t))
+ df++;
+ t = DECREF(t);
+ st = findtype(t, df, sue);
+ if (op > MAXPSTR-10)
+ cerror("printtype: too difficult expression");
+ }
+ /* print out basic type. may have to be entered in case of sue */
+ snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num);
+ /* snprintf here null-terminated the string */
+}
+
+void
+stabs_newsym(struct symtab *s)
+{
+ char *sname;
+ char ostr[MAXPSTR];
+
+ if (ISFTN(s->stype))
+ return; /* functions are handled separate */
+
+ if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS ||
+ s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE ||
+ s->sclass == TYPEDEF || (s->sclass & FIELD))
+ return; /* XXX - fix structs */
+
+ sname = s->sname;
+#ifdef GCC_COMPAT
+ sname = gcc_findname(s);
+#endif
+
+ printtype(s, ostr, sizeof(ostr));
+ switch (s->sclass) {
+ case PARAM:
+ cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr,
+ N_PSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ break;
+
+ case AUTO:
+ cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr,
+ N_LSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ break;
+
+ case STATIC:
+ if (blevel)
+ cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr,
+ N_LCSYM, BIT2BYTE(s->ssue->suesize), s->soffset);
+ else
+ cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr,
+ N_LCSYM, BIT2BYTE(s->ssue->suesize), exname(sname));
+ break;
+
+ case EXTERN:
+ case EXTDEF:
+ cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr,
+ N_GSYM, BIT2BYTE(s->ssue->suesize));
+ break;
+
+ case REGISTER:
+ cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr,
+ N_RSYM, 1, s->soffset);
+ break;
+
+ default:
+ cerror("fix stab_newsym; class %d", s->sclass);
+ }
+}
+
+void
+stabs_chgsym(struct symtab *s)
+{
+}
+
+/*
+ * define a struct.
+ */
+void
+stabs_struct(struct symtab *p, struct suedef *sue)
+{
+}
+
+void
+cprint(int p2, char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+
+ va_start(ap, fmt);
+ if (p2) {
+ str = tmpvsprintf(fmt, ap);
+ str = newstring(str, strlen(str)); /* XXX - for inlines */
+ send_passt(IP_ASM, str);
+ } else {
+ putchar('\t');
+ vprintf(fmt, ap);
+ putchar('\n');
+ }
+ va_end(ap);
+}
+
+#endif
diff --git a/usr.bin/pcc/cc/ccom/symtabs.c b/usr.bin/pcc/cc/ccom/symtabs.c
new file mode 100644
index 00000000000..1f96d5dc86a
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/symtabs.c
@@ -0,0 +1,356 @@
+/* $Id: symtabs.c,v 1.1 2007/09/15 18:12:35 otto Exp $ */
+/*
+ * 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"
+
+/*
+ * These definitions are used in the patricia tree that stores
+ * the strings.
+ */
+#define LEFT_IS_LEAF 0x80000000
+#define RIGHT_IS_LEAF 0x40000000
+#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
+#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
+#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
+#define CHECKBITS 8
+
+struct tree {
+ int bitno;
+ struct tree *lr[2];
+};
+
+static struct tree *firstname;
+int nametabs, namestrlen;
+static struct tree *firststr;
+int strtabs, strstrlen;
+static char *symtab_add(char *key, struct tree **, int *, int *);
+
+#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
+#define getree() permalloc(sizeof(struct tree))
+
+char *
+addname(char *key)
+{
+ return symtab_add(key, &firstname, &nametabs, &namestrlen);
+}
+
+char *
+addstring(char *key)
+{
+ return symtab_add(key, &firststr, &strtabs, &strstrlen);
+}
+
+/*
+ * Add a name to the name stack (if its non-existing),
+ * return its address.
+ * This is a simple patricia implementation.
+ */
+char *
+symtab_add(char *key, struct tree **first, int *tabs, int *stlen)
+{
+ struct tree *w, *new, *last;
+ int cix, bit, fbit, svbit, ix, bitno, len;
+ char *m, *k, *sm;
+
+ /* Count full string length */
+ for (k = key, len = 0; *k; k++, len++)
+ ;
+
+ switch (*tabs) {
+ case 0:
+ *first = (struct tree *)newstring(key, len);
+ *stlen += (len + 1);
+ (*tabs)++;
+ return (char *)*first;
+
+ case 1:
+ m = (char *)*first;
+ svbit = 0; /* XXX why? */
+ break;
+
+ default:
+ w = *first;
+ bitno = len * CHECKBITS;
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = bit > bitno ? 0 : P_BIT(key, bit);
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit) {
+ m = (char *)w;
+ break;
+ }
+ }
+ }
+
+ sm = m;
+ k = key;
+
+ /* Check for correct string and return */
+ for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
+ ;
+ if (*m == 0 && *k == 0)
+ return sm;
+
+ ix = *m ^ *k;
+ while ((ix & 1) == 0)
+ ix >>= 1, cix++;
+
+ /* Create new node */
+ new = getree();
+ bit = P_BIT(key, cix);
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)newstring(key, len);
+ *stlen += (len + 1);
+
+ if ((*tabs)++ == 1) {
+ new->lr[!bit] = *first;
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ *first = new;
+ return (char *)new->lr[bit];
+ }
+
+
+ w = *first;
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ cerror("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = P_BIT(key, bitno);
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ *first = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (char *)new->lr[bit];
+}
+
+static struct tree *sympole[NSTYPES];
+static struct symtab *tmpsyms[NSTYPES];
+int numsyms[NSTYPES];
+
+/*
+ * Inserts a symbol into the symbol tree.
+ * Returns a struct symtab.
+ */
+struct symtab *
+lookup(char *key, int ttype)
+{
+ struct symtab *sym;
+ struct tree *w, *new, *last;
+ int cix, bit, fbit, svbit, ix, bitno, match;
+ int type, uselvl;
+
+ long code = (long)key;
+ type = ttype & SMASK;
+ uselvl = (blevel > 0 && type != SSTRING);
+
+ /*
+ * The local symbols are kept in a simple linked list.
+ * Check this list first.
+ */
+ if (blevel > 0)
+ for (sym = tmpsyms[type]; sym; sym = sym->snext)
+ if (sym->sname == key)
+ return sym;
+
+ switch (numsyms[type]) {
+ case 0:
+ if (ttype & SNOCREAT)
+ return NULL;
+ if (uselvl) {
+ sym = getsymtab(key, ttype|STEMP);
+ sym->snext = tmpsyms[type];
+ tmpsyms[type] = sym;
+ return sym;
+ }
+ sympole[type] = (struct tree *)getsymtab(key, ttype);
+ numsyms[type]++;
+ return (struct symtab *)sympole[type];
+
+ case 1:
+ w = (struct tree *)sympole[type];
+ svbit = 0; /* XXX why? */
+ break;
+
+ default:
+ w = sympole[type];
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = (code >> bit) & 1;
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit)
+ break;
+ }
+ }
+
+ sym = (struct symtab *)w;
+ match = (long)sym->sname;
+
+ ix = code ^ match;
+ if (ix == 0)
+ return sym;
+ else if (ttype & SNOCREAT)
+ return NULL;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf(" adding %s as %s at level %d\n",
+ key, uselvl ? "temp" : "perm", blevel);
+#endif
+
+ /*
+ * Insert into the linked list, if feasible.
+ */
+ if (uselvl) {
+ sym = getsymtab(key, ttype|STEMP);
+ sym->snext = tmpsyms[type];
+ tmpsyms[type] = sym;
+ return sym;
+ }
+
+ /*
+ * Need a new node. If type is SNORMAL and inside a function
+ * the node must be allocated as permanent anyway.
+ * This could be optimized by adding a remove routine, but it
+ * may be more trouble than it is worth.
+ */
+ if (ttype == (STEMP|SNORMAL))
+ ttype = SNORMAL;
+
+ for (cix = 0; (ix & 1) == 0; ix >>= 1, cix++)
+ ;
+
+ new = ttype & STEMP ? tmpalloc(sizeof(struct tree)) :
+ permalloc(sizeof(struct tree));
+ bit = (code >> cix) & 1;
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)getsymtab(key, ttype);
+ if (numsyms[type]++ == 1) {
+ new->lr[!bit] = sympole[type];
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ sympole[type] = new;
+ return (struct symtab *)new->lr[bit];
+ }
+
+
+ w = sympole[type];
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ cerror("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = (code >> bitno) & 1;
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ sympole[type] = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (struct symtab *)new->lr[bit];
+}
+
+void
+symclear(int level)
+{
+ struct symtab *s;
+ int i;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("symclear(%d)\n", level);
+#endif
+ if (level < 1) {
+ for (i = 0; i < NSTYPES; i++) {
+ s = tmpsyms[i];
+ tmpsyms[i] = 0;
+ if (i != SLBLNAME)
+ continue;
+ while (s != NULL) {
+ if (s->soffset < 0)
+ uerror("label '%s' undefined",s->sname);
+ s = s->snext;
+ }
+ }
+ } else {
+ for (i = 0; i < NSTYPES; i++) {
+ if (i == SLBLNAME)
+ continue; /* function scope */
+ while (tmpsyms[i] != NULL &&
+ tmpsyms[i]->slevel > level) {
+ tmpsyms[i] = tmpsyms[i]->snext;
+ }
+ }
+ }
+}
+
+struct symtab *
+hide(struct symtab *sym)
+{
+ struct symtab *new;
+
+ new = getsymtab(sym->sname, SNORMAL|STEMP);
+ new->snext = tmpsyms[SNORMAL];
+ tmpsyms[SNORMAL] = new;
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("\t%s hidden at level %d (%p -> %p)\n",
+ sym->sname, blevel, sym, new);
+#endif
+ return new;
+}
diff --git a/usr.bin/pcc/cc/ccom/trees.c b/usr.bin/pcc/cc/ccom/trees.c
new file mode 100644
index 00000000000..c45a1767eac
--- /dev/null
+++ b/usr.bin/pcc/cc/ccom/trees.c
@@ -0,0 +1,2447 @@
+/* $Id: trees.c,v 1.1 2007/09/15 18:12:35 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+/*
+ * Some of the changes from 32V include:
+ * - Understand "void" as type.
+ * - Handle enums as ints everywhere.
+ * - Convert some C-specific ops into branches.
+ */
+
+# include "pass1.h"
+# include "pass2.h"
+
+# include <stdarg.h>
+
+static void chkpun(NODE *p);
+static int opact(NODE *p);
+static int moditype(TWORD);
+static NODE *strargs(NODE *);
+static void rmcops(NODE *p);
+
+int lastloc = -1;
+
+/* some special actions, used in finding the type of nodes */
+# define NCVT 01
+# define PUN 02
+# define TYPL 04
+# define TYPR 010
+# define TYMATCH 040
+# define LVAL 0100
+# define CVTO 0200
+# define CVTL 0400
+# define CVTR 01000
+# define PTMATCH 02000
+# define OTHER 04000
+# define NCVTR 010000
+
+/* node conventions:
+
+ NAME: rval>0 is stab index for external
+ rval<0 is -inlabel number
+ lval is offset in bits
+ ICON: lval has the value
+ rval has the STAB index, or - label number,
+ if a name whose address is in the constant
+ rval = NONAME means no name
+ REG: rval is reg. identification cookie
+
+ */
+
+int bdebug = 0;
+
+NODE *
+buildtree(int o, NODE *l, NODE *r)
+{
+ NODE *p, *q;
+ int actions;
+ int opty;
+ struct symtab *sp = NULL; /* XXX gcc */
+ NODE *lr, *ll;
+ char *name;
+ struct symtab **elem;
+
+#ifdef PCC_DEBUG
+ if (bdebug) {
+ printf("buildtree(%s, %p, %p)\n", copst(o), l, r);
+ if (l) fwalk(l, eprint, 0);
+ if (r) fwalk(r, eprint, 0);
+ }
+#endif
+ opty = coptype(o);
+
+ /* check for constants */
+
+ if( opty == UTYPE && l->n_op == ICON ){
+
+ switch( o ){
+
+ case NOT:
+ case UMINUS:
+ case COMPL:
+ if( conval( l, o, l ) ) return(l);
+ break;
+ }
+ } else if (o == NOT && l->n_op == FCON) {
+ l = clocal(block(SCONV, l, NIL, INT, 0, MKSUE(INT)));
+ } else if( o == UMINUS && l->n_op == FCON ){
+ l->n_dcon = -l->n_dcon;
+ return(l);
+
+ } else if( o==QUEST && l->n_op==ICON ) {
+ CONSZ c = l->n_lval;
+ nfree(l);
+ if (c) {
+ tfree(r->n_right);
+ l = r->n_left;
+ nfree(r);
+ return(l);
+ } else {
+ tfree(r->n_left);
+ l = r->n_right;
+ nfree(r);
+ return(l);
+ }
+ } else if( opty == BITYPE && l->n_op == ICON && r->n_op == ICON ){
+
+ switch( o ){
+
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ case MOD:
+ /*
+ * Do type propagation for simple types here.
+ * The constant value is correct anyway.
+ * Maybe this op shortcut should be removed?
+ */
+ if (l->n_sp == NULL && r->n_sp == NULL &&
+ l->n_type < BTMASK && r->n_type < BTMASK) {
+ if (l->n_type > r->n_type)
+ r->n_type = l->n_type;
+ else
+ l->n_type = r->n_type;
+ }
+ /* FALLTHROUGH */
+ case ULT:
+ case UGT:
+ case ULE:
+ case UGE:
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ case EQ:
+ case NE:
+ case ANDAND:
+ case OROR:
+ case AND:
+ case OR:
+ case ER:
+ case LS:
+ case RS:
+ if( conval( l, o, r ) ) {
+ nfree(r);
+ return(l);
+ }
+ break;
+ }
+ } else if (opty == BITYPE && (l->n_op == FCON || l->n_op == ICON) &&
+ (r->n_op == FCON || r->n_op == ICON) && (o == PLUS || o == MINUS ||
+ o == MUL || o == DIV)) {
+ switch(o){
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ if (l->n_op == ICON)
+ l->n_dcon = l->n_lval;
+ if (r->n_op == ICON)
+ r->n_dcon = r->n_lval;
+ switch (o) {
+ case PLUS:
+ l->n_dcon += r->n_dcon; break;
+ case MINUS:
+ l->n_dcon -= r->n_dcon; break;
+ case MUL:
+ l->n_dcon *= r->n_dcon; break;
+ case DIV:
+ if (r->n_dcon == 0)
+ uerror("division by 0.");
+ else
+ l->n_dcon /= r->n_dcon;
+ }
+ l->n_op = FCON;
+ l->n_type = DOUBLE;
+ l->n_sue = MKSUE(DOUBLE);
+ nfree(r);
+ return(l);
+ }
+ }
+
+ /* its real; we must make a new node */
+
+ p = block(o, l, r, INT, 0, MKSUE(INT));
+
+ actions = opact(p);
+
+ if (actions & LVAL) { /* check left descendent */
+ if (notlval(p->n_left)) {
+ uerror("lvalue required");
+#ifdef notyet
+ } else {
+ if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
+ (l->n_type <= BTMASK && ISCON(l->n_qual << TSHIFT)))
+ if (blevel > 0)
+ uerror("lvalue is declared const");
+#endif
+ }
+ }
+
+ if( actions & NCVTR ){
+ p->n_left = pconvert( p->n_left );
+ }
+ else if( !(actions & NCVT ) ){
+ switch( opty ){
+
+ case BITYPE:
+ p->n_right = pconvert( p->n_right );
+ case UTYPE:
+ p->n_left = pconvert( p->n_left );
+
+ }
+ }
+
+ if ((actions&PUN) && (o!=CAST))
+ chkpun(p);
+
+ if( actions & (TYPL|TYPR) ){
+
+ q = (actions&TYPL) ? p->n_left : p->n_right;
+
+ p->n_type = q->n_type;
+ p->n_qual = q->n_qual;
+ p->n_df = q->n_df;
+ p->n_sue = q->n_sue;
+ }
+
+ if( actions & CVTL ) p = convert( p, CVTL );
+ if( actions & CVTR ) p = convert( p, CVTR );
+ if( actions & TYMATCH ) p = tymatch(p);
+ if( actions & PTMATCH ) p = ptmatch(p);
+
+ if( actions & OTHER ){
+ l = p->n_left;
+ r = p->n_right;
+
+ switch(o){
+
+ case NAME:
+ sp = spname;
+ if (sp->sflags & STNODE) {
+ /* Generated for optimizer */
+ p->n_op = TEMP;
+ p->n_type = sp->stype;
+ p->n_sue = sp->ssue;
+ p->n_df = sp->sdf;
+ p->n_lval = sp->soffset;
+ break;
+ }
+
+#ifdef GCC_COMPAT
+ /* Get a label name */
+ if (sp->sflags == SLBLNAME) {
+ p->n_type = VOID;
+ p->n_sue = MKSUE(VOID);
+ p->n_lval = 0;
+ p->n_sp = sp;
+ break;
+ } else
+#endif
+ if (sp->stype == UNDEF) {
+ uerror("%s undefined", sp->sname);
+ /* make p look reasonable */
+ p->n_type = INT;
+ p->n_sue = MKSUE(INT);
+ p->n_df = NULL;
+ p->n_sp = sp;
+ p->n_lval = 0;
+ defid(p, SNULL);
+ break;
+ }
+ p->n_type = sp->stype;
+ p->n_qual = sp->squal;
+ p->n_df = sp->sdf;
+ p->n_sue = sp->ssue;
+ p->n_lval = 0;
+ p->n_sp = sp;
+ /* special case: MOETY is really an ICON... */
+ if (p->n_type == MOETY) {
+ p->n_sp = NULL;
+ p->n_lval = sp->soffset;
+ p->n_df = NULL;
+ p->n_type = ENUMTY;
+ p->n_op = ICON;
+ }
+ break;
+
+ case STREF:
+ /* p->x turned into *(p+offset) */
+ /* rhs must be a name; check correctness */
+
+ /* Find member symbol struct */
+ if (l->n_type != PTR+STRTY && l->n_type != PTR+UNIONTY){
+ uerror("struct or union required");
+ break;
+ }
+
+ if ((elem = l->n_sue->suelem) == NULL)
+ uerror("undefined struct or union");
+
+ name = r->n_name;
+ for (; *elem != NULL; elem++) {
+ sp = *elem;
+ if (sp->sname == name)
+ break;
+ }
+ if (*elem == NULL)
+ uerror("member '%s' not declared", name);
+
+ r->n_sp = sp;
+ p = stref(p);
+ break;
+
+ case UMUL:
+ if (l->n_op == ADDROF) {
+ nfree(p);
+ p = l->n_left;
+ nfree(l);
+ }
+ if( !ISPTR(l->n_type))uerror("illegal indirection");
+ p->n_type = DECREF(l->n_type);
+ p->n_qual = DECREF(l->n_qual);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ break;
+
+ case ADDROF:
+ switch( l->n_op ){
+
+ case UMUL:
+ nfree(p);
+ p = l->n_left;
+ nfree(l);
+ case TEMP:
+ case NAME:
+ p->n_type = INCREF(l->n_type);
+ p->n_qual = INCQAL(l->n_qual);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ break;
+
+ case COMOP:
+ nfree(p);
+ lr = buildtree(ADDROF, l->n_right, NIL);
+ p = buildtree( COMOP, l->n_left, lr );
+ nfree(l);
+ break;
+
+ case QUEST:
+ lr = buildtree( ADDROF, l->n_right->n_right, NIL );
+ ll = buildtree( ADDROF, l->n_right->n_left, NIL );
+ nfree(p); nfree(l->n_right);
+ p = buildtree( QUEST, l->n_left, buildtree( COLON, ll, lr ) );
+ nfree(l);
+ break;
+
+ default:
+ uerror("unacceptable operand of &: %d", l->n_op );
+ break;
+ }
+ break;
+
+ case LS:
+ case RS: /* must make type size at least int... */
+ if (p->n_type == CHAR || p->n_type == SHORT) {
+ p->n_left = makety(l, INT, 0, 0, MKSUE(INT));
+ } else if (p->n_type == UCHAR || p->n_type == USHORT) {
+ p->n_left = makety(l, UNSIGNED, 0, 0,
+ MKSUE(UNSIGNED));
+ }
+ l = p->n_left;
+ p->n_type = l->n_type;
+ p->n_qual = l->n_qual;
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+
+ /* FALLTHROUGH */
+ case LSEQ:
+ case RSEQ: /* ...but not for assigned types */
+ if(tsize(r->n_type, r->n_df, r->n_sue) > SZINT)
+ p->n_right = makety(r, INT, 0, 0, MKSUE(INT));
+ break;
+
+ case RETURN:
+ case ASSIGN:
+ case CAST:
+ /* structure assignment */
+ /* take the addresses of the two sides; then make an
+ * operator using STASG and
+ * the addresses of left and right */
+
+ {
+ struct suedef *sue;
+ TWORD t;
+ union dimfun *d;
+
+ if (l->n_sue != r->n_sue)
+ uerror("assignment of different structures");
+
+ r = buildtree(ADDROF, r, NIL);
+ t = r->n_type;
+ d = r->n_df;
+ sue = r->n_sue;
+
+ l = block(STASG, l, r, t, d, sue);
+
+ if( o == RETURN ){
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ p->n_op = UMUL;
+ p->n_left = l;
+ p->n_right = NIL;
+ break;
+ }
+ case COLON:
+ /* structure colon */
+
+ if (l->n_sue != r->n_sue)
+ uerror( "type clash in conditional" );
+ break;
+
+ case CALL:
+ p->n_right = r = strargs(p->n_right);
+ case UCALL:
+ if (!ISPTR(l->n_type))
+ uerror("illegal function");
+ p->n_type = DECREF(l->n_type);
+ if (!ISFTN(p->n_type))
+ uerror("illegal function");
+ p->n_type = DECREF(p->n_type);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ if (l->n_op == ADDROF && l->n_left->n_op == NAME &&
+ l->n_left->n_sp != NULL && l->n_left->n_sp != NULL &&
+ (l->n_left->n_sp->sclass == FORTRAN ||
+ l->n_left->n_sp->sclass == UFORTRAN)) {
+ p->n_op += (FORTCALL-CALL);
+ }
+ if (p->n_type == STRTY || p->n_type == UNIONTY) {
+ /* function returning structure */
+ /* make function really return ptr to str., with * */
+
+ p->n_op += STCALL-CALL;
+ p->n_type = INCREF(p->n_type);
+ p = clocal(p); /* before recursing */
+ p = buildtree(UMUL, p, NIL);
+
+ }
+ break;
+
+ default:
+ cerror( "other code %d", o );
+ }
+
+ }
+
+ /*
+ * Allow (void)0 casts.
+ * XXX - anything on the right side must be possible to cast.
+ * XXX - remove void types further on.
+ */
+ if (p->n_op == CAST && p->n_type == VOID &&
+ p->n_right->n_op == ICON)
+ p->n_right->n_type = VOID;
+
+ if (actions & CVTO)
+ p = oconvert(p);
+ p = clocal(p);
+
+#ifdef PCC_DEBUG
+ if (bdebug) {
+ printf("End of buildtree:\n");
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ return(p);
+
+ }
+
+/*
+ * Do a conditional branch.
+ */
+void
+cbranch(NODE *p, NODE *q)
+{
+ p = buildtree(CBRANCH, p, q);
+ if (p->n_left->n_op == ICON) {
+ if (p->n_left->n_lval != 0)
+ branch(q->n_lval); /* branch always */
+ tfree(p);
+ tfree(q);
+ return;
+ }
+ ecomp(p);
+}
+
+NODE *
+strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */
+
+ if( p->n_op == CM ){
+ p->n_left = strargs( p->n_left );
+ p->n_right = strargs( p->n_right );
+ return( p );
+ }
+
+ if( p->n_type == STRTY || p->n_type == UNIONTY ){
+ p = block(STARG, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left = buildtree( ADDROF, p->n_left, NIL );
+ p = clocal(p);
+ }
+ return( p );
+}
+
+/*
+ * apply the op o to the lval part of p; if binary, rhs is val
+ */
+int
+conval(NODE *p, int o, NODE *q)
+{
+ int i, u;
+ CONSZ val;
+ U_CONSZ v1, v2;
+
+ val = q->n_lval;
+ u = ISUNSIGNED(p->n_type) || ISUNSIGNED(q->n_type);
+ if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
+
+ if (p->n_sp != NULL && q->n_sp != NULL)
+ return(0);
+ if (q->n_sp != NULL && o != PLUS)
+ return(0);
+ if (p->n_sp != NULL && o != PLUS && o != MINUS)
+ return(0);
+ v1 = p->n_lval;
+ v2 = q->n_lval;
+ switch( o ){
+
+ case PLUS:
+ p->n_lval += val;
+ if (p->n_sp == NULL) {
+ p->n_rval = q->n_rval;
+ p->n_type = q->n_type;
+ }
+ break;
+ case MINUS:
+ p->n_lval -= val;
+ break;
+ case MUL:
+ p->n_lval *= val;
+ break;
+ case DIV:
+ if (val == 0)
+ uerror("division by 0");
+ else {
+ if (u) {
+ v1 /= v2;
+ p->n_lval = v1;
+ } else
+ p->n_lval /= val;
+ }
+ break;
+ case MOD:
+ if (val == 0)
+ uerror("division by 0");
+ else {
+ if (u) {
+ v1 %= v2;
+ p->n_lval = v1;
+ } else
+ p->n_lval %= val;
+ }
+ break;
+ case AND:
+ p->n_lval &= val;
+ break;
+ case OR:
+ p->n_lval |= val;
+ break;
+ case ER:
+ p->n_lval ^= val;
+ break;
+ case LS:
+ i = val;
+ p->n_lval = p->n_lval << i;
+ break;
+ case RS:
+ i = val;
+ if (u) {
+ v1 = v1 >> i;
+ p->n_lval = v1;
+ } else
+ p->n_lval = p->n_lval >> i;
+ break;
+
+ case UMINUS:
+ p->n_lval = - p->n_lval;
+ break;
+ case COMPL:
+ p->n_lval = ~p->n_lval;
+ break;
+ case NOT:
+ p->n_lval = !p->n_lval;
+ break;
+ case LT:
+ p->n_lval = p->n_lval < val;
+ break;
+ case LE:
+ p->n_lval = p->n_lval <= val;
+ break;
+ case GT:
+ p->n_lval = p->n_lval > val;
+ break;
+ case GE:
+ p->n_lval = p->n_lval >= val;
+ break;
+ case ULT:
+ p->n_lval = v1 < v2;
+ break;
+ case ULE:
+ p->n_lval = v1 <= v2;
+ break;
+ case UGT:
+ p->n_lval = v1 > v2;
+ break;
+ case UGE:
+ p->n_lval = v1 >= v2;
+ break;
+ case EQ:
+ p->n_lval = p->n_lval == val;
+ break;
+ case NE:
+ p->n_lval = p->n_lval != val;
+ break;
+ case ANDAND:
+ p->n_lval = p->n_lval && val;
+ break;
+ case OROR:
+ p->n_lval = p->n_lval || val;
+ break;
+ default:
+ return(0);
+ }
+ return(1);
+ }
+
+/*
+ * Checks p for the existance of a pun. This is called when the op of p
+ * is ASSIGN, RETURN, CAST, COLON, or relational.
+ * One case is when enumerations are used: this applies only to lint.
+ * In the other case, one operand is a pointer, the other integer type
+ * we check that this integer is in fact a constant zero...
+ * in the case of ASSIGN, any assignment of pointer to integer is illegal
+ * this falls out, because the LHS is never 0.
+ */
+void
+chkpun(NODE *p)
+{
+ union dimfun *d1, *d2;
+ NODE *q;
+ int t1, t2;
+
+ t1 = p->n_left->n_type;
+ t2 = p->n_right->n_type;
+
+ switch (p->n_op) {
+ case RETURN:
+ /* return of void allowed but nothing else */
+ if (t1 == VOID && t2 == VOID)
+ return;
+ if (t1 == VOID)
+ return werror("returning value from void function");
+ if (t2 == VOID)
+ return uerror("using void value");
+ case COLON:
+ if (t1 == VOID && t2 == VOID)
+ return;
+ break;
+ default:
+ if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID))
+ return uerror("value of void expression used");
+ break;
+ }
+
+ /* allow void pointer assignments in any direction */
+ if (BTYPE(t1) == VOID && (t2 & TMASK))
+ return;
+ if (BTYPE(t2) == VOID && (t1 & TMASK))
+ return;
+
+#ifdef notdef
+ /* C99 says that enums always should be handled as ints */
+ /* check for enumerations */
+ if (t1==ENUMTY || t2==ENUMTY) {
+ if( clogop( p->n_op ) && p->n_op != EQ && p->n_op != NE ) {
+ werror( "comparison of enums" );
+ return;
+ }
+ if (t1==ENUMTY && t2==ENUMTY) {
+ if (p->n_left->n_sue!=p->n_right->n_sue)
+ werror("enumeration type clash, "
+ "operator %s", copst(p->n_op));
+ return;
+ }
+ if ((t1 == ENUMTY && t2 <= BTMASK) ||
+ (t2 == ENUMTY && t1 <= BTMASK))
+ return;
+ }
+#endif
+
+ if (ISPTR(t1) || ISARY(t1))
+ q = p->n_right;
+ else
+ q = p->n_left;
+
+ if (!ISPTR(q->n_type) && !ISARY(q->n_type)) {
+ if (q->n_op != ICON || q->n_lval != 0)
+ werror("illegal combination of pointer and integer");
+ } else {
+ d1 = p->n_left->n_df;
+ d2 = p->n_right->n_df;
+ if (t1 == t2) {
+ if (p->n_left->n_sue != p->n_right->n_sue)
+ werror("illegal structure pointer combination");
+ return;
+ }
+ for (;;) {
+ if (ISARY(t1) || ISPTR(t1)) {
+ if (!ISARY(t2) && !ISPTR(t2))
+ break;
+ if (ISARY(t1) && ISARY(t2) && d1->ddim != d2->ddim) {
+ werror("illegal array size combination");
+ return;
+ }
+ if (ISARY(t1))
+ ++d1;
+ if (ISARY(t2))
+ ++d2;
+ } else if (ISFTN(t1)) {
+ if (chkftn(d1->dfun, d2->dfun)) {
+ werror("illegal function "
+ "pointer combination");
+ return;
+ }
+ ++d1;
+ ++d2;
+ } else
+ break;
+ t1 = DECREF(t1);
+ t2 = DECREF(t2);
+ }
+ werror("illegal pointer combination");
+ }
+}
+
+NODE *
+stref(NODE *p)
+{
+ NODE *r;
+ struct suedef *sue;
+ union dimfun *d;
+ TWORD t, q;
+ int dsc;
+ OFFSZ off;
+ struct symtab *s;
+
+ /* make p->x */
+ /* this is also used to reference automatic variables */
+
+ s = p->n_right->n_sp;
+ nfree(p->n_right);
+ r = p->n_left;
+ nfree(p);
+ p = pconvert(r);
+
+ /* make p look like ptr to x */
+
+ if (!ISPTR(p->n_type))
+ p->n_type = PTR+UNIONTY;
+
+ t = INCREF(s->stype);
+ q = INCQAL(s->squal);
+ d = s->sdf;
+ sue = s->ssue;
+
+ p = makety(p, t, q, d, sue);
+
+ /* compute the offset to be added */
+
+ off = s->soffset;
+ dsc = s->sclass;
+
+ if (dsc & FIELD) { /* make fields look like ints */
+ off = (off/ALINT)*ALINT;
+ sue = MKSUE(INT);
+ }
+ if (off != 0) {
+ p = block(PLUS, p, offcon(off, t, d, sue), t, d, sue);
+ p->n_qual = q;
+ p = optim(p);
+ }
+
+ p = buildtree(UMUL, p, NIL);
+
+ /* if field, build field info */
+
+ if (dsc & FIELD) {
+ p = block(FLD, p, NIL, s->stype, 0, s->ssue);
+ p->n_qual = q;
+ p->n_rval = PKFIELD(dsc&FLDSIZ, s->soffset%ALINT);
+ }
+
+ p = clocal(p);
+ return p;
+}
+
+int
+notlval(p) register NODE *p; {
+
+ /* return 0 if p an lvalue, 1 otherwise */
+
+ again:
+
+ switch( p->n_op ){
+
+ case FLD:
+ p = p->n_left;
+ goto again;
+
+ case NAME:
+ case OREG:
+ case UMUL:
+ if( ISARY(p->n_type) || ISFTN(p->n_type) ) return(1);
+ case TEMP:
+ case REG:
+ return(0);
+
+ default:
+ return(1);
+
+ }
+
+ }
+/* make a constant node with value i */
+NODE *
+bcon(int i)
+{
+ register NODE *p;
+
+ p = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ p->n_lval = i;
+ p->n_sp = NULL;
+ return(clocal(p));
+}
+
+NODE *
+bpsize(NODE *p)
+{
+ return(offcon(psize(p), p->n_type, p->n_df, p->n_sue));
+}
+
+/*
+ * p is a node of type pointer; psize returns the
+ * size of the thing pointed to
+ */
+OFFSZ
+psize(NODE *p)
+{
+
+ if (!ISPTR(p->n_type)) {
+ uerror("pointer required");
+ return(SZINT);
+ }
+ /* note: no pointers to fields */
+ return(tsize(DECREF(p->n_type), p->n_df, p->n_sue));
+}
+
+/*
+ * convert an operand of p
+ * f is either CVTL or CVTR
+ * operand has type int, and is converted by the size of the other side
+ * convert is called when an integer is to be added to a pointer, for
+ * example in arrays or structures.
+ */
+NODE *
+convert(NODE *p, int f)
+{
+ union dimfun *df;
+ TWORD ty, ty2;
+ NODE *q, *r, *s, *rv;
+
+ if (f == CVTL) {
+ q = p->n_left;
+ s = p->n_right;
+ } else {
+ q = p->n_right;
+ s = p->n_left;
+ }
+ ty2 = ty = DECREF(s->n_type);
+ while (ISARY(ty))
+ ty = DECREF(ty);
+
+ r = offcon(tsize(ty, s->n_df, s->n_sue), s->n_type, s->n_df, s->n_sue);
+ ty = ty2;
+ rv = bcon(1);
+ df = s->n_df;
+ while (ISARY(ty)) {
+ rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
+ tempnode(-df->ddim, INT, 0, MKSUE(INT)));
+ df++;
+ ty = DECREF(ty);
+ }
+ rv = clocal(block(PMCONV, rv, r, INT, 0, MKSUE(INT)));
+ rv = optim(rv);
+
+ r = block(PMCONV, q, rv, INT, 0, MKSUE(INT));
+ r = clocal(r);
+ /*
+ * Indexing is only allowed with integer arguments, so insert
+ * SCONV here if arg is not an integer.
+ * XXX - complain?
+ */
+ if (r->n_type != INT)
+ r = clocal(block(SCONV, r, NIL, INT, 0, MKSUE(INT)));
+ if (f == CVTL)
+ p->n_left = r;
+ else
+ p->n_right = r;
+ return(p);
+}
+
+/*
+ * change enums to ints, or appropriate types
+ */
+void
+econvert( p ) register NODE *p; {
+
+
+ register TWORD ty;
+
+ if( (ty=BTYPE(p->n_type)) == ENUMTY || ty == MOETY ) {
+ if (p->n_sue->suesize == SZCHAR)
+ ty = INT;
+ else if (p->n_sue->suesize == SZINT)
+ ty = INT;
+ else if (p->n_sue->suesize == SZSHORT)
+ ty = INT;
+ else if (p->n_sue->suesize == SZLONGLONG)
+ ty = LONGLONG;
+ else
+ ty = LONG;
+ ty = ctype(ty);
+ p->n_sue = MKSUE(ty);
+ MODTYPE(p->n_type,ty);
+ if (p->n_op == ICON && ty != LONG && ty != LONGLONG)
+ p->n_type = INT, p->n_sue = MKSUE(INT);
+ }
+}
+
+NODE *
+pconvert( p ) register NODE *p; {
+
+ /* if p should be changed into a pointer, do so */
+
+ if( ISARY( p->n_type) ){
+ p->n_type = DECREF( p->n_type );
+ ++p->n_df;
+ return( buildtree( ADDROF, p, NIL ) );
+ }
+ if( ISFTN( p->n_type) )
+ return( buildtree( ADDROF, p, NIL ) );
+
+ return( p );
+ }
+
+NODE *
+oconvert(p) register NODE *p; {
+ /* convert the result itself: used for pointer and unsigned */
+
+ switch(p->n_op) {
+
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ if( ISUNSIGNED(p->n_left->n_type) || ISUNSIGNED(p->n_right->n_type) ) p->n_op += (ULE-LE);
+ case EQ:
+ case NE:
+ return( p );
+
+ case MINUS:
+ return( clocal( block( PVCONV,
+ p, bpsize(p->n_left), INT, 0, MKSUE(INT))));
+ }
+
+ cerror( "illegal oconvert: %d", p->n_op );
+
+ return(p);
+ }
+
+/*
+ * makes the operands of p agree; they are
+ * either pointers or integers, by this time
+ * with MINUS, the sizes must be the same
+ * with COLON, the types must be the same
+ */
+NODE *
+ptmatch(NODE *p)
+{
+ struct suedef *sue, *sue2;
+ union dimfun *d, *d2;
+ TWORD t1, t2, t, q1, q2, q;
+ int o;
+
+ o = p->n_op;
+ t = t1 = p->n_left->n_type;
+ q = q1 = p->n_left->n_qual;
+ t2 = p->n_right->n_type;
+ q2 = p->n_right->n_qual;
+ d = p->n_left->n_df;
+ d2 = p->n_right->n_df;
+ sue = p->n_left->n_sue;
+ sue2 = p->n_right->n_sue;
+
+ switch( o ){
+
+ case ASSIGN:
+ case RETURN:
+ case CAST:
+ { break; }
+
+ case MINUS:
+ { if( psize(p->n_left) != psize(p->n_right) ){
+ uerror( "illegal pointer subtraction");
+ }
+ break;
+ }
+ case COLON:
+ if (t1 != t2) {
+ /*
+ * Check for void pointer types. They are allowed
+ * to cast to/from any pointers.
+ */
+ if (ISPTR(t1) && ISPTR(t2) &&
+ (BTYPE(t1) == VOID || BTYPE(t2) == VOID))
+ break;
+ uerror("illegal types in :");
+ }
+ break;
+
+ default: /* must work harder: relationals or comparisons */
+
+ if( !ISPTR(t1) ){
+ t = t2;
+ q = q2;
+ d = d2;
+ sue = sue2;
+ break;
+ }
+ if( !ISPTR(t2) ){
+ break;
+ }
+
+ /* both are pointers */
+ if( talign(t2,sue2) < talign(t,sue) ){
+ t = t2;
+ q = q2;
+ sue = sue2;
+ }
+ break;
+ }
+
+ p->n_left = makety( p->n_left, t, q, d, sue );
+ p->n_right = makety( p->n_right, t, q, d, sue );
+ if( o!=MINUS && !clogop(o) ){
+
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_df = d;
+ p->n_sue = sue;
+ }
+
+ return(clocal(p));
+ }
+
+int tdebug = 0;
+
+NODE *
+tymatch(p) register NODE *p; {
+
+ /* satisfy the types of various arithmetic binary ops */
+
+ /* rules are:
+ if assignment, type of LHS
+ if any doubles, make double
+ else if any float make float
+ else if any longlongs, make long long
+ else if any longs, make long
+ else etcetc.
+ if either operand is unsigned, the result is...
+ */
+
+ TWORD t1, t2, t, tu;
+ int o, lu, ru;
+
+ o = p->n_op;
+
+ t1 = p->n_left->n_type;
+ t2 = p->n_right->n_type;
+
+ lu = ru = 0;
+ if( ISUNSIGNED(t1) ){
+ lu = 1;
+ t1 = DEUNSIGN(t1);
+ }
+ if( ISUNSIGNED(t2) ){
+ ru = 1;
+ t2 = DEUNSIGN(t2);
+ }
+
+ if (t1 == ENUMTY || t1 == MOETY)
+ t1 = INT; /* XXX */
+ if (t2 == ENUMTY || t2 == MOETY)
+ t2 = INT; /* XXX */
+#if 0
+ if ((t1 == CHAR || t1 == SHORT) && o!= RETURN)
+ t1 = INT;
+ if (t2 == CHAR || t2 == SHORT)
+ t2 = INT;
+#endif
+
+ if (t1 == LDOUBLE || t2 == LDOUBLE)
+ t = LDOUBLE;
+ else if (t1 == DOUBLE || t2 == DOUBLE)
+ t = DOUBLE;
+ else if (t1 == FLOAT || t2 == FLOAT)
+ t = FLOAT;
+ else if (t1==LONGLONG || t2 == LONGLONG)
+ t = LONGLONG;
+ else if (t1==LONG || t2==LONG)
+ t = LONG;
+ else /* if (t1==INT || t2==INT) */
+ t = INT;
+#if 0
+ else if (t1==SHORT || t2==SHORT)
+ t = SHORT;
+ else
+ t = CHAR;
+#endif
+
+ if( casgop(o) ){
+ tu = p->n_left->n_type;
+ t = t1;
+ } else {
+ tu = ((ru|lu) && UNSIGNABLE(t))?ENUNSIGN(t):t;
+ }
+
+ /* because expressions have values that are at least as wide
+ as INT or UNSIGNED, the only conversions needed
+ are those involving FLOAT/DOUBLE, and those
+ from LONG to INT and ULONG to UNSIGNED */
+
+
+ if (t != t1 || (ru && !lu))
+ p->n_left = makety( p->n_left, tu, 0, 0, MKSUE(tu));
+
+ if (t != t2 || o==CAST || (lu && !ru))
+ p->n_right = makety(p->n_right, tu, 0, 0, MKSUE(tu));
+
+ if( casgop(o) ){
+ p->n_type = p->n_left->n_type;
+ p->n_df = p->n_left->n_df;
+ p->n_sue = p->n_left->n_sue;
+ }
+ else if( !clogop(o) ){
+ p->n_type = tu;
+ p->n_df = NULL;
+ p->n_sue = MKSUE(t);
+ }
+
+#ifdef PCC_DEBUG
+ if (tdebug) {
+ printf("tymatch(%p): ", p);
+ tprint(stdout, t1, 0);
+ printf(" %s ", copst(o));
+ tprint(stdout, t2, 0);
+ printf(" => ");
+ tprint(stdout, tu, 0);
+ printf("\n");
+ }
+#endif
+
+ return(p);
+ }
+
+/*
+ * make p into type t by inserting a conversion
+ */
+NODE *
+makety(NODE *p, TWORD t, TWORD q, union dimfun *d, struct suedef *sue)
+{
+
+ if (p->n_type == ENUMTY && p->n_op == ICON)
+ econvert(p);
+ if (t == p->n_type) {
+ p->n_df = d;
+ p->n_sue = sue;
+ p->n_qual = q;
+ return(p);
+ }
+
+ if ((p->n_type == FLOAT || p->n_type == DOUBLE || p->n_type == LDOUBLE)
+ && (t == FLOAT || t == DOUBLE || t == LDOUBLE) && p->n_op == FCON) {
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_df = d;
+ p->n_sue = sue;
+ return(p);
+ }
+
+ if (t & TMASK) {
+ /* non-simple type */
+ p = block(PCONV, p, NIL, t, d, sue);
+ p->n_qual = q;
+ return clocal(p);
+ }
+
+ if (p->n_op == ICON) {
+ if (t == DOUBLE || t == FLOAT) {
+ p->n_op = FCON;
+ if (ISUNSIGNED(p->n_type))
+ p->n_dcon = (U_CONSZ) p->n_lval;
+ else
+ p->n_dcon = p->n_lval;
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_sue = MKSUE(t);
+ return (clocal(p));
+ }
+ }
+ p = block(SCONV, p, NIL, t, d, sue);
+ p->n_qual = q;
+ return clocal(p);
+
+}
+
+NODE *
+block(int o, NODE *l, NODE *r, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ register NODE *p;
+
+ p = talloc();
+ p->n_rval = 0;
+ p->n_op = o;
+ p->n_lval = 0; /* Protect against large lval */
+ p->n_left = l;
+ p->n_right = r;
+ p->n_type = t;
+ p->n_qual = 0;
+ p->n_df = d;
+ p->n_sue = sue;
+#if !defined(MULTIPASS)
+ /* p->n_reg = */p->n_su = 0;
+ p->n_regw = 0;
+#endif
+ return(p);
+ }
+
+int
+icons(p) register NODE *p; {
+ /* if p is an integer constant, return its value */
+ int val;
+
+ if( p->n_op != ICON ){
+ uerror( "constant expected");
+ val = 1;
+ }
+ else {
+ val = p->n_lval;
+ if( val != p->n_lval ) uerror( "constant too big for cross-compiler" );
+ }
+ tfree( p );
+ return(val);
+}
+
+/*
+ * the intent of this table is to examine the
+ * operators, and to check them for
+ * correctness.
+ *
+ * The table is searched for the op and the
+ * modified type (where this is one of the
+ * types INT (includes char and short), LONG,
+ * DOUBLE (includes FLOAT), and POINTER
+ *
+ * The default action is to make the node type integer
+ *
+ * The actions taken include:
+ * PUN check for puns
+ * CVTL convert the left operand
+ * CVTR convert the right operand
+ * TYPL the type is determined by the left operand
+ * TYPR the type is determined by the right operand
+ * TYMATCH force type of left and right to match,by inserting conversions
+ * PTMATCH like TYMATCH, but for pointers
+ * LVAL left operand must be lval
+ * CVTO convert the op
+ * NCVT do not convert the operands
+ * OTHER handled by code
+ * NCVTR convert the left operand, not the right...
+ *
+ */
+
+# define MINT 01 /* integer */
+# define MDBI 02 /* integer or double */
+# define MSTR 04 /* structure */
+# define MPTR 010 /* pointer */
+# define MPTI 020 /* pointer or integer */
+# define MENU 040 /* enumeration variable or member */
+
+int
+opact(NODE *p)
+{
+ int mt12, mt1, mt2, o;
+
+ mt1 = mt2 = mt12 = 0;
+
+ switch (coptype(o = p->n_op)) {
+ case BITYPE:
+ mt12=mt2 = moditype(p->n_right->n_type);
+ case UTYPE:
+ mt12 &= (mt1 = moditype(p->n_left->n_type));
+ break;
+ }
+
+ switch( o ){
+
+ case NAME :
+ case ICON :
+ case FCON :
+ case CALL :
+ case UCALL:
+ case UMUL:
+ { return( OTHER ); }
+ case UMINUS:
+ if( mt1 & MDBI ) return( TYPL );
+ break;
+
+ case COMPL:
+ if( mt1 & MINT ) return( TYPL );
+ break;
+
+ case ADDROF:
+ return( NCVT+OTHER );
+ case NOT:
+/* case INIT: */
+ case CM:
+ case CBRANCH:
+ case ANDAND:
+ case OROR:
+ return( 0 );
+
+ case MUL:
+ case DIV:
+ if ((mt1&MDBI) && (mt2&MENU)) return( TYMATCH );
+ if ((mt2&MDBI) && (mt1&MENU)) return( TYMATCH );
+ if( mt12 & MDBI ) return( TYMATCH );
+ break;
+
+ case MOD:
+ case AND:
+ case OR:
+ case ER:
+ if( mt12 & MINT ) return( TYMATCH );
+ break;
+
+ case LS:
+ case RS:
+ if( mt12 & MINT ) return( TYPL+OTHER );
+ break;
+
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ if( mt12 & MDBI ) return( TYMATCH+CVTO );
+ else if( mt12 & MPTR ) return( PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( PTMATCH+PUN );
+ else break;
+
+ case QUEST:
+ case COMOP:
+ if( mt2&MENU ) return( TYPR+NCVTR );
+ return( TYPR );
+
+ case STREF:
+ return( NCVTR+OTHER );
+
+ case FORCE:
+ return( TYPL );
+
+ case COLON:
+ if( mt12 & MDBI ) return( TYMATCH );
+ else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
+ else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
+ else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
+ else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
+ break;
+
+ case ASSIGN:
+ case RETURN:
+ if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
+ case CAST:
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+#if 0
+ else if(mt1&MENU && mt2&MDBI) return( TYPL+LVAL+TYMATCH );
+ else if(mt2&MENU && mt1&MDBI) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) )
+ return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+#endif
+ else if( mt1 & MPTR) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+
+ case LSEQ:
+ case RSEQ:
+ if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
+ break;
+
+ case MULEQ:
+ case DIVEQ:
+ if( mt12 & MDBI ) return( LVAL+TYMATCH );
+ break;
+
+ case MODEQ:
+ case ANDEQ:
+ case OREQ:
+ case EREQ:
+ if (mt12 & MINT)
+ return(LVAL+TYMATCH);
+ break;
+
+ case PLUSEQ:
+ case MINUSEQ:
+ case INCR:
+ case DECR:
+ if (mt12 & MDBI)
+ return(TYMATCH+LVAL);
+ else if ((mt1&MPTR) && (mt2&MINT))
+ return(TYPL+LVAL+CVTR);
+ break;
+
+ case MINUS:
+ if (mt12 & MPTR)
+ return(CVTO+PTMATCH+PUN);
+ if (mt2 & MPTR)
+ break;
+ /* FALLTHROUGH */
+ case PLUS:
+ if (mt12 & MDBI)
+ return(TYMATCH);
+ else if ((mt1&MPTR) && (mt2&MINT))
+ return(TYPL+CVTR);
+ else if ((mt1&MINT) && (mt2&MPTR))
+ return(TYPR+CVTL);
+
+ }
+ uerror("operands of %s have incompatible types", copst(o));
+ return(NCVT);
+}
+
+int
+moditype(TWORD ty)
+{
+ switch (ty) {
+
+ case ENUMTY:
+ case MOETY:
+ return( MENU|MINT|MDBI|MPTI );
+
+ case STRTY:
+ case UNIONTY:
+ return( MSTR );
+
+ case BOOL:
+ case CHAR:
+ case SHORT:
+ case UCHAR:
+ case USHORT:
+ case UNSIGNED:
+ case ULONG:
+ case ULONGLONG:
+ case INT:
+ case LONG:
+ case LONGLONG:
+ return( MINT|MDBI|MPTI );
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+ return( MDBI );
+ default:
+ return( MPTR|MPTI );
+
+ }
+}
+
+int tvaloff = 100;
+
+/*
+ * Returns a TEMP node with temp number nr.
+ * If nr == 0, return a node with a new number.
+ */
+NODE *
+tempnode(int nr, TWORD type, union dimfun *df, struct suedef *sue)
+{
+ NODE *r;
+
+ r = block(TEMP, NIL, NIL, type, df, sue);
+ r->n_lval = nr ? nr : tvaloff;
+ tvaloff += szty(type);
+ return r;
+}
+
+/*
+ * Do sizeof on p.
+ */
+NODE *
+doszof(NODE *p)
+{
+ union dimfun *df;
+ TWORD ty;
+ NODE *rv;
+
+ /*
+ * Arrays may be dynamic, may need to make computations.
+ */
+
+ rv = bcon(1);
+ df = p->n_df;
+ ty = p->n_type;
+ while (ISARY(ty)) {
+ rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
+ tempnode(-df->ddim, INT, 0, MKSUE(INT)));
+ df++;
+ ty = DECREF(ty);
+ }
+ rv = buildtree(MUL, rv, bcon(tsize(ty, p->n_df, p->n_sue)/SZCHAR));
+ tfree(p);
+ return rv;
+}
+
+#ifdef PCC_DEBUG
+void
+eprint(NODE *p, int down, int *a, int *b)
+{
+ int ty;
+
+ *a = *b = down+1;
+ while( down > 1 ){
+ printf( "\t" );
+ down -= 2;
+ }
+ if( down ) printf( " " );
+
+ ty = coptype( p->n_op );
+
+ printf("%p) %s, ", p, copst(p->n_op));
+ if (ty == LTYPE) {
+ printf(CONFMT, p->n_lval);
+ printf(", %d, ", p->n_rval);
+ }
+ tprint(stdout, p->n_type, p->n_qual);
+ printf( ", %p, %p\n", p->n_df, p->n_sue );
+}
+# endif
+
+void
+prtdcon(NODE *p)
+{
+ int o = p->n_op, i;
+
+ if (o != FCON)
+ return;
+
+ /* Write float constants to memory */
+ /* Should be volontary per architecture */
+
+ setloc1(RDATA);
+ defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
+ ALDOUBLE : ALLDOUBLE );
+ deflab1(i = getlab());
+ ninval(0, btdims[p->n_type].suesize, p);
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = tmpalloc(sizeof(struct symtab_hdr));
+ p->n_sp->sclass = ILABEL;
+ p->n_sp->soffset = i;
+}
+
+extern int negrel[];
+
+/*
+ * Walk up through the tree from the leaves,
+ * removing constant operators.
+ */
+static void
+logwalk(NODE *p)
+{
+ int o = coptype(p->n_op);
+ NODE *l, *r;
+
+ l = p->n_left;
+ r = p->n_right;
+ switch (o) {
+ case LTYPE:
+ return;
+ case BITYPE:
+ logwalk(r);
+ case UTYPE:
+ logwalk(l);
+ }
+ if (!clogop(p->n_op))
+ return;
+ if (p->n_op == NOT && l->n_op == ICON) {
+ p->n_lval = l->n_lval == 0;
+ nfree(l);
+ p->n_op = ICON;
+ }
+ if (l->n_op == ICON && r->n_op == ICON) {
+ if (conval(l, p->n_op, r) == 0) {
+ /*
+ * people sometimes tend to do really odd compares,
+ * like "if ("abc" == "def")" etc.
+ * do it runtime instead.
+ */
+ } else {
+ p->n_lval = l->n_lval;
+ p->n_op = ICON;
+ nfree(l);
+ nfree(r);
+ }
+ }
+}
+
+/*
+ * Removes redundant logical operators for branch conditions.
+ */
+static void
+fixbranch(NODE *p, int label)
+{
+
+ logwalk(p);
+
+ if (p->n_op == ICON) {
+ if (p->n_lval != 0)
+ branch(label);
+ nfree(p);
+ } else {
+ if (!clogop(p->n_op)) /* Always conditional */
+ p = buildtree(NE, p, bcon(0));
+ ecode(buildtree(CBRANCH, p, bcon(label)));
+ }
+}
+
+/*
+ * Write out logical expressions as branches.
+ */
+static void
+andorbr(NODE *p, int true, int false)
+{
+ NODE *q;
+ int o, lab;
+
+ lab = -1;
+ switch (o = p->n_op) {
+ case EQ:
+ case NE:
+ /*
+ * Remove redundant EQ/NE nodes.
+ */
+ while (((o = p->n_left->n_op) == EQ || o == NE) &&
+ p->n_right->n_op == ICON) {
+ o = p->n_op;
+ q = p->n_left;
+ if (p->n_right->n_lval == 0) {
+ nfree(p->n_right);
+ *p = *q;
+ nfree(q);
+ if (o == EQ)
+ p->n_op = negrel[p->n_op - EQ];
+// p->n_op = NE; /* toggla */
+ } else if (p->n_right->n_lval == 1) {
+ nfree(p->n_right);
+ *p = *q;
+ nfree(q);
+ if (o == NE)
+ p->n_op = negrel[p->n_op - EQ];
+// p->n_op = EQ; /* toggla */
+ } else
+ break; /* XXX - should always be false */
+
+ }
+ /* FALLTHROUGH */
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+calc: if (true < 0) {
+ p->n_op = negrel[p->n_op - EQ];
+ true = false;
+ false = -1;
+ }
+
+ rmcops(p->n_left);
+ rmcops(p->n_right);
+ fixbranch(p, true);
+ if (false >= 0)
+ branch(false);
+ break;
+
+ case ULE:
+ case UGT:
+ /* Convert to friendlier ops */
+ if (p->n_right->n_op == ICON && p->n_right->n_lval == 0)
+ p->n_op = o == ULE ? EQ : NE;
+ goto calc;
+
+ case UGE:
+ case ULT:
+ /* Already true/false by definition */
+ if (p->n_right->n_op == ICON && p->n_right->n_lval == 0) {
+ if (true < 0) {
+ o = o == ULT ? UGE : ULT;
+ true = false;
+ }
+ rmcops(p->n_left);
+ ecode(p->n_left);
+ rmcops(p->n_right);
+ ecode(p->n_right);
+ nfree(p);
+ if (o == UGE) /* true */
+ branch(true);
+ break;
+ }
+ goto calc;
+
+ case ANDAND:
+ lab = false<0 ? getlab() : false ;
+ andorbr(p->n_left, -1, lab);
+ andorbr(p->n_right, true, false);
+ if (false < 0)
+ plabel( lab);
+ nfree(p);
+ break;
+
+ case OROR:
+ lab = true<0 ? getlab() : true;
+ andorbr(p->n_left, lab, -1);
+ andorbr(p->n_right, true, false);
+ if (true < 0)
+ plabel( lab);
+ nfree(p);
+ break;
+
+ case NOT:
+ andorbr(p->n_left, false, true);
+ nfree(p);
+ break;
+
+ default:
+ rmcops(p);
+ if (true >= 0)
+ fixbranch(p, true);
+ if (false >= 0) {
+ if (true >= 0)
+ branch(false);
+ else
+ fixbranch(buildtree(EQ, p, bcon(0)), false);
+ }
+ }
+}
+
+/*
+ * Massage the output trees to remove C-specific nodes:
+ * COMOPs are split into separate statements.
+ * QUEST/COLON are rewritten to branches.
+ * ANDAND/OROR/NOT are rewritten to branches for lazy-evaluation.
+ * CBRANCH conditions are rewritten for lazy-evaluation.
+ */
+static void
+rmcops(NODE *p)
+{
+ TWORD type;
+ NODE *q, *r;
+ int o, ty, lbl, lbl2, tval = 0;
+
+again:
+ o = p->n_op;
+ ty = coptype(o);
+ switch (o) {
+ case QUEST:
+
+ /*
+ * Create a branch node from ?:
+ * || and && must be taken special care of.
+ */
+ type = p->n_type;
+ andorbr(p->n_left, -1, lbl = getlab());
+
+ /* Make ASSIGN node */
+ /* Only if type is not void */
+ q = p->n_right->n_left;
+ if (type != VOID) {
+ r = tempnode(0, q->n_type, q->n_df, q->n_sue);
+ tval = r->n_lval;
+ q = buildtree(ASSIGN, r, q);
+ }
+ rmcops(q);
+ ecode(q); /* Done with assign */
+ branch(lbl2 = getlab());
+ plabel( lbl);
+
+ q = p->n_right->n_right;
+ if (type != VOID) {
+ r = tempnode(tval, q->n_type, q->n_df, q->n_sue);
+ q = buildtree(ASSIGN, r, q);
+ }
+ rmcops(q);
+ ecode(q); /* Done with assign */
+
+ plabel( lbl2);
+
+ nfree(p->n_right);
+ if (p->n_type != VOID) {
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ *p = *r;
+ nfree(r);
+ } else
+ p->n_op = ICON;
+ break;
+
+ case ULE:
+ case ULT:
+ case UGE:
+ case UGT:
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case ANDAND:
+ case OROR:
+ case NOT:
+#ifdef SPECIAL_CCODES
+#error fix for private CCODES handling
+#else
+ r = talloc();
+ *r = *p;
+ andorbr(r, -1, lbl = getlab());
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tval = q->n_lval;
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ ecode(buildtree(ASSIGN, q, bcon(1)));
+ branch(lbl2 = getlab());
+ plabel( lbl);
+ ecode(buildtree(ASSIGN, r, bcon(0)));
+ plabel( lbl2);
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ *p = *r;
+ nfree(r);
+#endif
+ break;
+ case CBRANCH:
+ andorbr(p->n_left, p->n_right->n_lval, -1);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_type = VOID;
+ break;
+ case COMOP:
+ rmcops(p->n_left);
+ ecode(p->n_left);
+ /* Now when left tree is dealt with, rm COMOP */
+ q = p->n_right;
+ *p = *p->n_right;
+ nfree(q);
+ goto again;
+
+ default:
+ if (ty == LTYPE)
+ return;
+ rmcops(p->n_left);
+ if (ty == BITYPE)
+ rmcops(p->n_right);
+ }
+}
+
+/*
+ * Return 1 if an assignment is found.
+ */
+static int
+has_se(NODE *p)
+{
+ if (cdope(p->n_op) & ASGFLG)
+ return 1;
+ if (coptype(p->n_op) == LTYPE)
+ return 0;
+ if (has_se(p->n_left))
+ return 1;
+ if (coptype(p->n_op) == BITYPE)
+ return has_se(p->n_right);
+ return 0;
+}
+
+/*
+ * Find and convert asgop's to separate statements.
+ * Be careful about side effects.
+ * assign tells whether ASSIGN should be considered giving
+ * side effects or not.
+ */
+static NODE *
+delasgop(NODE *p)
+{
+ NODE *q, *r;
+ int tval;
+
+ if (p->n_op == INCR || p->n_op == DECR) {
+ /*
+ * Rewrite x++ to (x += 1) -1; and deal with it further down.
+ * Pass2 will remove -1 if unneccessary.
+ */
+ q = ccopy(p);
+ tfree(p->n_left);
+ q->n_op = (p->n_op==INCR)?PLUSEQ:MINUSEQ;
+ p->n_op = (p->n_op==INCR)?MINUS:PLUS;
+ p->n_left = delasgop(q);
+
+ } else if ((cdope(p->n_op)&ASGOPFLG) &&
+ p->n_op != RETURN && p->n_op != CAST) {
+ NODE *l = p->n_left;
+ NODE *ll = l->n_left;
+
+ if (has_se(l)) {
+ q = tempnode(0, ll->n_type, ll->n_df, ll->n_sue);
+ tval = q->n_lval;
+ r = tempnode(tval, ll->n_type, ll->n_df,ll->n_sue);
+ l->n_left = q;
+ /* Now the left side of node p has no side effects. */
+ /* side effects on the right side must be obeyed */
+ p = delasgop(p);
+
+ r = buildtree(ASSIGN, r, ll);
+ r = delasgop(r);
+ ecode(r);
+ } else {
+#if 0 /* Cannot call buildtree() here, it would invoke double add shifts */
+ p->n_right = buildtree(UNASG p->n_op, ccopy(l),
+ p->n_right);
+#else
+ p->n_right = block(UNASG p->n_op, ccopy(l),
+ p->n_right, p->n_type, p->n_df, p->n_sue);
+#endif
+ p->n_op = ASSIGN;
+ p->n_right = delasgop(p->n_right);
+ p->n_right = clocal(p->n_right);
+ }
+
+ } else {
+ if (coptype(p->n_op) == LTYPE)
+ return p;
+ p->n_left = delasgop(p->n_left);
+ if (coptype(p->n_op) == BITYPE)
+ p->n_right = delasgop(p->n_right);
+ }
+ return p;
+}
+
+int edebug = 0;
+void
+ecomp(NODE *p)
+{
+
+#ifdef PCC_DEBUG
+ if (edebug)
+ fwalk(p, eprint, 0);
+#endif
+ if (!reached) {
+ werror("statement not reached");
+ reached = 1;
+ }
+ p = optim(p);
+ rmcops(p);
+ p = delasgop(p);
+ setloc1(PROG);
+ if (p->n_op == ICON && p->n_type == VOID)
+ tfree(p);
+ else
+ ecode(p);
+}
+
+#if defined(MULTIPASS)
+void
+p2tree(NODE *p)
+{
+ struct symtab *q;
+ int ty;
+
+# ifdef MYP2TREE
+ MYP2TREE(p); /* local action can be taken here; then return... */
+# endif
+
+ ty = coptype(p->n_op);
+
+ printf("%d\t", p->n_op);
+
+ if (ty == LTYPE) {
+ printf(CONFMT, p->n_lval);
+ printf("\t");
+ }
+ if (ty != BITYPE) {
+ if (p->n_op == NAME || p->n_op == ICON)
+ printf("0\t");
+ else
+ printf("%d\t", p->n_rval);
+ }
+
+ printf("%o\t", p->n_type);
+
+ /* handle special cases */
+
+ switch (p->n_op) {
+
+ case NAME:
+ case ICON:
+ /* print external name */
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+ q->sclass == ILABEL) {
+ printf(LABFMT, q->soffset);
+ } else
+ printf("%s\n", exname(q->sname));
+ } else
+ printf("\n");
+ break;
+
+ case STARG:
+ case STASG:
+ case STCALL:
+ case USTCALL:
+ /* print out size */
+ /* use lhs size, in order to avoid hassles
+ * with the structure `.' operator
+ */
+
+ /* note: p->left not a field... */
+ printf(CONFMT, (CONSZ)tsize(STRTY, p->n_left->n_df,
+ p->n_left->n_sue));
+ printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue));
+ break;
+
+ default:
+ printf( "\n" );
+ }
+
+ if (ty != LTYPE)
+ p2tree(p->n_left);
+ if (ty == BITYPE)
+ p2tree(p->n_right);
+}
+#else
+void
+p2tree(NODE *p)
+{
+ struct symtab *q;
+ int ty;
+
+# ifdef MYP2TREE
+ MYP2TREE(p); /* local action can be taken here; then return... */
+# endif
+
+ ty = coptype(p->n_op);
+
+ switch( p->n_op ){
+
+ case NAME:
+ case ICON:
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+#ifdef GCC_COMPAT
+ q->sflags == SLBLNAME ||
+#endif
+ q->sclass == ILABEL) {
+ char *cp = (isinlining ?
+ permalloc(32) : tmpalloc(32));
+ int n = q->soffset;
+ if (n < 0)
+ n = -n;
+ snprintf(cp, 32, LABFMT, n);
+ p->n_name = cp;
+ } else {
+#ifdef GCC_COMPAT
+ p->n_name = gcc_findname(q);
+#else
+ p->n_name = exname(q->sname);
+#endif
+ }
+ } else
+ p->n_name = "";
+ break;
+
+ case STASG:
+ /* STASG used for stack array init */
+ if (ISARY(p->n_type)) {
+ int size1 = tsize(p->n_type, p->n_left->n_df,
+ p->n_left->n_sue)/SZCHAR;
+ p->n_stsize = tsize(p->n_type, p->n_right->n_df,
+ p->n_right->n_sue)/SZCHAR;
+ if (size1 < p->n_stsize)
+ p->n_stsize = size1;
+ p->n_stalign = talign(p->n_type,
+ p->n_left->n_sue)/SZCHAR;
+ break;
+ }
+ /* FALLTHROUGH */
+ case STARG:
+ case STCALL:
+ case USTCALL:
+ /* set up size parameters */
+ p->n_stsize = (tsize(STRTY, p->n_left->n_df,
+ p->n_left->n_sue)+SZCHAR-1)/SZCHAR;
+ p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR;
+ break;
+
+ default:
+ p->n_name = "";
+ }
+
+ if( ty != LTYPE ) p2tree( p->n_left );
+ if( ty == BITYPE ) p2tree( p->n_right );
+ }
+
+#endif
+
+/*
+ * Change void data types into char.
+ */
+static void
+delvoid(NODE *p)
+{
+ /* Convert "PTR undef" (void *) to "PTR uchar" */
+ if (BTYPE(p->n_type) == VOID)
+ p->n_type = (p->n_type & ~BTMASK) | UCHAR;
+ if (BTYPE(p->n_type) == BOOL) {
+ if (p->n_op == SCONV && p->n_type == BOOL) {
+ /* create a jump and a set */
+ NODE *q, *r, *s;
+ int l, val;
+
+ q = talloc();
+ *q = *p;
+ q->n_type = BOOL_TYPE;
+ r = tempnode(0, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
+ val = r->n_lval;
+ s = tempnode(val, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
+ *p = *s;
+ q = buildtree(ASSIGN, r, q);
+ cbranch(buildtree(EQ, q, bcon(0)), bcon(l = getlab()));
+ ecode(buildtree(ASSIGN, s, bcon(1)));
+ plabel(l);
+ } else
+ p->n_type = (p->n_type & ~BTMASK) | BOOL_TYPE;
+ }
+
+}
+
+void
+ecode(NODE *p)
+{
+ /* walk the tree and write out the nodes.. */
+
+ if (nerrors)
+ return;
+
+ p = optim(p);
+ p = delasgop(p);
+ walkf(p, prtdcon);
+ walkf(p, delvoid);
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("Fulltree:\n");
+ fwalk(p, eprint, 0);
+ }
+#endif
+ p2tree(p);
+#if !defined(MULTIPASS)
+ send_passt(IP_NODE, p);
+#endif
+}
+
+/*
+ * Send something further on to the next pass.
+ */
+void
+send_passt(int type, ...)
+{
+ struct interpass *ip;
+ struct interpass_prolog *ipp;
+ extern int crslab;
+ va_list ap;
+ int sz;
+
+ va_start(ap, type);
+ if (type == IP_PROLOG || type == IP_EPILOG)
+ sz = sizeof(struct interpass_prolog);
+ else
+ sz = sizeof(struct interpass);
+
+ ip = isinlining ? permalloc(sz) : tmpalloc(sz);
+ ip->type = type;
+ ip->lineno = lineno;
+ switch (type) {
+ case IP_NODE:
+ if (lastloc != PROG)
+ setloc1(PROG);
+ ip->ip_node = va_arg(ap, NODE *);
+ break;
+ case IP_EPILOG:
+ case IP_PROLOG:
+ setloc1(PROG);
+ ipp = (struct interpass_prolog *)ip;
+ ipp->ipp_regs = va_arg(ap, int);
+ ipp->ipp_autos = va_arg(ap, int);
+ ipp->ipp_name = va_arg(ap, char *);
+ ipp->ipp_type = va_arg(ap, TWORD);
+ ipp->ipp_vis = va_arg(ap, int);
+ ip->ip_lbl = va_arg(ap, int);
+ ipp->ip_tmpnum = tvaloff;
+ ipp->ip_lblnum = crslab;
+ if (type == IP_PROLOG)
+ ipp->ip_lblnum--;
+ break;
+ case IP_DEFLAB:
+ ip->ip_lbl = va_arg(ap, int);
+ break;
+ case IP_ASM:
+ if (blevel == 0) { /* outside function */
+ printf("\t%s\n", va_arg(ap, char *));
+ va_end(ap);
+ lastloc = -1;
+ return;
+ }
+ ip->ip_asm = va_arg(ap, char *);
+ break;
+ default:
+ cerror("bad send_passt type %d", type);
+ }
+ va_end(ap);
+ if (isinlining)
+ inline_addarg(ip);
+ else
+ pass2_compile(ip);
+ if (type == IP_EPILOG)
+ lastloc = PROG;
+}
+
+char *
+copst(int op)
+{
+ if (op <= MAXOP)
+ return opst[op];
+#define SNAM(x,y) case x: return #y;
+ switch (op) {
+ SNAM(QUALIFIER,QUALIFIER)
+ SNAM(CLASS,CLASS)
+ SNAM(RB,])
+ SNAM(DOT,.)
+ SNAM(ELLIPSIS,...)
+ SNAM(LB,[)
+ SNAM(TYPE,TYPE)
+ SNAM(COMOP,COMOP)
+ SNAM(QUEST,?)
+ SNAM(COLON,:)
+ SNAM(ANDAND,&&)
+ SNAM(OROR,||)
+ SNAM(NOT,!)
+ SNAM(CAST,CAST)
+ SNAM(PLUSEQ,+=)
+ SNAM(MINUSEQ,-=)
+ SNAM(MULEQ,*=)
+ SNAM(DIVEQ,/=)
+ SNAM(MODEQ,%=)
+ SNAM(ANDEQ,&=)
+ SNAM(OREQ,|=)
+ SNAM(EREQ,^=)
+ SNAM(LSEQ,<<=)
+ SNAM(RSEQ,>>=)
+ SNAM(INCR,++)
+ SNAM(DECR,--)
+ default:
+ cerror("bad copst %d", op);
+ }
+ return 0; /* XXX gcc */
+}
+
+int
+cdope(int op)
+{
+ if (op <= MAXOP)
+ return dope[op];
+ switch (op) {
+ case QUALIFIER:
+ case CLASS:
+ case RB:
+ case DOT:
+ case ELLIPSIS:
+ case TYPE:
+ return LTYPE;
+ case COMOP:
+ case QUEST:
+ case COLON:
+ case LB:
+ return BITYPE;
+ case ANDAND:
+ case OROR:
+ return BITYPE|LOGFLG;
+ case NOT:
+ return UTYPE|LOGFLG;
+ case CAST:
+ return BITYPE|ASGFLG|ASGOPFLG;
+ case PLUSEQ:
+ return BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG;
+ case MINUSEQ:
+ return BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG;
+ case MULEQ:
+ return BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG;
+ case OREQ:
+ case EREQ:
+ case ANDEQ:
+ return BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG;
+ case DIVEQ:
+ return BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG;
+ case MODEQ:
+ return BITYPE|DIVFLG|ASGFLG|ASGOPFLG;
+ case LSEQ:
+ case RSEQ:
+ return BITYPE|SHFFLG|ASGFLG|ASGOPFLG;
+ case INCR:
+ case DECR:
+ return BITYPE|ASGFLG;
+ }
+ return 0; /* XXX gcc */
+}
+
+/*
+ * make a fresh copy of p
+ */
+NODE *
+ccopy(NODE *p)
+{
+ NODE *q;
+
+ q = talloc();
+ *q = *p;
+
+ switch (coptype(q->n_op)) {
+ case BITYPE:
+ q->n_right = ccopy(p->n_right);
+ case UTYPE:
+ q->n_left = ccopy(p->n_left);
+ }
+
+ return(q);
+}
+
+/*
+ * set PROG-seg label.
+ */
+void
+plabel(int label)
+{
+ setloc1(PROG);
+ reached = 1; /* Will this always be correct? */
+ send_passt(IP_DEFLAB, label);
+}
diff --git a/usr.bin/pcc/cc/cpp/Makefile.in b/usr.bin/pcc/cc/cpp/Makefile.in
new file mode 100644
index 00000000000..c293478a71a
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/Makefile.in
@@ -0,0 +1,79 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:32 otto Exp $
+#
+# Makefile.in for cpp
+#
+XFL=-DCPP_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libexecdir = @libexecdir@
+strip = @strip@
+CC = @CC@
+CFLAGS = @CFLAGS@ $(XFL)
+CPPFLAGS = @CPPFLAGS@
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+YACC = @YACC@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+OBJS=cpp.o cpy.o scanner.o
+HEADERS=cpp.h
+DEST=cpp
+
+all: ${DEST}
+
+${DEST}: $(OBJS) $(HEADERS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+.c.o:
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
+
+.l.o:
+ $(LEX) $(LFLAGS) $<
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ lex.yy.c
+
+.y.o:
+ $(YACC) -d $(YFLAGS) $<
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ y.tab.c
+
+$(OBJS): $(HEADERS)
+
+cpp.o: cpy.o
+
+test:
+ ./cpp < tests/test1 > tests/run1
+ cmp tests/run1 tests/res1
+ ./cpp < tests/test2 > tests/run2
+ cmp tests/run2 tests/res2
+ ./cpp < tests/test3 > tests/run3
+ cmp tests/run3 tests/res3
+ ./cpp < tests/test4 > tests/run4
+ cmp tests/run4 tests/res4
+ ./cpp < tests/test5 > tests/run5
+ cmp tests/run5 tests/res5
+ ./cpp < tests/test6 > tests/run6
+ cmp tests/run6 tests/res6
+ ./cpp < tests/test7 > tests/run7
+ cmp tests/run7 tests/res7
+ ./cpp < tests/test8 > tests/run8
+ cmp tests/run8 tests/res8
+ ./cpp < tests/test9 > tests/run9
+ cmp tests/run9 tests/res9
+
+
+install:
+ test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)"
+ ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir}
+ @if [ ${strip} = yes ]; then \
+ strip ${DESTDIR}${libexecdir}/${DEST} ; \
+ echo strip ${DESTDIR}${libexecdir}/${DEST} ; \
+ fi
+
+clean:
+ /bin/rm -f $(OBJS) cpp lex.yy.c y.tab.[ch] tests/run*
+
+distclean: clean
+ /bin/rm -f Makefile
diff --git a/usr.bin/pcc/cc/cpp/cpp.c b/usr.bin/pcc/cc/cpp/cpp.c
new file mode 100644
index 00000000000..d6f042aba71
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/cpp.c
@@ -0,0 +1,1447 @@
+/* $Id: cpp.c,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * 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.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+/*
+ * The C preprocessor.
+ * This code originates from the V6 preprocessor with some additions
+ * from V7 cpp, and at last ansi/c99 support.
+ */
+
+#include "../../config.h"
+
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include "cpp.h"
+#include "y.tab.h"
+
+#define MAXARG 250 /* # of args to a macro, limited by char value */
+#define SBSIZE 600000
+
+static usch sbf[SBSIZE];
+/* C command */
+
+int tflag; /* traditional cpp syntax */
+#ifdef CPP_DEBUG
+int dflag; /* debug printouts */
+#define DPRINT(x) if (dflag) printf x
+#define DDPRINT(x) if (dflag > 1) printf x
+#else
+#define DPRINT(x)
+#define DDPRINT(x)
+#endif
+
+int ofd;
+static usch outbuf[CPPBUF];
+static int obufp, istty;
+int Cflag, Mflag;
+usch *Mfile;
+struct initar *initar;
+
+/* avoid recursion */
+struct recur {
+ struct recur *next;
+ struct symtab *sp;
+};
+
+/* include dirs */
+struct incs {
+ struct incs *next;
+ usch *dir;
+} *incdir[2];
+#define INCINC 0
+#define SYSINC 1
+
+static struct symtab *filloc;
+static struct symtab *linloc;
+int trulvl;
+int flslvl;
+int elflvl;
+int elslvl;
+usch *stringbuf = sbf;
+
+/*
+ * Macro replacement list syntax:
+ * - For object-type macros, replacement strings are stored as-is.
+ * - For function-type macros, macro args are substituted for the
+ * character WARN followed by the argument number.
+ * - The value element points to the end of the string, to simplify
+ * pushback onto the input queue.
+ *
+ * The first character (from the end) in the replacement list is
+ * the number of arguments:
+ * VARG - ends with ellipsis, next char is argcount without ellips.
+ * OBJCT - object-type macro
+ * 0 - empty parenthesis, foo()
+ * 1-> - number of args.
+ */
+
+#define VARG 0xfe /* has varargs */
+#define OBJCT 0xff
+#define WARN 1 /* SOH, not legal char */
+#define CONC 2 /* STX, not legal char */
+#define SNUFF 3 /* ETX, not legal char */
+#define NOEXP 4 /* EOT, not legal char */
+#define EXPAND 5 /* ENQ, not legal char */
+
+/* args for lookup() */
+#define FIND 0
+#define ENTER 1
+
+static void expdef(usch *proto, struct recur *, int gotwarn);
+void define(void);
+static int canexpand(struct recur *, struct symtab *np);
+void include(void);
+void line(void);
+void flbuf(void);
+void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ struct initar *it;
+ struct incs *w, *w2;
+ struct symtab *nl;
+ register int ch;
+// usch *osp;
+
+ while ((ch = getopt(argc, argv, "CD:I:MS:U:di:t")) != -1)
+ switch (ch) {
+ case 'C': /* Do not discard comments */
+ Cflag++;
+ break;
+
+ case 'i': /* include */
+ case 'U': /* undef */
+ case 'D': /* define something */
+ it = malloc(sizeof(struct initar));
+ it->type = ch;
+ it->str = optarg;
+ it->next = initar;
+ initar = it;
+#if 0
+ osp = (usch *)optarg;
+ while (*osp && *osp != '=')
+ osp++;
+ if (*osp == '=') {
+ *osp++ = 0;
+ while (*osp)
+ osp++;
+ *osp = OBJCT;
+ } else {
+ static usch c[3] = { 0, '1', OBJCT };
+ osp = &c[2];
+ }
+ nl = lookup((usch *)optarg, ENTER);
+ if (nl->value) {
+ /* check for redefinition */
+ usch *o = nl->value, *n = osp;
+ while (*o && *o == *n)
+ o--, n--;
+ if (*o || *o != *n)
+ error("%s redefined", optarg);
+ }
+ nl->value = osp;
+#endif
+ break;
+
+ case 'M': /* Generate dependencies for make */
+ Mflag++;
+ break;
+
+ case 'S':
+ case 'I':
+ w = calloc(sizeof(struct incs), 1);
+ w->dir = (usch *)optarg;
+ w2 = incdir[ch == 'I' ? INCINC : SYSINC];
+ if (w2 != NULL) {
+ while (w2->next)
+ w2 = w2->next;
+ w2->next = w;
+ } else
+ incdir[ch == 'I' ? INCINC : SYSINC] = w;
+ break;
+
+#if 0
+ case 'U':
+ if ((nl = lookup((usch *)optarg, FIND)))
+ nl->value = NULL;
+ break;
+#endif
+#ifdef CPP_DEBUG
+ case 'd':
+ dflag++;
+ break;
+#endif
+ case 't':
+ tflag = 1;
+ break;
+
+#if 0
+ case 'i':
+ if (ifile)
+ error("max 1 -i entry");
+ ifile = optarg;
+ break;
+#endif
+
+ case '?':
+ usage();
+ default:
+ error("bad arg %c\n", ch);
+ }
+ argc -= optind;
+ argv += optind;
+
+ filloc = lookup((usch *)"__FILE__", ENTER);
+ linloc = lookup((usch *)"__LINE__", ENTER);
+ filloc->value = linloc->value = (usch *)""; /* Just something */
+
+ if (tflag == 0) {
+ time_t t = time(NULL);
+ usch *n = (usch *)ctime(&t);
+
+ /*
+ * Manually move in the predefined macros.
+ */
+ nl = lookup((usch *)"__TIME__", ENTER);
+ savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"');
+ savch(OBJCT);
+ nl->value = stringbuf-1;
+
+ nl = lookup((usch *)"__DATE__", ENTER);
+ savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]);
+ savstr(&n[20]); savch('"'); savch(OBJCT);
+ nl->value = stringbuf-1;
+
+ nl = lookup((usch *)"__STDC__", ENTER);
+ savch(0); savch('1'); savch(OBJCT);
+ nl->value = stringbuf-1;
+ }
+
+ if (Mflag) {
+ usch *c;
+
+ if (argc < 1)
+ error("-M and no infile");
+ if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
+ c = (usch *)argv[0];
+ else
+ c++;
+ Mfile = stringbuf;
+ savstr(c); savch(0);
+ if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL)
+ error("-M and no extension: ");
+ c[1] = 'o';
+ c[2] = 0;
+ }
+
+ if (argc == 2) {
+ if ((ofd = open(argv[1], O_WRONLY|O_CREAT, 0600)) < 0)
+ error("Can't creat %s", argv[1]);
+ } else
+ ofd = 1; /* stdout */
+ istty = isatty(ofd);
+
+ if (pushfile((usch *)(argc && strcmp(argv[0], "-") ? argv[0] : NULL)))
+ error("cannot open %s", argv[0]);
+
+ flbuf();
+ close(ofd);
+ return 0;
+}
+
+/*
+ * Expand the symbol nl read from input.
+ * Return a pointer to the fully expanded result.
+ * It is the responsibility of the caller to reset the heap usage.
+ */
+usch *
+gotident(struct symtab *nl)
+{
+ struct symtab *thisnl;
+ usch *osp, *ss2, *base;
+ int c;
+
+ thisnl = NULL;
+ slow = 1;
+ base = osp = stringbuf;
+ goto found;
+
+ while ((c = yylex()) != 0) {
+ switch (c) {
+ case IDENT:
+ if (flslvl)
+ break;
+ osp = stringbuf;
+
+ DPRINT(("IDENT0: %s\n", yytext));
+ nl = lookup((usch *)yytext, FIND);
+ if (nl == 0 || thisnl == 0)
+ goto found;
+ if (thisnl == nl) {
+ nl = 0;
+ goto found;
+ }
+ ss2 = stringbuf;
+ if ((c = yylex()) == WSPACE) {
+ savstr((usch *)yytext);
+ c = yylex();
+ }
+ if (c != EXPAND) {
+ unpstr((usch *)yytext);
+ if (ss2 != stringbuf)
+ unpstr(ss2);
+ unpstr(nl->namep);
+ (void)yylex(); /* get yytext correct */
+ nl = 0; /* ignore */
+ } else {
+ thisnl = NULL;
+ if (nl->value[0] == OBJCT) {
+ unpstr(nl->namep);
+ (void)yylex(); /* get yytext correct */
+ nl = 0;
+ }
+ }
+ stringbuf = ss2;
+
+found: if (nl == 0 || subst(nl, NULL) == 0) {
+ if (nl)
+ savstr(nl->namep);
+ else
+ savstr((usch *)yytext);
+ } else if (osp != stringbuf) {
+ DPRINT(("IDENT1: unput osp %p stringbuf %p\n",
+ osp, stringbuf));
+ ss2 = stringbuf;
+ cunput(EXPAND);
+ while (ss2 > osp)
+ cunput(*--ss2);
+ thisnl = nl;
+ stringbuf = osp; /* clean up heap */
+ }
+ break;
+
+ case EXPAND:
+ DPRINT(("EXPAND!\n"));
+ thisnl = NULL;
+ break;
+
+ case STRING:
+ case '\n':
+ case NUMBER:
+ case FPOINT:
+ case WSPACE:
+ savstr((usch *)yytext);
+ break;
+
+ default:
+ if (c < 256)
+ savch(c);
+ else
+ savstr((usch *)yytext);
+ break;
+ }
+ if (thisnl == NULL) {
+ slow = 0;
+ savch(0);
+ return base;
+ }
+ }
+ error("preamture EOF");
+ /* NOTREACHED */
+ return NULL; /* XXX gcc */
+}
+
+void
+line()
+{
+ static usch *lbuf;
+ static int llen;
+ int c;
+
+ slow = 1;
+ if (yylex() != WSPACE)
+ goto bad;
+ if ((c = yylex()) != IDENT || !isdigit((int)yytext[0]))
+ goto bad;
+ ifiles->lineno = atoi(yytext);
+
+ if ((c = yylex()) != '\n' && c != WSPACE)
+ goto bad;
+ if (c == '\n') {
+ slow = 0;
+ return;
+ }
+ if (yylex() != STRING)
+ goto bad;
+ c = strlen((char *)yytext);
+ if (llen < c) {
+ /* XXX may loose heap space */
+ lbuf = stringbuf;
+ stringbuf += c;
+ llen = c;
+ }
+ yytext[strlen(yytext)-1] = 0;
+ strcpy((char *)lbuf, &yytext[1]);
+ ifiles->fname = lbuf;
+ if (yylex() != '\n')
+ goto bad;
+ slow = 0;
+ return;
+
+bad: error("bad line directive");
+}
+
+/*
+ * Include a file. Include order:
+ * - For <...> files, first search -I directories, then system directories.
+ * - For "..." files, first search "current" dir, then as <...> files.
+ */
+void
+include()
+{
+ struct incs *w;
+ struct symtab *nl;
+ usch *osp;
+ usch *fn;
+ int i, c, it;
+
+ if (flslvl)
+ return;
+ osp = stringbuf;
+ slow = 1;
+ if (yylex() != WSPACE)
+ goto bad;
+again: if ((c = yylex()) != STRING && c != '<' && c != IDENT)
+ goto bad;
+
+ if (c == IDENT) {
+ if ((nl = lookup((usch *)yytext, FIND)) == NULL)
+ goto bad;
+ if (subst(nl, NULL) == 0)
+ goto bad;
+ savch('\0');
+ unpstr(osp);
+ goto again;
+ } else if (c == '<') {
+ fn = stringbuf;
+ while ((c = yylex()) != '>' && c != '\n') {
+ if (c == '\n')
+ goto bad;
+ savstr((usch *)yytext);
+ }
+ savch('\0');
+ while ((c = yylex()) == WSPACE)
+ ;
+ if (c != '\n')
+ goto bad;
+ it = SYSINC;
+ } else {
+ usch *nm = stringbuf;
+
+ yytext[strlen(yytext)-1] = 0;
+ fn = (usch *)&yytext[1];
+ /* first try to open file relative to previous file */
+ /* but only if it is not an absolute path */
+ if (*fn != '/') {
+ savstr(ifiles->orgfn);
+ if ((stringbuf =
+ (usch *)strrchr((char *)nm, '/')) == NULL)
+ stringbuf = nm;
+ else
+ stringbuf++;
+ }
+ savstr(fn); savch(0);
+ while ((c = yylex()) == WSPACE)
+ ;
+ if (c != '\n')
+ goto bad;
+ slow = 0;
+ if (pushfile(nm) == 0)
+ return;
+ stringbuf = nm;
+ }
+
+ /* create search path and try to open file */
+ slow = 0;
+ for (i = 0; i < 2; i++) {
+ for (w = incdir[i]; w; w = w->next) {
+ usch *nm = stringbuf;
+
+ savstr(w->dir); savch('/');
+ savstr(fn); savch(0);
+ if (pushfile(nm) == 0)
+ return;
+ stringbuf = nm;
+ }
+ }
+ error("cannot find '%s'", fn);
+ /* error() do not return */
+
+bad: error("bad include");
+ /* error() do not return */
+}
+
+static int
+definp(void)
+{
+ int c;
+
+ do
+ c = yylex();
+ while (c == WSPACE);
+ return c;
+}
+
+void
+define()
+{
+ struct symtab *np;
+ usch *args[MAXARG], *ubuf, *sbeg;
+ int c, i, redef;
+ int mkstr = 0, narg = -1;
+ int ellips = 0;
+
+ if (flslvl)
+ return;
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ goto bad;
+
+ if (isdigit((int)yytext[0]))
+ goto bad;
+
+ np = lookup((usch *)yytext, ENTER);
+ redef = np->value != NULL;
+
+ sbeg = stringbuf;
+ if ((c = yylex()) == '(') {
+ narg = 0;
+ /* function-like macros, deal with identifiers */
+ for (;;) {
+ c = definp();
+ if (c == ')')
+ break;
+ if (c == ELLIPS) {
+ ellips = 1;
+ if (definp() != ')')
+ goto bad;
+ break;
+ }
+ if (c == IDENT) {
+ args[narg] = alloca(strlen(yytext)+1);
+ strcpy((char *)args[narg], yytext);
+ narg++;
+ if ((c = definp()) == ',')
+ continue;
+ if (c == ')')
+ break;
+ goto bad;
+ }
+ goto bad;
+ }
+ c = yylex();
+ } else if (c == '\n') {
+ /* #define foo */
+ ;
+ } else if (c != WSPACE)
+ goto bad;
+
+ while (c == WSPACE)
+ c = yylex();
+
+ /* parse replacement-list, substituting arguments */
+ savch('\0');
+ while (c != '\n') {
+ switch (c) {
+ case WSPACE:
+ /* remove spaces if it surrounds a ## directive */
+ ubuf = stringbuf;
+ savstr((usch *)yytext);
+ c = yylex();
+ if (c == CONCAT) {
+ stringbuf = ubuf;
+ savch(CONC);
+ if ((c = yylex()) == WSPACE)
+ c = yylex();
+ }
+ continue;
+
+ case CONCAT:
+ /* No spaces before concat op */
+ savch(CONC);
+ if ((c = yylex()) == WSPACE)
+ c = yylex();
+ continue;
+
+ case MKSTR:
+ if (narg < 0) {
+ /* no meaning in object-type macro */
+ savch('#');
+ break;
+ }
+ /* remove spaces between # and arg */
+ savch(SNUFF);
+ if ((c = yylex()) == WSPACE)
+ c = yylex(); /* whitespace, ignore */
+ mkstr = 1;
+ if (c == VA_ARGS)
+ continue;
+
+ /* FALLTHROUGH */
+ case IDENT:
+ if (narg < 0)
+ goto id; /* just add it if object */
+ /* check if its an argument */
+ for (i = 0; i < narg; i++)
+ if (strcmp(yytext, (char *)args[i]) == 0)
+ break;
+ if (i == narg) {
+ if (mkstr)
+ error("not argument");
+ goto id;
+ }
+ savch(i);
+ savch(WARN);
+ if (mkstr)
+ savch(SNUFF), mkstr = 0;
+ break;
+
+ case VA_ARGS:
+ if (ellips == 0)
+ error("unwanted %s", yytext);
+ savch(VARG);
+ savch(WARN);
+ if (mkstr)
+ savch(SNUFF), mkstr = 0;
+ break;
+
+ default:
+id: savstr((usch *)yytext);
+ break;
+ }
+ c = yylex();
+ }
+ /* remove trailing whitespace */
+ while (stringbuf > sbeg) {
+ if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')
+ stringbuf--;
+ else
+ break;
+ }
+ if (ellips) {
+ savch(narg);
+ savch(VARG);
+ } else
+ savch(narg < 0 ? OBJCT : narg);
+ if (redef) {
+ usch *o = np->value, *n = stringbuf-1;
+
+ /* Redefinition to identical replacement-list is allowed */
+ while (*o && *o == *n)
+ o--, n--;
+ if (*o || *o != *n)
+ error("%s redefined\nprevious define: %s:%d",
+ np->namep, np->file, np->line);
+ stringbuf = sbeg; /* forget this space */
+ } else
+ np->value = stringbuf-1;
+
+#ifdef CPP_DEBUG
+ if (dflag) {
+ usch *w = np->value;
+
+ printf("!define: ");
+ if (*w == OBJCT)
+ printf("[object]");
+ else if (*w == VARG)
+ printf("[VARG%d]", *--w);
+ while (*--w) {
+ switch (*w) {
+ case WARN: printf("<%d>", *--w); break;
+ case CONC: printf("<##>"); break;
+ case SNUFF: printf("<\">"); break;
+ default: putchar(*w); break;
+ }
+ }
+ putchar('\n');
+ }
+#endif
+ slow = 0;
+ return;
+
+bad: error("bad define");
+}
+
+void
+xerror(usch *s)
+{
+ usch *t;
+
+ flbuf();
+ savch(0);
+ if (ifiles != NULL) {
+ t = sheap("%s:%d: ", ifiles->fname, ifiles->lineno);
+ write (2, t, strlen((char *)t));
+ }
+ write (2, s, strlen((char *)s));
+ write (2, "\n", 1);
+ exit(1);
+}
+
+/*
+ * store a character into the "define" buffer.
+ */
+void
+savch(c)
+{
+ if (stringbuf-sbf < SBSIZE) {
+ *stringbuf++ = c;
+ } else {
+ stringbuf = sbf; /* need space to write error message */
+ error("Too much defining");
+ }
+}
+
+/*
+ * substitute namep for sp->value.
+ */
+int
+subst(sp, rp)
+struct symtab *sp;
+struct recur *rp;
+{
+ struct recur rp2;
+ register usch *vp, *cp;
+ int c, rv = 0, ws;
+
+ DPRINT(("subst: %s\n", sp->namep));
+ /*
+ * First check for special macros.
+ */
+ if (sp == filloc) {
+ (void)sheap("\"%s\"", ifiles->fname);
+ return 1;
+ } else if (sp == linloc) {
+ (void)sheap("%d", ifiles->lineno);
+ return 1;
+ }
+ vp = sp->value;
+
+ rp2.next = rp;
+ rp2.sp = sp;
+
+ if (*vp-- != OBJCT) {
+ int gotwarn = 0;
+
+ /* should we be here at all? */
+ /* check if identifier is followed by parentheses */
+ rv = 1;
+ ws = 0;
+ do {
+ c = yylex();
+ if (c == WARN) {
+ gotwarn++;
+ if (rp == NULL)
+ goto noid;
+ } else if (c == WSPACE)
+ ws = 1;
+ } while (c == WSPACE || c == '\n' || c == WARN);
+
+ cp = (usch *)yytext;
+ while (*cp)
+ cp++;
+ while (cp > (usch *)yytext)
+ cunput(*--cp);
+ DPRINT(("c %d\n", c));
+ if (c == '(' ) {
+ expdef(vp, &rp2, gotwarn);
+ return rv;
+ } else {
+ /* restore identifier */
+noid: while (gotwarn--)
+ cunput(WARN);
+ if (ws)
+ cunput(' ');
+ cp = sp->namep;
+ while (*cp)
+ cp++;
+ while (cp > sp->namep)
+ cunput(*--cp);
+ if ((c = yylex()) != IDENT)
+ error("internal sync error");
+ return 0;
+ }
+ } else {
+ cunput(WARN);
+ cp = vp;
+ while (*cp) {
+ if (*cp != CONC)
+ cunput(*cp);
+ cp--;
+ }
+ expmac(&rp2);
+ }
+ return 1;
+}
+
+/*
+ * do macro-expansion until WARN character read.
+ * read from lex buffer and store result on heap.
+ * will recurse into lookup() for recursive expansion.
+ * when returning all expansions on the token list is done.
+ */
+void
+expmac(struct recur *rp)
+{
+ struct symtab *nl;
+ int c, noexp = 0, orgexp;
+ usch *och, *stksv;
+ extern int yyleng;
+
+#ifdef CPP_DEBUG
+ if (dflag) {
+ struct recur *rp2 = rp;
+ printf("\nexpmac\n");
+ while (rp2) {
+ printf("do not expand %s\n", rp->sp->namep);
+ rp2 = rp2->next;
+ }
+ }
+#endif
+ while ((c = yylex()) != WARN) {
+ switch (c) {
+ case NOEXP: noexp++; break;
+ case EXPAND: noexp--; break;
+
+ case IDENT:
+ /*
+ * Handle argument concatenation here.
+ * If an identifier is found and directly
+ * after EXPAND or NOEXP then push the
+ * identifier back on the input stream and
+ * call yylex() again.
+ * Be careful to keep the noexp balance.
+ */
+ och = stringbuf;
+ savstr((usch *)yytext);
+ DDPRINT(("id: str %s\n", och));
+
+ orgexp = 0;
+ while ((c = yylex()) == EXPAND || c == NOEXP)
+ if (c == EXPAND)
+ orgexp--;
+ else
+ orgexp++;
+
+ DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp));
+ if (c == IDENT) { /* XXX numbers? */
+ DDPRINT(("id2: str %s\n", yytext));
+ /* OK to always expand here? */
+ savstr((usch *)yytext);
+ switch (orgexp) {
+ case 0: /* been EXP+NOEXP */
+ if (noexp == 0)
+ break;
+ if (noexp != 1)
+ error("case 0");
+ cunput(NOEXP);
+ noexp = 0;
+ break;
+ case -1: /* been EXP */
+ if (noexp != 1)
+ error("case -1");
+ noexp = 0;
+ break;
+ case 1:
+ if (noexp != 0)
+ error("case 1");
+ cunput(NOEXP);
+ break;
+ default:
+ error("orgexp = %d", orgexp);
+ }
+ unpstr(och);
+ stringbuf = och;
+ continue; /* New longer identifier */
+ }
+ unpstr((usch *)yytext);
+ if (orgexp == -1)
+ cunput(EXPAND);
+ else if (orgexp == 1)
+ cunput(NOEXP);
+ unpstr(och);
+ stringbuf = och;
+
+
+ yylex(); /* XXX reget last identifier */
+
+ if ((nl = lookup((usch *)yytext, FIND)) == NULL)
+ goto def;
+
+ if (canexpand(rp, nl) == 0)
+ goto def;
+ /*
+ * If noexp == 0 then expansion of any macro is
+ * allowed. If noexp == 1 then expansion of a
+ * fun-like macro is allowed iff there is an
+ * EXPAND between the identifier and the '('.
+ */
+ if (noexp == 0) {
+ if ((c = subst(nl, rp)) == 0)
+ goto def;
+ break;
+ }
+//printf("noexp1 %d nl->namep %s\n", noexp, nl->namep);
+//if (noexp > 1) goto def;
+ if (noexp != 1)
+ error("bad noexp %d", noexp);
+ stksv = NULL;
+ if ((c = yylex()) == WSPACE) {
+ stksv = alloca(yyleng+1);
+ strcpy((char *)stksv, yytext);
+ c = yylex();
+ }
+ /* only valid for expansion if fun macro */
+ if (c == EXPAND && *nl->value != OBJCT) {
+ noexp--;
+ if (subst(nl, rp))
+ break;
+ savstr(nl->namep);
+ if (stksv)
+ savstr(stksv);
+ } else {
+ unpstr((usch *)yytext);
+ if (stksv)
+ unpstr(stksv);
+ savstr(nl->namep);
+ }
+ break;
+
+ case STRING:
+ /* remove EXPAND/NOEXP from strings */
+ if (yytext[1] == NOEXP) {
+ savch('"');
+ och = (usch *)&yytext[2];
+ while (*och != EXPAND)
+ savch(*och++);
+ savch('"');
+ break;
+ }
+ /* FALLTHROUGH */
+
+def: default:
+ savstr((usch *)yytext);
+ break;
+ }
+ }
+ if (noexp)
+ error("expmac noexp=%d", noexp);
+ DPRINT(("return from expmac\n"));
+}
+
+/*
+ * expand a function-like macro.
+ * vp points to end of replacement-list
+ * reads function arguments from yylex()
+ * result is written on top of heap
+ */
+void
+expdef(vp, rp, gotwarn)
+ usch *vp;
+ struct recur *rp;
+{
+ usch **args, *sptr, *ap, *bp, *sp;
+ int narg, c, i, plev, snuff, instr;
+ int ellips = 0;
+
+ DPRINT(("expdef %s rp %s\n", vp, (rp ? (char *)rp->sp->namep : "")));
+ if ((c = yylex()) != '(')
+ error("got %c, expected )", c);
+ if (vp[1] == VARG) {
+ narg = *vp--;
+ ellips = 1;
+ } else
+ narg = vp[1];
+ args = alloca(sizeof(usch *) * (narg+ellips));
+
+ /*
+ * read arguments and store them on heap.
+ * will be removed just before return from this function.
+ */
+ sptr = stringbuf;
+ for (i = 0; i < narg && c != ')'; i++) {
+ args[i] = stringbuf;
+ plev = 0;
+ while ((c = yylex()) == WSPACE || c == '\n')
+ ;
+ for (;;) {
+ if (plev == 0 && (c == ')' || c == ','))
+ break;
+ if (c == '(')
+ plev++;
+ if (c == ')')
+ plev--;
+ savstr((usch *)yytext);
+ while ((c = yylex()) == '\n')
+ savch('\n');
+ }
+ while (args[i] < stringbuf &&
+ (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
+ stringbuf--;
+ savch('\0');
+ }
+ if (ellips)
+ args[i] = (usch *)"";
+ if (ellips && c != ')') {
+ args[i] = stringbuf;
+ plev = 0;
+ while ((c = yylex()) == WSPACE)
+ ;
+ for (;;) {
+ if (plev == 0 && c == ')')
+ break;
+ if (c == '(')
+ plev++;
+ if (c == ')')
+ plev--;
+ savstr((usch *)yytext);
+ while ((c = yylex()) == '\n')
+ savch('\n');
+ }
+ while (args[i] < stringbuf &&
+ (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
+ stringbuf--;
+ savch('\0');
+
+ }
+ if (narg == 0 && ellips == 0)
+ c = yylex();
+ if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
+ error("wrong arg count");
+
+ while (gotwarn--)
+ cunput(WARN);
+
+ sp = vp;
+ instr = snuff = 0;
+
+ /*
+ * push-back replacement-list onto lex buffer while replacing
+ * arguments.
+ */
+ cunput(WARN);
+ while (*sp != 0) {
+ if (*sp == SNUFF)
+ cunput('\"'), snuff ^= 1;
+ else if (*sp == CONC)
+ ;
+ else if (*sp == WARN) {
+
+ if (sp[-1] == VARG) {
+ bp = ap = args[narg];
+ sp--;
+ } else
+ bp = ap = args[(int)*--sp];
+ if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
+ cunput(WARN);
+ while (*bp)
+ bp++;
+ while (bp > ap)
+ cunput(*--bp);
+ DPRINT(("expand arg %d string %s\n", *sp, ap));
+ bp = ap = stringbuf;
+ savch(NOEXP);
+ expmac(NULL);
+ savch(EXPAND);
+ savch('\0');
+ }
+ while (*bp)
+ bp++;
+ while (bp > ap) {
+ bp--;
+ if (snuff && !instr &&
+ (*bp == ' ' || *bp == '\t' || *bp == '\n')){
+ while (*bp == ' ' || *bp == '\t' ||
+ *bp == '\n') {
+ bp--;
+ }
+ cunput(' ');
+ }
+ cunput(*bp);
+ if ((*bp == '\'' || *bp == '"')
+ && bp[-1] != '\\' && snuff) {
+ instr ^= 1;
+ if (instr == 0 && *bp == '"')
+ cunput('\\');
+ }
+ if (instr && (*bp == '\\' || *bp == '"'))
+ cunput('\\');
+ }
+ } else
+ cunput(*sp);
+ sp--;
+ }
+ stringbuf = sptr;
+
+ /* scan the input buffer (until WARN) and save result on heap */
+ expmac(rp);
+}
+
+usch *
+savstr(usch *str)
+{
+ usch *rv = stringbuf;
+
+ do {
+ if (stringbuf >= &sbf[SBSIZE]) {
+ stringbuf = sbf; /* need space to write error message */
+ error("out of macro space!");
+ }
+ } while ((*stringbuf++ = *str++));
+ stringbuf--;
+ return rv;
+}
+
+int
+canexpand(struct recur *rp, struct symtab *np)
+{
+ struct recur *w;
+
+ for (w = rp; w && w->sp != np; w = w->next)
+ ;
+ if (w != NULL)
+ return 0;
+ return 1;
+}
+
+void
+unpstr(usch *c)
+{
+ usch *d = c;
+
+ while (*d)
+ d++;
+ while (d > c) {
+ cunput(*--d);
+ }
+}
+
+void
+flbuf()
+{
+ if (obufp == 0)
+ return;
+ if (Mflag == 0 && write(ofd, outbuf, obufp) < 0)
+ error("obuf write error");
+ obufp = 0;
+}
+
+void
+putch(int ch)
+{
+ outbuf[obufp++] = ch;
+ if (obufp == CPPBUF || (istty && ch == '\n'))
+ flbuf();
+}
+
+void
+putstr(usch *s)
+{
+ for (; *s; s++) {
+ outbuf[obufp++] = *s;
+ if (obufp == CPPBUF || (istty && *s == '\n'))
+ flbuf();
+ }
+}
+
+/*
+ * convert a number to an ascii string. Store it on the heap.
+ */
+static void
+num2str(int num)
+{
+ static usch buf[12];
+ usch *b = buf;
+ int m = 0;
+
+ if (num < 0)
+ num = -num, m = 1;
+ do {
+ *b++ = num % 10 + '0', num /= 10;
+ } while (num);
+ if (m)
+ *b++ = '-';
+ while (b > buf)
+ savch(*--b);
+}
+
+/*
+ * similar to sprintf, but only handles %s and %d.
+ * saves result on heap.
+ */
+usch *
+sheap(char *fmt, ...)
+{
+ va_list ap;
+ usch *op = stringbuf;
+
+ va_start(ap, fmt);
+ for (; *fmt; fmt++) {
+ if (*fmt == '%') {
+ fmt++;
+ switch (*fmt) {
+ case 's':
+ savstr(va_arg(ap, usch *));
+ break;
+ case 'd':
+ num2str(va_arg(ap, int));
+ break;
+ case 'c':
+ savch(va_arg(ap, int));
+ break;
+ default:
+ break; /* cannot call error() here */
+ }
+ } else
+ savch(*fmt);
+ }
+ va_end(ap);
+ *stringbuf = 0;
+ return op;
+}
+
+void
+usage()
+{
+ error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]");
+}
+
+#ifdef notyet
+/*
+ * Symbol table stuff.
+ * The data structure used is a patricia tree implementation using only
+ * bytes to store offsets.
+ * The information stored is (lower address to higher):
+ *
+ * unsigned char bitno[2]; bit number in the string
+ * unsigned char left[3]; offset from base to left element
+ * unsigned char right[3]; offset from base to right element
+ */
+#endif
+
+/*
+ * This patricia implementation is more-or-less the same as
+ * used in ccom for string matching.
+ */
+struct tree {
+ int bitno;
+ struct tree *lr[2];
+};
+
+#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
+#define LEFT_IS_LEAF 0x80000000
+#define RIGHT_IS_LEAF 0x40000000
+#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
+#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
+#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
+#define CHECKBITS 8
+
+static struct tree *sympole;
+static int numsyms;
+
+#define getree() malloc(sizeof(struct tree))
+
+/*
+ * Allocate a symtab struct and store the string.
+ */
+static struct symtab *
+getsymtab(usch *str)
+{
+ struct symtab *sp = malloc(sizeof(struct symtab));
+
+ sp->namep = savstr(str), savch('\0');
+ sp->value = NULL;
+ sp->file = ifiles ? ifiles->orgfn : (usch *)"<initial>";
+ sp->line = ifiles ? ifiles->lineno : 0;
+ return sp;
+}
+
+/*
+ * Do symbol lookup in a patricia tree.
+ * Only do full string matching, no pointer optimisations.
+ */
+struct symtab *
+lookup(usch *key, int enterf)
+{
+ struct symtab *sp;
+ struct tree *w, *new, *last;
+ int len, cix, bit, fbit, svbit, ix, bitno;
+ usch *k, *m, *sm;
+
+ /* Count full string length */
+ for (k = key, len = 0; *k; k++, len++)
+ ;
+
+ switch (numsyms) {
+ case 0: /* no symbols yet */
+ if (enterf != ENTER)
+ return NULL;
+ sympole = (struct tree *)getsymtab(key);
+ numsyms++;
+ return (struct symtab *)sympole;
+
+ case 1:
+ w = sympole;
+ svbit = 0; /* XXX gcc */
+ break;
+
+ default:
+ w = sympole;
+ bitno = len * CHECKBITS;
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = bit > bitno ? 0 : P_BIT(key, bit);
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit)
+ break;
+ }
+ }
+
+ sp = (struct symtab *)w;
+
+ sm = m = sp->namep;
+ k = key;
+
+ /* Check for correct string and return */
+ for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
+ ;
+ if (*m == 0 && *k == 0) {
+ if (enterf != ENTER && sp->value == NULL)
+ return NULL;
+ return sp;
+ }
+
+ if (enterf != ENTER)
+ return NULL; /* no string found and do not enter */
+
+ ix = *m ^ *k;
+ while ((ix & 1) == 0)
+ ix >>= 1, cix++;
+
+ /* Create new node */
+ new = getree();
+ bit = P_BIT(key, cix);
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)getsymtab(key);
+
+ if (numsyms++ == 1) {
+ new->lr[!bit] = sympole;
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ sympole = new;
+ return (struct symtab *)new->lr[bit];
+ }
+
+ w = sympole;
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ error("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = P_BIT(key, bitno);
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ sympole = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (struct symtab *)new->lr[bit];
+}
+
diff --git a/usr.bin/pcc/cc/cpp/cpp.h b/usr.bin/pcc/cc/cpp/cpp.h
new file mode 100644
index 00000000000..ad57e9d3cd8
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/cpp.h
@@ -0,0 +1,120 @@
+/* $Id: cpp.h,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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 <stdio.h> /* for obuf */
+
+#include "../../config.h"
+
+typedef unsigned char usch;
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#else
+extern char yytext[];
+#endif
+extern usch *stringbuf;
+
+extern int trulvl;
+extern int flslvl;
+extern int elflvl;
+extern int elslvl;
+extern int tflag, Cflag;
+extern int Mflag;
+extern usch *Mfile;
+extern int ofd;
+
+/* args for lookup() */
+#define FIND 0
+#define ENTER 1
+
+/* buffer used internally */
+#ifndef CPPBUF
+#ifdef __pdp11__
+#define CPPBUF BUFSIZ
+#else
+#define CPPBUF 65536
+#endif
+#endif
+
+#define NAMEMAX 64 /* max len of identifier */
+
+/* definition for include file info */
+struct includ {
+ struct includ *next;
+ usch *fname; /* current fn, changed if #line found */
+ usch *orgfn; /* current fn, not changed */
+ int lineno;
+ int infil;
+ usch *curptr;
+ usch *maxread;
+ usch *buffer;
+ usch bbuf[NAMEMAX+CPPBUF+1];
+} *ifiles;
+
+/* Symbol table entry */
+struct symtab {
+ usch *namep;
+ usch *value;
+ usch *file;
+ int line;
+};
+
+struct initar {
+ struct initar *next;
+ int type;
+ char *str;
+};
+
+struct recur; /* not used outside cpp.c */
+int subst(struct symtab *, struct recur *);
+struct symtab *lookup(usch *namep, int enterf);
+usch *gotident(struct symtab *nl);
+int slow; /* scan slowly for new tokens */
+
+int pushfile(usch *fname);
+void popfile(void);
+void prtline(void);
+int yylex(void);
+void cunput(int);
+int curline(void);
+char *curfile(void);
+void setline(int);
+void setfile(char *);
+int yyparse(void);
+void yyerror(char *);
+void unpstr(usch *);
+usch *savstr(usch *str);
+void savch(int c);
+void mainscan(void);
+void putch(int);
+void putstr(usch *s);
+void line(void);
+usch *sheap(char *fmt, ...);
+void xerror(usch *);
+#define error(...) xerror(sheap(__VA_ARGS__))
+void expmac(struct recur *);
diff --git a/usr.bin/pcc/cc/cpp/cpy.y b/usr.bin/pcc/cc/cpp/cpy.y
new file mode 100644
index 00000000000..2f39c920306
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/cpy.y
@@ -0,0 +1,166 @@
+/* $Id: cpy.y,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * 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.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+void yyerror(char *);
+int yylex(void);
+%}
+
+%term stop
+%term EQ NE LE GE LS RS
+%term ANDAND OROR IDENT NUMBER
+/*
+ * The following terminals are not used in the yacc code.
+ */
+%term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS
+
+%left ','
+%right '='
+%right '?' ':'
+%left OROR
+%left ANDAND
+%left '|' '^'
+%left '&'
+%binary EQ NE
+%binary '<' '>' LE GE
+%left LS RS
+%left '+' '-'
+%left '*' '/' '%'
+%right '!' '~' UMINUS
+%left '(' '.'
+
+%union {
+ long long val;
+}
+
+%type <val> term NUMBER e
+
+%%
+S: e '\n' { return($1 != 0);}
+
+
+e: e '*' e
+ {$$ = $1 * $3;}
+ | e '/' e
+ {$$ = $1 / $3;}
+ | e '%' e
+ {$$ = $1 % $3;}
+ | e '+' e
+ {$$ = $1 + $3;}
+ | e '-' e
+ {$$ = $1 - $3;}
+ | e LS e
+ {$$ = $1 << $3;}
+ | e RS e
+ {$$ = $1 >> $3;}
+ | e '<' e
+ {$$ = $1 < $3;}
+ | e '>' e
+ {$$ = $1 > $3;}
+ | e LE e
+ {$$ = $1 <= $3;}
+ | e GE e
+ {$$ = $1 >= $3;}
+ | e EQ e
+ {$$ = $1 == $3;}
+ | e NE e
+ {$$ = $1 != $3;}
+ | e '&' e
+ {$$ = $1 & $3;}
+ | e '^' e
+ {$$ = $1 ^ $3;}
+ | e '|' e
+ {$$ = $1 | $3;}
+ | e ANDAND e
+ {$$ = $1 && $3;}
+ | e OROR e
+ {$$ = $1 || $3;}
+ | e '?' e ':' e
+ {$$ = $1 ? $3 : $5;}
+ | e ',' e
+ {$$ = $3;}
+ | term
+ {$$ = $1;}
+term:
+ '-' term %prec UMINUS
+ {$$ = -$2;}
+ | '!' term
+ {$$ = !$2;}
+ | '~' term
+ {$$ = ~$2;}
+ | '(' e ')'
+ {$$ = $2;}
+ | NUMBER
+ {$$= $1;}
+%%
+
+#include "cpp.h"
+
+void
+yyerror(char *err)
+{
+ error(err);
+}
diff --git a/usr.bin/pcc/cc/cpp/scanner.l b/usr.bin/pcc/cc/cpp/scanner.l
new file mode 100644
index 00000000000..87d4a5285af
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/scanner.l
@@ -0,0 +1,808 @@
+%{
+/* $Id: scanner.l,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson. 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cpp.h"
+#include "y.tab.h"
+%}
+
+%{
+static long long cvtdig(int rad);
+static int charcon(void);
+static void elsestmt(void);
+static void ifdefstmt(void);
+static void ifndefstmt(void);
+static void endifstmt(void);
+static void ifstmt(void);
+static void cpperror(void);
+static void pragmastmt(void);
+static void undefstmt(void);
+static void cpperror(void);
+static void elifstmt(void);
+//static void linestmt(void);
+static void storepb(void);
+void include(void);
+void define(void);
+
+static int inch(void);
+
+static int scale, gotdef, contr;
+int inif;
+
+#ifdef FLEX_SCANNER /* should be set by autoconf instead */
+static int
+yyinput(char *b, int m)
+{
+ int c, i;
+
+ for (i = 0; i < m; i++) {
+ if ((c = inch()) < 0)
+ break;
+ *b++ = c;
+ if (c == '\n') {
+ i++;
+ break;
+ }
+ }
+ return i;
+}
+#undef YY_INPUT
+#undef YY_BUF_SIZE
+#define YY_BUF_SIZE 32768
+#define YY_INPUT(b,r,m) (r = yyinput(b, m))
+#define fprintf(x, ...) error(__VA_ARGS__)
+#define ECHO putstr((usch *)yytext)
+#undef fileno
+#define fileno(x) 0
+
+#if YY_FLEX_SUBMINOR_VERSION >= 31
+/* Hack to avoid unneccessary warnings */
+FILE *yyget_in (void);
+FILE *yyget_out (void);
+int yyget_leng (void);
+char *yyget_text (void);
+void yyset_in (FILE * in_str );
+void yyset_out (FILE * out_str );
+int yyget_debug (void);
+void yyset_debug (int bdebug );
+int yylex_destroy (void);
+#endif
+#else /* Assume lex here */
+#undef input
+#undef unput
+#define input() inch()
+#define unput(ch) unch(ch)
+#endif
+#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext);
+%}
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+FS (f|F|l|L)
+IS (u|U|l|L)*
+WS [\t ]
+
+%s IFR CONTR DEF
+
+%%
+
+"\n" { int os = YYSTATE;
+ if (os != IFR)
+ BEGIN 0;
+ ifiles->lineno++;
+ if (flslvl == 0) {
+ if (ifiles->lineno == 1)
+ prtline();
+ else
+ putch('\n');
+ }
+ if ((os != 0 || slow) && !contr)
+ return '\n';
+ contr = 0;
+ }
+
+"\r" { ; /* Ignore CR's */ }
+
+<IFR>"==" { return EQ; }
+<IFR>"!=" { return NE; }
+<IFR>"<=" { return LE; }
+<IFR>"<<" { return LS; }
+<IFR>">>" { return RS; }
+<IFR>">=" { return GE; }
+<IFR>"||" { return OROR; }
+<IFR>"&&" { return ANDAND; }
+<IFR>"defined" { int p, c;
+ gotdef = 1;
+ if ((p = c = yylex()) == '(')
+ c = yylex();
+ if (c != IDENT || (p != IDENT && p != '('))
+ error("syntax error");
+ if (p == '(' && yylex() != ')')
+ error("syntax error");
+ return NUMBER;
+ }
+
+<IFR>{WS}+ { ; }
+<IFR>{L}({L}|{D})* {
+ if (gotdef) {
+ yylval.val =
+ lookup((usch *)yytext, FIND) != 0;
+ gotdef = 0;
+ return IDENT;
+ }
+ yylval.val = 0;
+ return NUMBER;
+ }
+
+[1-9][0-9]* { if (slow && !YYSTATE) return IDENT; scale = 10; goto num; }
+
+0[xX]{H}+{IS}? { scale = 16;
+ num: if (YYSTATE)
+ yylval.val = cvtdig(scale);
+ PRTOUT(NUMBER);
+ }
+0{D}+{IS}? { scale = 8; goto num; }
+{D}+{IS}? { scale = 10; goto num; }
+L?'(\\.|[^\\'])+' { if (YYSTATE)
+ yylval.val = charcon();
+ PRTOUT(NUMBER);
+ }
+
+<IFR>. { return yytext[0]; }
+
+{D}+{E}{FS}? { PRTOUT(FPOINT); }
+{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
+{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
+
+^{WS}*#{WS}* { contr = 1; BEGIN CONTR; }
+{WS}+ { PRTOUT(WSPACE); }
+
+<CONTR>"ifndef" { contr = 0; ifndefstmt(); }
+<CONTR>"ifdef" { contr = 0; ifdefstmt(); }
+<CONTR>"if"{WS}+ { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; }
+<CONTR>"include" { contr = 0; BEGIN 0; include(); prtline(); }
+<CONTR>"else" { contr = 0; elsestmt(); }
+<CONTR>"endif" { contr = 0; endifstmt(); }
+<CONTR>"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; }
+<CONTR>"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; }
+<CONTR>"undef" { contr = 0; if (slow) return IDENT; undefstmt(); }
+<CONTR>"line" { contr = 0; storepb(); BEGIN 0; line(); }
+<CONTR>"pragma" { contr = 0; pragmastmt(); }
+<CONTR>"elif"{WS}+ { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; }
+
+
+
+"//".*$ { /* if (tflag) yyless(..) */
+ if (Cflag)
+ putstr((usch *)yytext);
+ else if (!flslvl)
+ putch(' ');
+ }
+"/*" { int c, wrn;
+ if (Cflag)
+ putstr((usch *)yytext);
+ wrn = 0;
+ more: while ((c = input()) && c != '*') {
+ if (c == '\n')
+ putch(c), ifiles->lineno++;
+ else if (c == 1) /* WARN */
+ wrn = 1;
+ else if (Cflag)
+ putch(c);
+ }
+ if (c == 0)
+ return 0;
+ if (Cflag)
+ putch(c);
+ if ((c = input()) && c != '/') {
+ if (Cflag)
+ putch('*');
+ unput(c);
+ goto more;
+ }
+ if (Cflag)
+ putch(c);
+ if (c == 0)
+ return 0;
+ if (!tflag && !Cflag && !flslvl)
+ unput(' ');
+ if (wrn)
+ unput(1);
+ }
+
+<DEF>"##" { return CONCAT; }
+<DEF>"#" { return MKSTR; }
+<DEF>"..." { return ELLIPS; }
+<DEF>"__VA_ARGS__" { return VA_ARGS; }
+
+L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); }
+[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */
+ struct symtab *nl;
+ if (slow)
+ return IDENT;
+ if (YYSTATE == CONTR) {
+ if (flslvl == 0) {
+ /*error("undefined control");*/
+ while (input() != '\n')
+ ;
+ unput('\n');
+ BEGIN 0;
+ goto xx;
+ } else {
+ BEGIN 0; /* do nothing */
+ }
+ }
+ if (flslvl) {
+ ; /* do nothing */
+ } else if (isdigit((int)yytext[0]) == 0 &&
+ (nl = lookup((usch *)yytext, FIND)) != 0) {
+ usch *op = stringbuf;
+ putstr(gotident(nl));
+ stringbuf = op;
+ } else
+ putstr((usch *)yytext);
+ xx: ;
+ }
+
+. { PRTOUT(yytext[0]); }
+
+%%
+
+usch *yyp, yybuf[CPPBUF];
+
+int yylex(void);
+int yywrap(void);
+
+static int
+inpch(void)
+{
+ int len;
+
+ if (ifiles->curptr < ifiles->maxread)
+ return *ifiles->curptr++;
+
+ if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
+ error("read error on file %s", ifiles->orgfn);
+ if (len == 0)
+ return -1;
+ ifiles->curptr = ifiles->buffer;
+ ifiles->maxread = ifiles->buffer + len;
+ return inpch();
+}
+
+#define unch(c) *--ifiles->curptr = c
+
+static int
+inch(void)
+{
+ int c;
+
+again: switch (c = inpch()) {
+ case '\\': /* continued lines */
+ if ((c = inpch()) == '\n') {
+ ifiles->lineno++;
+ putch('\n');
+ goto again;
+ }
+ unch(c);
+ return '\\';
+ case '?': /* trigraphs */
+ if ((c = inpch()) != '?') {
+ unch(c);
+ return '?';
+ }
+ switch (c = inpch()) {
+ case '=': c = '#'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '!': c = '|'; break;
+ case '-': c = '~'; break;
+ default:
+ unch(c);
+ unch('?');
+ return '?';
+ }
+ unch(c);
+ goto again;
+ default:
+ return c;
+ }
+}
+
+/*
+ * Let the command-line args be faked defines at beginning of file.
+ */
+static void
+prinit(struct initar *it, struct includ *ic)
+{
+ char *a, *pre, *post;
+
+ if (it->next)
+ prinit(it->next, ic);
+ pre = post = NULL; /* XXX gcc */
+ switch (it->type) {
+ case 'D':
+ pre = "#define ";
+ if ((a = strchr(it->str, '=')) != NULL) {
+ *a = ' ';
+ post = "\n";
+ } else
+ post = " 1\n";
+ break;
+ case 'U':
+ pre = "#undef ";
+ post = "\n";
+ break;
+ case 'i':
+ pre = "#include \"";
+ post = "\"\n";
+ break;
+ }
+ strcat((char *)ic->buffer, pre);
+ strcat((char *)ic->buffer, it->str);
+ strcat((char *)ic->buffer, post);
+ ic->lineno--;
+ while (*ic->maxread)
+ ic->maxread++;
+}
+
+/*
+ * A new file included.
+ * If ifiles == NULL, this is the first file and already opened (stdin).
+ * Return 0 on success, -1 on failure to open file.
+ */
+int
+pushfile(usch *file)
+{
+ extern struct initar *initar;
+ struct includ ibuf;
+ struct includ *old;
+ struct includ *ic;
+ int c, otrulvl;
+
+ ic = &ibuf;
+ old = ifiles;
+
+ slow = 0;
+ if (file != NULL) {
+ if ((ic->infil = open((char *)file, O_RDONLY)) < 0)
+ return -1;
+ ic->orgfn = ic->fname = file;
+ } else {
+ ic->infil = 0;
+ ic->orgfn = ic->fname = (usch *)"<stdin>";
+ }
+ ic->buffer = ic->bbuf+NAMEMAX;
+ ic->curptr = ic->buffer;
+ ifiles = ic;
+ ic->lineno = 1;
+ ic->maxread = ic->curptr;
+ prtline();
+ if (initar) {
+ *ic->maxread = 0;
+ prinit(initar, ic);
+ initar = NULL;
+ }
+#if 0
+ if (old == NULL && ifile != NULL) {
+ strcpy((char *)ic->buffer, "#include \"");
+ strcat((char *)ic->buffer, ifile);
+ strcat((char *)ic->buffer, "\"\n");
+ while (*ic->maxread)
+ ic->maxread++;
+ ic->lineno = 0;
+ ifile = NULL;
+ }
+#endif
+
+ otrulvl = trulvl;
+
+ if ((c = yylex()) != 0)
+ error("yylex returned %d", c);
+
+ if (otrulvl != trulvl || flslvl)
+ error("unterminated conditional");
+
+ ifiles = old;
+ close(ic->infil);
+ return 0;
+}
+
+/*
+ * Print current position to output file.
+ */
+void
+prtline()
+{
+ usch *s, *os = stringbuf;
+
+ if (Mflag) {
+ if (ifiles->lineno == 1) {
+ s = sheap("%s: %s\n", Mfile, ifiles->fname);
+ write(ofd, s, strlen((char *)s));
+ }
+ } else
+ putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
+ stringbuf = os;
+}
+
+void
+cunput(int c)
+{
+#ifdef CPP_DEBUG
+ extern int dflag;
+ if (dflag)printf(": '%c'(%d)", c, c);
+#endif
+ unput(c);
+}
+
+int yywrap(void) { return 1; }
+
+static int
+dig2num(int c)
+{
+ if (c >= 'a')
+ c = c - 'a' + 10;
+ else if (c >= 'A')
+ c = c - 'A' + 10;
+ else
+ c = c - '0';
+ return c;
+}
+
+/*
+ * Convert some string numbers to long long.
+ * Do not care about UL trailers, should we?
+ */
+static long long
+cvtdig(int rad)
+{
+ long long rv = 0;
+ char *y = yytext;
+ int c;
+
+ c = *y++;
+ if (rad == 16)
+ y++;
+ while (isxdigit(c)) {
+ rv = rv * rad + dig2num(c);
+ c = *y++;
+ }
+ return rv;
+}
+
+static int
+charcon(void)
+{
+ usch *p = (usch *)yytext;
+ int val, c;
+
+ if (*p == 'L')
+ p++;
+ p++; /* first ' */
+ val = 0;
+ if (*p++ == '\\') {
+ switch (*p++) {
+ case 'a': val = '\a'; break;
+ case 'b': val = '\b'; break;
+ case 'f': val = '\f'; break;
+ case 'n': val = '\n'; break;
+ case 'r': val = '\r'; break;
+ case 't': val = '\t'; break;
+ case 'v': val = '\v'; break;
+ case '\"': val = '\"'; break;
+ case '\'': val = '\''; break;
+ case '\\': val = '\\'; break;
+ case 'x':
+ while (isxdigit(c = *p)) {
+ val = val * 16 + dig2num(c);
+ p++;
+ }
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7':
+ p--;
+ while (isdigit(c = *p)) {
+ val = val * 8 + (c - '0');
+ p++;
+ }
+ break;
+ default: val = p[-1];
+ }
+
+ } else
+ val = p[-1];
+ return val;
+}
+
+static void
+chknl(void)
+{
+ int t;
+
+ while ((t = yylex()) == WSPACE)
+ ;
+ if (t != '\n')
+ error("newline expected, got %d", t);
+}
+
+static void
+elsestmt(void)
+{
+ if (flslvl) {
+ if (elflvl > trulvl)
+ ;
+ else if (--flslvl!=0) {
+ flslvl++;
+ } else {
+ trulvl++;
+ prtline();
+ }
+ } else if (trulvl) {
+ flslvl++;
+ trulvl--;
+ } else
+ error("If-less else");
+ if (elslvl==trulvl+flslvl)
+ error("Too many else");
+ elslvl=trulvl+flslvl;
+ chknl();
+}
+
+static void
+ifdefstmt(void)
+{
+ if (flslvl) {
+ /* just ignore the rest of the line */
+ while (input() != '\n')
+ ;
+ unput('\n');
+ yylex();
+ flslvl++;
+ return;
+ }
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ error("bad ifdef");
+ slow = 0;
+ if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0)
+ trulvl++;
+ else
+ flslvl++;
+ chknl();
+}
+
+static void
+ifndefstmt(void)
+{
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ error("bad ifndef");
+ slow = 0;
+ if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0)
+ trulvl++;
+ else
+ flslvl++;
+ chknl();
+}
+
+static void
+endifstmt(void)
+{
+ if (flslvl) {
+ flslvl--;
+ if (flslvl == 0)
+ prtline();
+ } else if (trulvl)
+ trulvl--;
+ else
+ error("If-less endif");
+ if (flslvl == 0)
+ elflvl = 0;
+ elslvl = 0;
+ chknl();
+}
+
+/*
+ * Note! Ugly!
+ * Walk over the string s and search for defined, and replace it with
+ * spaces and a 1 or 0.
+ */
+static void
+fixdefined(usch *s)
+{
+ usch *bc, oc;
+
+ for (; *s; s++) {
+ if (*s != 'd')
+ continue;
+ if (memcmp(s, "defined", 7))
+ continue;
+ /* Ok, got defined, can scratch it now */
+ memset(s, ' ', 7);
+ s += 7;
+#define WSARG(x) (x == ' ' || x == '\t')
+ if (*s != '(' && !WSARG(*s))
+ continue;
+ while (WSARG(*s))
+ s++;
+ if (*s == '(')
+ s++;
+ while (WSARG(*s))
+ s++;
+#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_'))
+#define NUMARG(x) (x >= '0' && x <= '9')
+ if (!IDARG(*s))
+ error("bad defined arg");
+ bc = s;
+ while (IDARG(*s) || NUMARG(*s))
+ s++;
+ oc = *s;
+ *s = 0;
+ *bc = (lookup(bc, FIND) != 0) + '0';
+ memset(bc+1, ' ', s-bc-1);
+ *s = oc;
+ }
+}
+
+/*
+ * get the full line of identifiers after an #if, pushback a WARN and
+ * the line and prepare for expmac() to expand.
+ * This is done before switching state. When expmac is finished,
+ * pushback the expanded line, change state and call yyparse.
+ */
+static void
+storepb(void)
+{
+ usch *opb = stringbuf;
+ int c;
+
+ while ((c = input()) != '\n')
+ savch(c);
+ cunput('\n');
+ savch(0);
+ fixdefined(opb); /* XXX can fail if #line? */
+ cunput(1); /* WARN XXX */
+ unpstr(opb);
+ stringbuf = opb;
+ slow = 1;
+ expmac(NULL);
+ slow = 0;
+ /* line now expanded */
+ while (stringbuf > opb)
+ cunput(*--stringbuf);
+}
+
+static void
+ifstmt(void)
+{
+ if (flslvl == 0) {
+ slow = 1;
+ if (yyparse())
+ ++trulvl;
+ else
+ ++flslvl;
+ slow = 0;
+ } else
+ ++flslvl;
+}
+
+static void
+elifstmt(void)
+{
+ if (flslvl == 0)
+ elflvl = trulvl;
+ if (flslvl) {
+ if (elflvl > trulvl)
+ ;
+ else if (--flslvl!=0)
+ ++flslvl;
+ else {
+ slow = 1;
+ if (yyparse()) {
+ ++trulvl;
+ prtline();
+ } else
+ ++flslvl;
+ slow = 0;
+ }
+ } else if (trulvl) {
+ ++flslvl;
+ --trulvl;
+ } else
+ error("If-less elif");
+}
+
+static usch *
+svinp(void)
+{
+ int c;
+ usch *cp = stringbuf;
+
+ while ((c = input()) && c != '\n')
+ savch(c);
+ savch('\n');
+ savch(0);
+ BEGIN 0;
+ return cp;
+}
+
+static void
+cpperror(void)
+{
+ usch *cp;
+ int c;
+
+ if (flslvl)
+ return;
+ c = yylex();
+ if (c != WSPACE && c != '\n')
+ error("bad error");
+ cp = svinp();
+ if (flslvl)
+ stringbuf = cp;
+ else
+ error("error: %s", cp);
+}
+
+static void
+undefstmt(void)
+{
+ struct symtab *np;
+
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ error("bad undef");
+ if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
+ np->value = 0;
+ slow = 0;
+ chknl();
+}
+
+static void
+pragmastmt(void)
+{
+ slow = 1;
+ if (yylex() != WSPACE)
+ error("bad pragma");
+ while (yylex() != '\n') /* no pragma support */
+ ;
+ slow = 0;
+}
diff --git a/usr.bin/pcc/cc/cpp/tests/res1 b/usr.bin/pcc/cc/cpp/tests/res1
new file mode 100644
index 00000000000..c0bb48019f3
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res1
@@ -0,0 +1,7 @@
+# 1 "<stdin>"
+
+
+
+
+char p[] = "x ## y";
+
diff --git a/usr.bin/pcc/cc/cpp/tests/res2 b/usr.bin/pcc/cc/cpp/tests/res2
new file mode 100644
index 00000000000..1eb808aac47
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res2
@@ -0,0 +1,26 @@
+# 1 "<stdin>"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t (1);
+f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &
+f(2 * (0,1))^m (0,1);
+int i[] = { 1, 23, 4, 5, };
+char c[2][6] = { "hello", "" };
+
+
+
+
+
+
diff --git a/usr.bin/pcc/cc/cpp/tests/res3 b/usr.bin/pcc/cc/cpp/tests/res3
new file mode 100644
index 00000000000..4219319ddff
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res3
@@ -0,0 +1,16 @@
+# 1 "<stdin>"
+
+
+
+
+
+
+
+
+
+printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
+fputs(
+"strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);
+\#include "vers2.h"
+"hello";
+"hello" ", world"
diff --git a/usr.bin/pcc/cc/cpp/tests/res4 b/usr.bin/pcc/cc/cpp/tests/res4
new file mode 100644
index 00000000000..d7046a01507
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res4
@@ -0,0 +1,5 @@
+# 1 "<stdin>"
+
+
+
+(1)
diff --git a/usr.bin/pcc/cc/cpp/tests/res5 b/usr.bin/pcc/cc/cpp/tests/res5
new file mode 100644
index 00000000000..291405dcfee
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res5
@@ -0,0 +1,4 @@
+# 1 "<stdin>"
+
+int j[] = { 123, 45, 67, 89,
+ 10, 11, 12, };
diff --git a/usr.bin/pcc/cc/cpp/tests/res6 b/usr.bin/pcc/cc/cpp/tests/res6
new file mode 100644
index 00000000000..0bb0f9a1dbf
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res6
@@ -0,0 +1,6 @@
+# 1 "<stdin>"
+
+
+
+
+foo
diff --git a/usr.bin/pcc/cc/cpp/tests/res7 b/usr.bin/pcc/cc/cpp/tests/res7
new file mode 100644
index 00000000000..18c492bda72
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res7
@@ -0,0 +1,5 @@
+# 1 "<stdin>"
+
+
+
+a YES
diff --git a/usr.bin/pcc/cc/cpp/tests/res8 b/usr.bin/pcc/cc/cpp/tests/res8
new file mode 100644
index 00000000000..e7de0945f47
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res8
@@ -0,0 +1,8 @@
+# 1 "<stdin>"
+
+
+
+
+
+(hej.s_s.s_pos)
+
diff --git a/usr.bin/pcc/cc/cpp/tests/res9 b/usr.bin/pcc/cc/cpp/tests/res9
new file mode 100644
index 00000000000..aea239fc9aa
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/res9
@@ -0,0 +1,5 @@
+# 1 "<stdin>"
+
+
+
+ao
diff --git a/usr.bin/pcc/cc/cpp/tests/test1 b/usr.bin/pcc/cc/cpp/tests/test1
new file mode 100644
index 00000000000..79a3c5dc5d4
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test1
@@ -0,0 +1,6 @@
+#define hash_hash # ## #
+#define mkstr(a) # a
+#define in_between(a) mkstr(a)
+#define join(c, d) in_between(c hash_hash d)
+char p[] = join(x, y); // equivalent to
+ // char p[] = "x ## y";
diff --git a/usr.bin/pcc/cc/cpp/tests/test2 b/usr.bin/pcc/cc/cpp/tests/test2
new file mode 100644
index 00000000000..283d4fbc1f0
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test2
@@ -0,0 +1,25 @@
+#define x 3
+#define f(a) f(x * (a))
+#undef x
+#define x 2
+#define g f
+#define z z[0]
+#define h g(~
+#define m(a) a(w)
+#define w 0,1
+#define t(a) a
+#define p() int
+#define q(x) x
+#define r(x,y) x ## y
+#define str(x) # x
+f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
+g(x+(3,4)-w) | h 5) & m
+(f)^m(m);
+p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
+char c[2][6] = { str(hello), str() };
+/*
+ * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+ * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+ * int i[] = { 1, 23, 4, 5, };
+ * char c[2][6] = { "hello", "" };
+ */
diff --git a/usr.bin/pcc/cc/cpp/tests/test3 b/usr.bin/pcc/cc/cpp/tests/test3
new file mode 100644
index 00000000000..a659245ecbc
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test3
@@ -0,0 +1,15 @@
+#define str(s) # s
+#define xstr(s) str(s)
+#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
+ x ## s, x ## t)
+#define INCFILE(n) vers ## n
+#define glue(a, b) a ## b
+#define xglue(a, b) glue(a, b)
+#define HIGHLOW "hello"
+#define LOW LOW ", world"
+debug(1, 2);
+fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away
+ == 0) str(: @\n), s);
+\#include xstr(INCFILE(2).h)
+glue(HIGH, LOW);
+xglue(HIGH, LOW)
diff --git a/usr.bin/pcc/cc/cpp/tests/test4 b/usr.bin/pcc/cc/cpp/tests/test4
new file mode 100644
index 00000000000..0068f3751b8
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test4
@@ -0,0 +1,4 @@
+#define foobar 1
+#define C(x,y) x##y
+#define D(x) (C(x,bar))
+D(foo)
diff --git a/usr.bin/pcc/cc/cpp/tests/test5 b/usr.bin/pcc/cc/cpp/tests/test5
new file mode 100644
index 00000000000..3ca0bb6c9c0
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test5
@@ -0,0 +1,3 @@
+#define t(x,y,z) x ## y ## z
+int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
+ t(10,,), t(,11,), t(,,12), t(,,) };
diff --git a/usr.bin/pcc/cc/cpp/tests/test6 b/usr.bin/pcc/cc/cpp/tests/test6
new file mode 100644
index 00000000000..28cfddece68
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test6
@@ -0,0 +1,5 @@
+#define X(a,b, \
+ c,d) \
+ foo
+
+X(1,2,3,4)
diff --git a/usr.bin/pcc/cc/cpp/tests/test7 b/usr.bin/pcc/cc/cpp/tests/test7
new file mode 100644
index 00000000000..b22b22bbcc9
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test7
@@ -0,0 +1,4 @@
+#define a() YES
+#define b() a
+b()
+b()()
diff --git a/usr.bin/pcc/cc/cpp/tests/test8 b/usr.bin/pcc/cc/cpp/tests/test8
new file mode 100644
index 00000000000..c5d2f9a1449
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test8
@@ -0,0 +1,7 @@
+// test macro expansion in arguments
+#define s_pos s_s.s_pos
+#define foo(x) (x)
+
+//hej.s_pos
+foo(hej.s_pos)
+
diff --git a/usr.bin/pcc/cc/cpp/tests/test9 b/usr.bin/pcc/cc/cpp/tests/test9
new file mode 100644
index 00000000000..4d4368d5663
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/tests/test9
@@ -0,0 +1,4 @@
+#define C(a,b,c) a##b##c
+#define N(x,y) C(x,_,y)
+#define A_O ao
+N(A,O)
diff --git a/usr.bin/pcc/cc/cpp/token.c b/usr.bin/pcc/cc/cpp/token.c
new file mode 100644
index 00000000000..3f18f754cb5
--- /dev/null
+++ b/usr.bin/pcc/cc/cpp/token.c
@@ -0,0 +1,495 @@
+/* $Id: token.c,v 1.1 2007/09/15 18:12:32 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson. 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cpp.h"
+
+/* definition for include file info */
+struct includ {
+ struct includ *next;
+ char *fname;
+ int lineno;
+ int infil;
+ usch *curptr;
+ usch *maxread;
+ usch *ostr;
+ usch *buffer;
+ usch bbuf[NAMEMAX+CPPBUF+1];
+} *ifiles;
+
+usch *yyp, *yystr, yybuf[CPPBUF];
+
+int yylex(void);
+int yywrap(void);
+
+static struct includ *
+getbuf(usch *file)
+{
+ struct includ *ic;
+ usch *ostr = stringbuf;
+
+ stringbuf = (usch *)ROUND((int)stringbuf);
+ ic = (struct includ *)stringbuf;
+ stringbuf += sizeof(struct includ);
+ ic->ostr = ostr;
+
+ return ic;
+}
+
+static void
+putbuf(struct includ *ic)
+{
+if (stringbuf < (usch *)&ic[1])
+;
+else
+ stringbuf = ic->ostr;
+}
+
+static int
+input(void)
+{
+ struct includ *ic;
+ int len;
+
+ if (ifiles->curptr < ifiles->maxread)
+ return *ifiles->curptr++;
+
+ if (ifiles->infil < 0) {
+ ic = ifiles;
+ ifiles = ifiles->next;
+ putbuf(ic);
+ return input();
+ }
+ if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
+ error("read error on file %s", ifiles->fname);
+ if (len == 0)
+ return -1;
+ ifiles->curptr = ifiles->buffer;
+ ifiles->maxread = ifiles->buffer + len;
+ return input();
+}
+
+static void
+unput(int c)
+{
+ struct includ *ic;
+
+ if (ifiles->curptr > ifiles->bbuf) {
+ *--ifiles->curptr = c;
+ } else {
+ ic = getbuf(NULL);
+ ic->fname = ifiles->fname;
+ ic->lineno = ifiles->lineno;
+ ic->infil = -1;
+ ic->curptr = &ic->bbuf[NAMEMAX+CPPBUF+1];
+ ic->maxread = ic->curptr;
+ ic->next = ifiles;
+ ifiles = ic;
+ *--ifiles->curptr = c;
+ }
+}
+
+#define UNPUT(c) *--ifiles->curptr = c
+
+static int
+slofgetc(void)
+{
+ int c;
+
+again: switch (c = input()) {
+ case '\\': /* continued lines */
+ if ((c = input()) == '\n') {
+ ifiles->lineno++;
+ putc('\n', obuf);
+ goto again;
+ }
+ cunput(c);
+ return '\\';
+ case '?': /* trigraphs */
+ if ((c = input()) != '?') {
+ cunput(c);
+ return '?';
+ }
+ switch (c = input()) {
+ case '=': c = '#'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '!': c = '|'; break;
+ case '-': c = '~'; break;
+ default:
+ cunput(c);
+ cunput('?');
+ return '?';
+ }
+ cunput(c);
+ goto again;
+ default:
+ return c;
+ }
+}
+
+int
+yylex()
+{
+ static int wasnl = 1;
+ int c, oc, rval;
+
+fast: yystr = yybuf;
+ yyp = yystr;
+ c = input();
+ if (c != ' ' && c != '\t' && c != '#')
+ wasnl = 0;
+#define ONEMORE() { *yyp++ = c; c = slofgetc(); }
+again: switch (c) {
+ case -1:
+ rval = 0;
+ break;
+
+ case '\'': /* charcon */
+ case '"': /* string */
+chstr: oc = c;
+ if (slow == 0) {
+ do {
+ putch(c);
+ if (c == '\\')
+ putch(slofgetc());
+ } while ((c = slofgetc()) != EOF && c != oc);
+ if (c == oc)
+ putch(c);
+ goto fast;
+ } else {
+ do {
+ *yyp++ = c;
+ if (c == '\\')
+ *yyp++ = slofgetc();
+ } while ((c = slofgetc()) != EOF && c != oc);
+ *yyp++ = c; *yyp = 0;
+ }
+ rval = oc == '"' ? STRING : CHARCON;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *yyp++ = c;
+ c = slofgetc();
+ if (yyp[-1] == '0' && (c == 'x' || c == 'X')) {
+ do {
+ ONEMORE();
+ } while (isxdigit(c));
+ } else {
+ while (isdigit(c))
+ ONEMORE();
+ }
+ if (c != '.' && c != 'e' && c != 'E') {
+ /* not floating point number */
+ while (c == 'l' || c == 'L' || c == 'u' || c == 'U') {
+ ONEMORE();
+ }
+ cunput(c);
+ *yyp = 0;
+ rval = NUMBER;
+ break;
+ }
+ /* it's a floating point number here */
+ if (c == '.') { /* decimal point */
+F: do { /* may be followed by digits */
+ ONEMORE();
+ } while (isdigit(c));
+ if (c == 'e' || c == 'E') {
+E: ONEMORE();
+ if (c == '-' || c == '+') {
+ ONEMORE();
+ }
+ while (isdigit(c))
+ ONEMORE();
+ }
+ if (c == 'f' || c == 'F' || c == 'l' || c == 'L')
+ ONEMORE();
+ cunput(c);
+ *yyp = 0;
+ rval = FPOINT;
+ break;
+ } else
+ goto E;
+
+ case '.':
+ ONEMORE();
+ if (isdigit(c))
+ goto F;
+ if (!slow) {
+ UNPUT(c);
+ putch('.');
+ goto fast;
+ }
+ if (c == '.') {
+ ONEMORE();
+ if (c == '.') {
+ *yyp++ = '.'; *yyp = 0;
+ rval = ELLIPS;
+ break;
+ }
+ cunput(c);
+ cunput('.');
+ *--yyp = 0;
+ rval = '.';
+ break;
+ }
+ cunput(c);
+ *yyp = 0;
+ rval = '.';
+ break;
+
+ case '\\':
+ c = input();
+ if (c == '\n') {
+ ifiles->lineno++;
+ putch('\n');
+ goto fast;
+ }
+ if (!slow) {
+ putch('\\');
+ goto again;
+ }
+ UNPUT(c);
+ *yyp++ = '\\'; *yyp = 0;
+ rval = '\\';
+ break;
+
+ case '\n':
+ wasnl = 1;
+ ifiles->lineno++;
+ rval = NL;
+ if (slow)
+ break;
+ if (flslvl == 0) {
+ if (curline() == 1)
+ prtline();
+ else
+ putch('\n');
+ }
+ goto fast;
+
+ case '#':
+ if (wasnl) {
+ wasnl = 0;
+ rval = CONTROL;
+ break;
+ }
+ if (!slow) {
+ putch('#');
+ goto fast;
+ }
+ *yyp++ = c;
+ c = input();
+ if (c == '#') {
+ *yyp++ = c;
+ *yyp = 0;
+ rval = CONCAT;
+ } else {
+ unput(c);
+ *yyp = 0;
+ rval = MKSTR;
+ }
+ break;
+
+ case ' ':
+ case '\t': /* whitespace */
+ do {
+ *yyp++ = c;
+ c = input();
+ } while (c == ' ' || c == '\t');
+ if (wasnl && c == '#') {
+ wasnl = 0;
+ rval = CONTROL;
+ } else {
+ unput(c);
+ *yyp = 0;
+ rval = WSPACE;
+ }
+ break;
+
+ case '/':
+ if ((c = slofgetc()) == '/') {
+ if (Cflag)
+ fprintf(obuf, "//");
+ while ((c = slofgetc()) && c != '\n')
+ if (Cflag)
+ putc(c, obuf);
+ goto again;
+ } else if (c == '*') {
+ if (Cflag)
+ fprintf(obuf, "/*");
+ oc = 0;
+ do {
+ while ((c = slofgetc()) && c != '*') {
+ if (c == '\n') {
+ putc(c, obuf);
+ ifiles->lineno++;
+ } else if (Cflag)
+ putc(c, obuf);
+ }
+ if (Cflag)
+ putc(c, obuf);
+ if ((c = slofgetc()) == '/')
+ break;
+ unput(c);
+ } while (c);
+ if (Cflag)
+ putc(c, obuf);
+ if (tflag) {
+ rval = yylex();
+ } else {
+ *yyp++ = ' '; *yyp = 0;
+ rval = WSPACE;
+ }
+ } else {
+ unput(c);
+ *yyp++ = '/'; *yyp = 0;
+ rval = '/';
+ }
+ break;
+
+ case 'L': /* may be STRING, CHARCON or identifier */
+ *yyp++ = c;
+ if ((c = slofgetc()) == '"' || c == '\'')
+ goto chstr;
+gotid: while (isalnum(c) || c == '_') {
+ *yyp++ = c;
+ c = slofgetc();
+ }
+ *yyp = 0;
+ unput(c);
+ rval = IDENT;
+ break;
+
+ default:
+ if (isalpha(c) || c == '_')
+ goto gotid;
+ if (!slow && c > 5) {
+ putch(c);
+ goto fast;
+ }
+ yystr[0] = c; yystr[1] = 0;
+ rval = c;
+ break;
+ }
+ return rval;
+}
+
+/*
+ * A new file included.
+ * If ifiles == NULL, this is the first file and already opened (stdin).
+ * Return 0 on success, -1 on failure to open file.
+ */
+int
+pushfile(char *file)
+{
+ struct includ ibuf;
+ struct includ *old;
+ struct includ *ic;
+
+ ic = &ibuf;
+ old = ifiles;
+
+ slow = 0;
+ if (file != NULL) {
+ if ((ic->infil = open(file, O_RDONLY)) < 0)
+ return -1;
+ ic->fname = file;
+ } else {
+ ic->infil = 0;
+ ic->fname = "<stdin>";
+ }
+ ic->buffer = ic->bbuf+NAMEMAX;
+ ic->curptr = ic->buffer;
+ ifiles = ic;
+ ic->lineno = 0;
+ ic->maxread = ic->curptr;
+ unput('\n');
+
+ mainscan();
+
+ if (trulvl || flslvl)
+ error("unterminated conditional");
+
+ ifiles = old;
+ close(ic->infil);
+ return 0;
+}
+
+/*
+ * Print current position to output file.
+ */
+void
+prtline()
+{
+ fprintf(obuf, "# %d \"%s\"\n", ifiles->lineno, ifiles->fname);
+}
+
+void
+cunput(int c)
+{
+extern int dflag;
+if (dflag)printf(": '%c'(%d)", c, c);
+ unput(c);
+}
+
+void
+setline(int line)
+{
+ if (ifiles)
+ ifiles->lineno = line-1;
+}
+
+void
+setfile(char *name)
+{
+ if (ifiles)
+ ifiles->fname = strdup(name);
+}
+
+int
+curline()
+{
+ return ifiles ? ifiles->lineno : 0;
+}
+
+char *
+curfile()
+{
+ return ifiles ? ifiles->fname : "";
+}
diff --git a/usr.bin/pcc/config.guess b/usr.bin/pcc/config.guess
new file mode 100644
index 00000000000..1e6f50b7da5
--- /dev/null
+++ b/usr.bin/pcc/config.guess
@@ -0,0 +1,1463 @@
+#! /bin/sh
+#
+# $NetBSD: config.guess,v 1.8 2004/08/14 19:13:55 schmonz Exp $
+#
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-06-11'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha*:OpenVMS:*:*)
+ echo alpha-hp-vms
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ # GNU/KFreeBSD systems have a "k" prefix to indicate we are using
+ # FreeBSD's kernel, but not the complete OS.
+ case ${LIBC} in gnu) kernel_only='k' ;; esac
+ echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ case `uname -p` in
+ *86) UNAME_PROCESSOR=i686 ;;
+ powerpc) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/usr.bin/pcc/config.h.in b/usr.bin/pcc/config.h.in
new file mode 100644
index 00000000000..4da1b61c085
--- /dev/null
+++ b/usr.bin/pcc/config.h.in
@@ -0,0 +1,155 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef PCC_MAJOR
+#undef PCC_MINOR
+#undef PCC_MINORMINOR
+#undef VERSSTR
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+/* target operating system */
+#undef TARGOS
+
+/* mkstemp() */
+#undef HAVE_MKSTEMP
+
+/* which lex is used */
+#undef ISFLEX
diff --git a/usr.bin/pcc/config.sub b/usr.bin/pcc/config.sub
new file mode 100644
index 00000000000..b9e9bc4860a
--- /dev/null
+++ b/usr.bin/pcc/config.sub
@@ -0,0 +1,1555 @@
+#! /bin/sh
+#
+# $NetBSD: config.sub,v 1.7 2004/08/14 19:14:42 schmonz Exp $
+#
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-03-12'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | msp430-* \
+ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nv1)
+ basic_machine=nv1-cray
+ os=-unicosmp
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/usr.bin/pcc/configure b/usr.bin/pcc/configure
new file mode 100644
index 00000000000..7308715407c
--- /dev/null
+++ b/usr.bin/pcc/configure
@@ -0,0 +1,5655 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for pcc 0.9.8.
+#
+# Report bugs to <BUG-REPORT-ADDRESS>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='pcc'
+PACKAGE_TARNAME='pcc'
+PACKAGE_VERSION='0.9.8'
+PACKAGE_STRING='pcc 0.9.8'
+PACKAGE_BUGREPORT='BUG-REPORT-ADDRESS'
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+SET_MAKE
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+LEX
+LEX_OUTPUT_ROOT
+LEXLIB
+YACC
+YFLAGS
+strip
+CPP
+GREP
+EGREP
+ALLOCA
+targos
+targmach
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+YACC
+YFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures pcc 0.9.8 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/pcc]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of pcc 0.9.8:";;
+ esac
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ YACC The `Yet Another C Compiler' implementation to use. Defaults to
+ the first program found out of: `bison -y', `byacc', `yacc'.
+ YFLAGS The list of arguments that will be passed by default to $YACC.
+ This script will default YFLAGS to the empty string to avoid a
+ default value of `-d' given by some make applications.
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <BUG-REPORT-ADDRESS>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+pcc configure 0.9.8
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by pcc $as_me 0.9.8, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+case "$target_os" in
+ netbsd*)
+ targos=netbsd
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ openbsd*)
+ targos=openbsd
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ dragonfly*)
+ targos=dragonfly
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ linux*)
+ targos=linux
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ *)
+ targos="$target_os"
+ case "$target_cpu" in
+ m16c) targmach=m16c ;;
+ nova) targmach=nova ;;
+ esac
+ ;;
+esac
+
+if test "X$targos" = X -o "X$targmach" = X ; then
+ { { echo "$as_me:$LINENO: error: '$target' is not (yet) supported by pcc." >&5
+echo "$as_me: error: '$target' is not (yet) supported by pcc." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+for ac_prog in flex lex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_LEX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_LEX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+ { echo "$as_me:$LINENO: result: $LEX" >&5
+echo "${ECHO_T}$LEX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+ cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { yyless (input () != 0); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+ return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ (ac_try="$LEX conftest.l"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$LEX conftest.l") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ echo "$as_me:$LINENO: checking lex output file root" >&5
+echo $ECHO_N "checking lex output file root... $ECHO_C" >&6; }
+if test "${ac_cv_prog_lex_root+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+else
+ { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5
+echo "$as_me: error: cannot find output from $LEX; giving up" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+ { echo "$as_me:$LINENO: checking lex library" >&5
+echo $ECHO_N "checking lex library... $ECHO_C" >&6; }
+if test "${ac_cv_lib_lex+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ ac_save_LIBS=$LIBS
+ ac_cv_lib_lex='none needed'
+ for ac_lib in '' -lfl -ll; do
+ LIBS="$ac_lib $ac_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_lex=$ac_lib
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ test "$ac_cv_lib_lex" != 'none needed' && break
+ done
+ LIBS=$ac_save_LIBS
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_lex" >&5
+echo "${ECHO_T}$ac_cv_lib_lex" >&6; }
+ test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5
+echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6; }
+if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_prog_lex_yytext_pointer=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define YYTEXT_POINTER 1
+_ACEOF
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+for ac_prog in 'bison -y' byacc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_YACC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_YACC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ { echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+# Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_strip+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$strip"; then
+ ac_cv_prog_strip="$strip" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_strip="yes"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_strip" && ac_cv_prog_strip="no"
+fi
+fi
+strip=$ac_cv_prog_strip
+if test -n "$strip"; then
+ { echo "$as_me:$LINENO: result: $strip" >&5
+echo "${ECHO_T}$strip" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+# Checks for libraries.
+
+# Checks for header files.
+# AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+for ac_header in string.h alloca.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## --------------------------------- ##
+## Report this to BUG-REPORT-ADDRESS ##
+## --------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for library functions.
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+{ echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6; }
+if test "${ac_cv_working_alloca_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_working_alloca_h=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_working_alloca_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6; }
+if test "${ac_cv_func_alloca_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_alloca_works=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_alloca_works=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble. Some versions do not even contain alloca or
+# contain a buggy version. If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6; }
+if test "${ac_cv_os_cray+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "webecray" >/dev/null 2>&1; then
+ ac_cv_os_cray=yes
+else
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+ for ac_func in _getb67 GETB67 getb67; do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+ break
+fi
+
+ done
+fi
+
+{ echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6; }
+if test "${ac_cv_c_stack_direction+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+ return find_stack_direction () < 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_stack_direction=1
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+## AC_FUNC_STRTOD
+# AC_FUNC_VPRINTF
+# AC_CHECK_FUNCS([memset strchr strdup strrchr strtol])
+
+for ac_func in mkstemp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+pcc_major=`echo $PACKAGE_VERSION | awk -F. '{print $1}'`
+pcc_minor=`echo $PACKAGE_VERSION | awk -F. '{print $2}'`
+pcc_minorminor=`echo $PACKAGE_VERSION | awk -F. '{print $3}'`
+versstr="\"$PACKAGE_STRING for $target, $USER@`hostname` `date`\""
+
+cat >>confdefs.h <<_ACEOF
+#define TARGOS $targos
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PCC_MAJOR $pcc_major
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PCC_MINOR $pcc_minor
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PCC_MINORMINOR $pcc_minorminor
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define VERSSTR $versstr
+_ACEOF
+
+if test "$LEX" = flex ; then
+ cat >>confdefs.h <<_ACEOF
+#define ISFLEX 1
+_ACEOF
+
+fi
+
+ac_config_files="$ac_config_files Makefile cc/Makefile cc/cc/Makefile cc/cpp/Makefile cc/ccom/Makefile f77/Makefile f77/f77/Makefile f77/fcom/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by pcc $as_me 0.9.8, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+pcc config.status 0.9.8
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "cc/Makefile") CONFIG_FILES="$CONFIG_FILES cc/Makefile" ;;
+ "cc/cc/Makefile") CONFIG_FILES="$CONFIG_FILES cc/cc/Makefile" ;;
+ "cc/cpp/Makefile") CONFIG_FILES="$CONFIG_FILES cc/cpp/Makefile" ;;
+ "cc/ccom/Makefile") CONFIG_FILES="$CONFIG_FILES cc/ccom/Makefile" ;;
+ "f77/Makefile") CONFIG_FILES="$CONFIG_FILES f77/Makefile" ;;
+ "f77/f77/Makefile") CONFIG_FILES="$CONFIG_FILES f77/f77/Makefile" ;;
+ "f77/fcom/Makefile") CONFIG_FILES="$CONFIG_FILES f77/fcom/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+LEX!$LEX$ac_delim
+LEX_OUTPUT_ROOT!$LEX_OUTPUT_ROOT$ac_delim
+LEXLIB!$LEXLIB$ac_delim
+YACC!$YACC$ac_delim
+YFLAGS!$YFLAGS$ac_delim
+strip!$strip$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+ALLOCA!$ALLOCA$ac_delim
+targos!$targos$ac_delim
+targmach!$targmach$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 74; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/usr.bin/pcc/configure.ac b/usr.bin/pcc/configure.ac
new file mode 100644
index 00000000000..b3f81139dcb
--- /dev/null
+++ b/usr.bin/pcc/configure.ac
@@ -0,0 +1,102 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT([pcc], [0.9.8], BUG-REPORT-ADDRESS)
+AC_CONFIG_HEADER([config.h])
+
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+AC_CANONICAL_TARGET
+
+
+case "$target_os" in
+ netbsd*)
+ targos=netbsd
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ openbsd*)
+ targos=openbsd
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ dragonfly*)
+ targos=dragonfly
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ linux*)
+ targos=linux
+ case "$target_cpu" in
+ i?86) targmach=x86 ;;
+ esac
+ ;;
+ *)
+ targos="$target_os"
+ case "$target_cpu" in
+ m16c) targmach=m16c ;;
+ nova) targmach=nova ;;
+ esac
+ ;;
+esac
+
+if test "X$targos" = X -o "X$targmach" = X ; then
+ AC_MSG_ERROR(['$target' is not (yet) supported by pcc.])
+fi
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_LEX
+AC_PROG_YACC
+
+AC_CHECK_PROG(strip,strip,yes,no)
+
+# Checks for libraries.
+
+# Checks for header files.
+# AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])
+AC_CHECK_HEADERS([string.h alloca.h])
+
+# Checks for library functions.
+AC_FUNC_ALLOCA
+## AC_FUNC_STRTOD
+# AC_FUNC_VPRINTF
+# AC_CHECK_FUNCS([memset strchr strdup strrchr strtol])
+AC_CHECK_FUNCS(mkstemp)
+
+AC_SUBST(targos)
+AC_SUBST(targmach)
+AC_SUBST(prefix)
+AC_SUBST(exec_prefix)
+AC_SUBST(libexecdir)
+AC_SUBST(includedir)
+AC_SUBST(strip)
+
+pcc_major=`echo $PACKAGE_VERSION | awk -F. '{print $1}'`
+pcc_minor=`echo $PACKAGE_VERSION | awk -F. '{print $2}'`
+pcc_minorminor=`echo $PACKAGE_VERSION | awk -F. '{print $3}'`
+versstr="\"$PACKAGE_STRING for $target, $USER@`hostname` `date`\""
+
+AC_DEFINE_UNQUOTED(TARGOS, $targos)
+AC_DEFINE_UNQUOTED(PCC_MAJOR, $pcc_major)
+AC_DEFINE_UNQUOTED(PCC_MINOR, $pcc_minor)
+AC_DEFINE_UNQUOTED(PCC_MINORMINOR, $pcc_minorminor)
+AC_DEFINE_UNQUOTED(VERSSTR, $versstr)
+if test "$LEX" = flex ; then
+ AC_DEFINE_UNQUOTED(ISFLEX, 1)
+fi
+
+AC_CONFIG_FILES([Makefile
+ cc/Makefile
+ cc/cc/Makefile
+ cc/cpp/Makefile
+ cc/ccom/Makefile
+ f77/Makefile
+ f77/f77/Makefile
+ f77/fcom/Makefile
+])
+AC_OUTPUT
diff --git a/usr.bin/pcc/f77/Makefile.in b/usr.bin/pcc/f77/Makefile.in
new file mode 100644
index 00000000000..76ad025b263
--- /dev/null
+++ b/usr.bin/pcc/f77/Makefile.in
@@ -0,0 +1,36 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:35 otto Exp $
+#
+# Makefile.in for top-level of pcc.
+#
+
+@SET_MAKE@
+CC=@CC@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+CPPFLAGS=@CPPFLAGS@
+YACC=@YACC@
+LEX=@LEX@
+
+SUBDIR=cc cpp ccom
+
+all: ${SUBDIR}
+
+install:
+ cd cc && ${MAKE} install
+ cd cpp && ${MAKE} install
+ cd ccom && ${MAKE} install
+
+clean:
+ cd cc && ${MAKE} clean
+ cd cpp && ${MAKE} clean
+ cd ccom && ${MAKE} clean
+
+distclean:
+ cd cc && ${MAKE} distclean
+ cd cpp && ${MAKE} distclean
+ cd ccom && ${MAKE} distclean
+ /bin/rm -rf Makefile config.log stamp-h1 config.status \
+ configure.lineno config.h autom4te.cache
+
+${SUBDIR}:
+ cd $@; $(MAKE) all $(MFLAGS)
diff --git a/usr.bin/pcc/f77/f77/Makefile.in b/usr.bin/pcc/f77/f77/Makefile.in
new file mode 100644
index 00000000000..9ab666faba9
--- /dev/null
+++ b/usr.bin/pcc/f77/f77/Makefile.in
@@ -0,0 +1,42 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:35 otto Exp $
+#
+# Makefile.in for the cc part of pcc.
+#
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libexecdir = @libexecdir@
+strip = @strip@
+CC = @CC@
+TARGOS = @targos@
+TARGMACH = @targmach@
+CFLAGS = @CFLAGS@ -DLIBEXECDIR=\"${libexecdir}\"
+CPPFLAGS = @CPPFLAGS@ -I../os/${TARGOS} -Dmach_${TARGMACH} -Dos_${TARGOS}
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+OBJS=cc.o
+DEST=pcc
+
+all: ${DEST}
+
+${DEST}: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+.c.o:
+ $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
+
+install:
+ ${INSTALL_PROGRAM} ${DEST} ${bindir}
+ @if [ ${strip} = yes ]; then \
+ strip ${bindir}/${DEST} ; \
+ echo strip ${bindir}/${DEST} ; \
+ fi
+
+clean:
+ /bin/rm -f $(OBJS) ${DEST}
+
+distclean: clean
+ /bin/rm -f Makefile
diff --git a/usr.bin/pcc/f77/fcom/Makefile.in b/usr.bin/pcc/f77/fcom/Makefile.in
new file mode 100644
index 00000000000..04018acc84e
--- /dev/null
+++ b/usr.bin/pcc/f77/fcom/Makefile.in
@@ -0,0 +1,95 @@
+# $Id: Makefile.in,v 1.1 2007/09/15 18:12:35 otto Exp $
+#
+# Makefile for the Fortran 77 command
+# Running on the @targmach@
+# Generating code for the @targmach@
+# Using the Johnson C compiler's second pass (binary version)
+
+TARGOS = @targos@
+TARGMACH = @targmach@
+MDIR=../arch/$(TARGMACH)
+YFLAGS=-d
+
+COMPFLGS = -O -DFORTRAN -DTARGET=@targmach@ -DFAMILY=SCJ -DHERE=VAX -DOUTPUT=BINARY -DPOLISH=POSTFIX -I../os/${TARGOS} -I../arch/${TARGMACH} -I. -Wall -Wmissing-prototypes -Wstrict-prototypes
+FILES = Makefile defs.h defines.h ftypes.h scjdefs tokens fio.h\
+ driver.c \
+ main.c proc.c init.c\
+ gram.head gram.dcl gram.expr gram.exec gram.io\
+ lex.c equiv.c data.c expr.c exec.c intr.c\
+ io.c misc.c error.c put.c putscjb.c f77md.c f77md2.c
+
+
+OBJECTS = main.o init.o proc.o gram.o lex.o \
+ equiv.o data.o expr.o exec.o intr.o io.o misc.o error.o\
+ put.o putscjb.o f77md.o f77md2.o
+
+compiler: f77 f77pass1
+
+f77 : f77.o f77md.o
+ $(CC) f77.o f77md.o -o f77
+ @size f77
+
+f77pass1 : $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) -o f77pass1
+ @size f77pass1
+
+gram.c: gram.head gram.dcl gram.expr gram.exec gram.io tokdefs
+ ( sed <tokdefs "s/#define/%token/" ;\
+ cat gram.head gram.dcl gram.expr gram.exec gram.io ) >gram.in
+ $(YACC) $(YFLAGS) gram.in
+ mv y.tab.c gram.c
+ mv y.tab.h gram.h
+ rm gram.in
+
+tokdefs: tokens
+ grep -n . <tokens | sed "s/\([^:]*\):\(.*\)/#define \2 \1/" >tokdefs
+
+lex.o : tokdefs
+driver.o $(OBJECTS) : defs.h defines.h ftypes.h
+
+fio.h :# /usr/sif/fort/libI77/fio.h
+# @echo "***Warning : /usr/sif/fort/libI77/fio.h has changed***"
+
+archall:
+ ar rc ../fortarch $(FILES)
+
+arch : ../fortarch
+
+../fortarch: $(FILES)
+ @ar uv ../fortarch $?
+ @wc ../fortarch
+
+
+printall:
+ pr $(FILES) | $P
+ touch print
+
+print: $(FILES)
+ pr $? | $P
+ touch print
+
+lint:
+ @echo "nohup lint -p ... >Lintout&"
+ @nohup lint -p error.c exec.c intr.c expr.c gram.c init.c io.c\
+ lex.c main.c proc.c misc.c put.c putscjb.c vax.c vaxx.c\
+ equiv.c data.c -lS >Lintout&
+
+clean:
+ -rm -f gram.c *.o f77 f77pass1
+ du
+
+install:
+ install -s f77 $(DESTDIR)/usr/bin
+ install -s f77pass1 $(DESTDIR)/usr/lib
+
+src : $(FILES) vaxdefs
+ cp $? /usr/src/cmd/f77
+ touch src
+.c.o :
+ cc -c $(CFLAGS) $(COMPFLGS) $*.c
+
+f77md.o: $(MDIR)/f77md.c
+ $(CC) -c $(CFLAGS) $(COMPFLGS) -o $@ $(MDIR)/f77md.c
+
+f77md2.o: $(MDIR)/f77md2.c
+ $(CC) -c $(CFLAGS) $(COMPFLGS) -o $@ $(MDIR)/f77md2.c
diff --git a/usr.bin/pcc/install-sh b/usr.bin/pcc/install-sh
new file mode 100644
index 00000000000..0ec27bcd488
--- /dev/null
+++ b/usr.bin/pcc/install-sh
@@ -0,0 +1,294 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+#
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd=$cpprog
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd=$stripprog
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "$0: no input file specified" >&2
+ exit 1
+else
+ :
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d "$dst" ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f "$src" ] || [ -d "$src" ]
+ then
+ :
+ else
+ echo "$0: $src does not exist" >&2
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "$0: no destination specified" >&2
+ exit 1
+ else
+ :
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d "$dst" ]
+ then
+ dst=$dst/`basename "$src"`
+ else
+ :
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+ '
+IFS="${IFS-$defaultIFS}"
+
+oIFS=$IFS
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS=$oIFS
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp=$pathcomp$1
+ shift
+
+ if [ ! -d "$pathcomp" ] ;
+ then
+ $mkdirprog "$pathcomp"
+ else
+ :
+ fi
+
+ pathcomp=$pathcomp/
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd "$dst" &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename "$dst"`
+ else
+ dstfile=`basename "$dst" $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename "$dst"`
+ else
+ :
+ fi
+
+# Make a couple of temp file names in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+ rmtmp=$dstdir/#rm.$$#
+
+# Trap to clean up temp files at exit.
+
+ trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+ trap '(exit $?); exit' 1 2 13 15
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd "$src" "$dsttmp" &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
+
+# Now remove or move aside any old file at destination location. We try this
+# two ways since rm can't unlink itself on some systems and the destination
+# file might be busy for other reasons. In this case, the final cleanup
+# might fail but the new file should still install successfully.
+
+{
+ if [ -f "$dstdir/$dstfile" ]
+ then
+ $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
+ $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
+ {
+ echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+ (exit 1); exit
+ }
+ else
+ :
+ fi
+} &&
+
+# Now rename the file to the real destination.
+
+ $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+
+fi &&
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+
+{
+ (exit 0); exit
+}
diff --git a/usr.bin/pcc/mip/common.c b/usr.bin/pcc/mip/common.c
new file mode 100644
index 00000000000..e5d49df9282
--- /dev/null
+++ b/usr.bin/pcc/mip/common.c
@@ -0,0 +1,631 @@
+/* $Id: common.c,v 1.1 2007/09/15 18:12:35 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "pass2.h"
+
+# ifndef EXIT
+# define EXIT exit
+# endif
+
+int nerrors = 0; /* number of errors */
+char *ftitle;
+int lineno;
+
+#ifndef WHERE
+#define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
+#endif
+
+/*
+ * nonfatal error message
+ * the routine where is different for pass 1 and pass 2;
+ * it tells where the error took place
+ */
+void
+uerror(char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ ++nerrors;
+ WHERE('u');
+ vfprintf(stderr, s, ap);
+ fprintf(stderr, "\n");
+ if (nerrors > 30)
+ cerror("too many errors");
+ va_end(ap);
+}
+
+/*
+ * compiler error: die
+ */
+void
+cerror(char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ WHERE('c');
+
+ /* give the compiler the benefit of the doubt */
+ if (nerrors && nerrors <= 30) {
+ fprintf(stderr,
+ "cannot recover from earlier errors: goodbye!\n");
+ } else {
+ fprintf(stderr, "compiler error: ");
+ vfprintf(stderr, s, ap);
+ fprintf(stderr, "\n");
+ }
+ va_end(ap);
+ EXIT(1);
+}
+
+/*
+ * warning
+ */
+void
+werror(char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ WHERE('w');
+ fprintf(stderr, "warning: ");
+ vfprintf(stderr, s, ap);
+ fprintf(stderr, "\n");
+}
+
+#ifndef MKEXT
+static NODE *freelink;
+static int usednodes;
+
+NODE *
+talloc()
+{
+ extern int inlnodecnt, recovernodes;
+ register NODE *p;
+
+ usednodes++;
+
+ if (recovernodes)
+ inlnodecnt++;
+ if (freelink != NULL) {
+ p = freelink;
+ freelink = p->next;
+ if (p->n_op != FREE)
+ cerror("node not FREE: %p", p);
+ if (nflag)
+ printf("alloc node %p from freelist\n", p);
+ return p;
+ }
+
+ p = permalloc(sizeof(NODE));
+ p->n_op = FREE;
+ if (nflag)
+ printf("alloc node %p from memory\n", p);
+ return p;
+}
+
+/*
+ * make a fresh copy of p
+ */
+NODE *
+tcopy(NODE *p)
+{
+ NODE *q;
+
+ q = talloc();
+ *q = *p;
+
+ switch (optype(q->n_op)) {
+ case BITYPE:
+ q->n_right = tcopy(p->n_right);
+ case UTYPE:
+ q->n_left = tcopy(p->n_left);
+ }
+
+ return(q);
+}
+
+
+/*
+ * ensure that all nodes have been freed
+ */
+void
+tcheck()
+{
+ extern int inlnodecnt;
+
+ if (nerrors)
+ return;
+
+ if ((usednodes - inlnodecnt) != 0)
+ cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt);
+}
+
+/*
+ * free the tree p
+ */
+void
+tfree(NODE *p)
+{
+ if (p->n_op != FREE)
+ walkf(p, (void (*)(NODE *))nfree);
+}
+
+/*
+ * Free a node, and return its left descendant.
+ * It is up to the caller to know whether the return value is usable.
+ */
+NODE *
+nfree(NODE *p)
+{
+ extern int inlnodecnt, recovernodes;
+ NODE *l;
+#ifdef PCC_DEBUG_NODES
+ NODE *q;
+#endif
+
+ if (p == NULL)
+ cerror("freeing blank node!");
+
+ l = p->n_left;
+ if (p->n_op == FREE)
+ cerror("freeing FREE node", p);
+#ifdef PCC_DEBUG_NODES
+ q = freelink;
+ while (q != NULL) {
+ if (q == p)
+ cerror("freeing free node %p", p);
+ q = q->next;
+ }
+#endif
+
+ if (nflag)
+ printf("freeing node %p\n", p);
+ p->n_op = FREE;
+ p->next = freelink;
+ freelink = p;
+ usednodes--;
+ if (recovernodes)
+ inlnodecnt--;
+ return l;
+}
+#endif
+
+#ifdef MKEXT
+#define coptype(o) (dope[o]&TYFLG)
+#else
+int cdope(int);
+#define coptype(o) (cdope(o)&TYFLG)
+#endif
+
+void
+fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down)
+{
+
+ int down1, down2;
+
+ more:
+ down1 = down2 = 0;
+
+ (*f)(t, down, &down1, &down2);
+
+ switch (coptype( t->n_op )) {
+
+ case BITYPE:
+ fwalk( t->n_left, f, down1 );
+ t = t->n_right;
+ down = down2;
+ goto more;
+
+ case UTYPE:
+ t = t->n_left;
+ down = down1;
+ goto more;
+
+ }
+}
+
+void
+walkf(NODE *t, void (*f)(NODE *))
+{
+ int opty;
+
+ opty = coptype(t->n_op);
+
+ if (opty != LTYPE)
+ walkf( t->n_left, f );
+ if (opty == BITYPE)
+ walkf( t->n_right, f );
+ (*f)(t);
+}
+
+int dope[DSIZE];
+char *opst[DSIZE];
+
+struct dopest {
+ int dopeop;
+ char opst[8];
+ int dopeval;
+} indope[] = {
+ { NAME, "NAME", LTYPE, },
+ { REG, "REG", LTYPE, },
+ { OREG, "OREG", LTYPE, },
+ { TEMP, "TEMP", LTYPE, },
+ { MOVE, "MOVE", UTYPE, },
+ { ICON, "ICON", LTYPE, },
+ { FCON, "FCON", LTYPE, },
+ { CCODES, "CCODES", LTYPE, },
+ { UMINUS, "U-", UTYPE, },
+ { UMUL, "U*", UTYPE, },
+ { FUNARG, "FUNARG", UTYPE, },
+ { UCALL, "UCALL", UTYPE|CALLFLG, },
+ { UFORTCALL, "UFCALL", UTYPE|CALLFLG, },
+ { COMPL, "~", UTYPE, },
+ { FORCE, "FORCE", UTYPE, },
+/* { INIT, "INIT", UTYPE, }, */
+ { SCONV, "SCONV", UTYPE, },
+ { PCONV, "PCONV", UTYPE, },
+ { PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, },
+ { MINUS, "-", BITYPE|FLOFLG|SIMPFLG, },
+ { MUL, "*", BITYPE|FLOFLG|MULFLG, },
+ { AND, "&", BITYPE|SIMPFLG|COMMFLG, },
+ { CM, ",", BITYPE, },
+ { ASSIGN, "=", BITYPE|ASGFLG, },
+ { DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG, },
+ { MOD, "%", BITYPE|DIVFLG, },
+ { LS, "<<", BITYPE|SHFFLG, },
+ { RS, ">>", BITYPE|SHFFLG, },
+ { OR, "|", BITYPE|COMMFLG|SIMPFLG, },
+ { ER, "^", BITYPE|COMMFLG|SIMPFLG, },
+ { STREF, "->", BITYPE, },
+ { CALL, "CALL", BITYPE|CALLFLG, },
+ { FORTCALL, "FCALL", BITYPE|CALLFLG, },
+ { EQ, "==", BITYPE|LOGFLG, },
+ { NE, "!=", BITYPE|LOGFLG, },
+ { LE, "<=", BITYPE|LOGFLG, },
+ { LT, "<", BITYPE|LOGFLG, },
+ { GE, ">=", BITYPE|LOGFLG, },
+ { GT, ">", BITYPE|LOGFLG, },
+ { UGT, "UGT", BITYPE|LOGFLG, },
+ { UGE, "UGE", BITYPE|LOGFLG, },
+ { ULT, "ULT", BITYPE|LOGFLG, },
+ { ULE, "ULE", BITYPE|LOGFLG, },
+ { CBRANCH, "CBRANCH", BITYPE, },
+ { FLD, "FLD", UTYPE, },
+ { PMCONV, "PMCONV", BITYPE, },
+ { PVCONV, "PVCONV", BITYPE, },
+ { RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG, },
+ { GOTO, "GOTO", UTYPE, },
+ { STASG, "STASG", BITYPE|ASGFLG, },
+ { STARG, "STARG", UTYPE, },
+ { STCALL, "STCALL", BITYPE|CALLFLG, },
+ { USTCALL, "USTCALL", UTYPE|CALLFLG, },
+ { ADDROF, "U&", UTYPE, },
+
+ { -1, "", 0 },
+};
+
+void
+mkdope()
+{
+ struct dopest *q;
+
+ for( q = indope; q->dopeop >= 0; ++q ){
+ dope[q->dopeop] = q->dopeval;
+ opst[q->dopeop] = q->opst;
+ }
+}
+
+/*
+ * output a nice description of the type of t
+ */
+void
+tprint(FILE *fp, TWORD t, TWORD q)
+{
+ static char * tnames[] = {
+ "undef",
+ "farg",
+ "char",
+ "uchar",
+ "short",
+ "ushort",
+ "int",
+ "unsigned",
+ "long",
+ "ulong",
+ "longlong",
+ "ulonglong",
+ "float",
+ "double",
+ "ldouble",
+ "strty",
+ "unionty",
+ "enumty",
+ "moety",
+ "void",
+ "signed", /* pass1 */
+ "bool", /* pass1 */
+ "?", "?"
+ };
+
+ for(;; t = DECREF(t), q = DECREF(q)) {
+ if (ISCON(q))
+ fputc('C', fp);
+ if (ISVOL(q))
+ fputc('V', fp);
+
+ if (ISPTR(t))
+ fprintf(fp, "PTR ");
+ else if (ISFTN(t))
+ fprintf(fp, "FTN ");
+ else if (ISARY(t))
+ fprintf(fp, "ARY ");
+ else {
+ fprintf(fp, "%s%s%s", ISCON(q << TSHIFT) ? "const " : "",
+ ISVOL(q << TSHIFT) ? "volatile " : "", tnames[t]);
+ return;
+ }
+ }
+}
+
+int crslab = 10;
+/*
+ * Return a number for internal labels.
+ */
+int
+getlab()
+{
+ return crslab++;
+}
+
+/*
+ * Memory allocation routines.
+ * Memory are allocated from the system in MEMCHUNKSZ blocks.
+ * permalloc() returns a bunch of memory that is never freed.
+ * Memory allocated through tmpalloc() will be released the
+ * next time a function is ended (via tmpfree()).
+ */
+
+#define MEMCHUNKSZ 8192 /* 8k per allocation */
+struct b {
+ char a1;
+ union {
+ long long l;
+ long double d;
+ } a2;
+};
+
+#define ALIGNMENT ((int)&((struct b *)0)->a2)
+#define ROUNDUP(x) ((x) + (sizeof(ALIGNMENT)-1)) & ~(sizeof(ALIGNMENT)-1)
+
+static char *allocpole;
+static int allocleft;
+static char *tmppole;
+static int tmpleft;
+int permallocsize, tmpallocsize, lostmem;
+
+void *
+permalloc(int size)
+{
+ void *rv;
+
+//printf("permalloc: allocpole %p allocleft %d size %d ", allocpole, allocleft, size);
+ if (size > MEMCHUNKSZ)
+ cerror("permalloc");
+ if (size <= 0)
+ cerror("permalloc2");
+ if (allocleft < size) {
+ /* looses unused bytes */
+ lostmem += allocleft;
+//fprintf(stderr, "allocating perm\n");
+ if ((allocpole = malloc(MEMCHUNKSZ)) == NULL)
+ cerror("permalloc: out of memory");
+ allocleft = MEMCHUNKSZ;
+ }
+ size = ROUNDUP(size);
+ rv = &allocpole[MEMCHUNKSZ-allocleft];
+//printf("rv %p\n", rv);
+ allocleft -= size;
+ permallocsize += size;
+ return rv;
+}
+
+static char *tmplink;
+
+void *
+tmpcalloc(int size)
+{
+ void *rv;
+
+ rv = tmpalloc(size);
+ memset(rv, 0, size);
+ return rv;
+}
+
+#define TMPOLE &tmppole[MEMCHUNKSZ-tmpleft]
+void *
+tmpalloc(int size)
+{
+ void *rv;
+
+ if (size > MEMCHUNKSZ) {
+ return malloc(size);
+ // cerror("tmpalloc %d", size);
+ }
+ if (size <= 0)
+ cerror("tmpalloc2");
+//printf("tmpalloc: tmppole %p tmpleft %d size %d ", tmppole, tmpleft, size);
+ size = ROUNDUP(size);
+ if (tmpleft < size) {
+ if ((tmppole = malloc(MEMCHUNKSZ)) == NULL)
+ cerror("tmpalloc: out of memory");
+//fprintf(stderr, "allocating tmp\n");
+ tmpleft = MEMCHUNKSZ - (ROUNDUP(sizeof(char *)));
+ *(char **)tmppole = tmplink;
+ tmplink = tmppole;
+ }
+ rv = TMPOLE;
+//printf("rv %p\n", rv);
+ tmpleft -= size;
+ tmpallocsize += size;
+ return rv;
+}
+
+#if 0
+/*
+ * Print and pack strings on heap.
+ */
+char *tmpsprintf(char *fmt, ...);
+char *
+tmpsprintf(char *fmt, ...)
+{
+ va_list ap;
+ int len;
+ char *tmp;
+
+ tmp = TMPOLE;
+ va_start(ap, fmt);
+ if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft) {
+ (void)tmpalloc(tmpleft); /* ugly */
+ tmp = TMPOLE;
+ if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft)
+ cerror("bad tmpsprintf len");
+ }
+ va_end(ap);
+ tmpleft += len;
+ return tmp;
+}
+#endif
+
+/*
+ * Print and pack vararg string on heap.
+ */
+char *tmpvsprintf(char *fmt, va_list ap);
+char *
+tmpvsprintf(char *fmt, va_list ap)
+{
+ int len;
+ char *tmp;
+
+ if (tmpleft == 0)
+ (void)tmpalloc(1); /* XXX ugly */
+ tmp = TMPOLE;
+ if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft) {
+ (void)tmpalloc(tmpleft+1); /* ugly */
+ tmp = TMPOLE;
+ if ((len = vsnprintf(tmp, tmpleft, fmt, ap)) >= tmpleft)
+ cerror("bad tmpsprintf len");
+ }
+ tmpleft -= len+1;
+ return tmp;
+}
+
+void
+tmpfree()
+{
+ char *f, *of;
+
+ f = tmplink;
+ if (f == NULL)
+ return;
+ if (*(char **)f == NULL) {
+ tmpleft = MEMCHUNKSZ - (ROUNDUP(sizeof(char *)));
+ return;
+ }
+ while (f != NULL) {
+ of = f;
+ f = *(char **)f;
+ free(of);
+ }
+ tmplink = tmppole = NULL;
+ tmpleft = 0;
+//fprintf(stderr, "freeing tmp\n");
+ /* XXX - nothing right now */
+}
+
+/*
+ * Allocate space on the permanent stack for a string of length len+1
+ * and copy it there.
+ * Return the new address.
+ */
+char *
+newstring(char *s, int len)
+{
+ char *u, *c;
+
+ len++;
+ if (allocleft < len) {
+ u = c = permalloc(len);
+ } else {
+ u = c = &allocpole[MEMCHUNKSZ-allocleft];
+ allocleft -= ROUNDUP(len+1);
+ }
+ while (len--)
+ *c++ = *s++;
+ return u;
+}
diff --git a/usr.bin/pcc/mip/manifest.h b/usr.bin/pcc/mip/manifest.h
new file mode 100644
index 00000000000..dd4cf0ecafb
--- /dev/null
+++ b/usr.bin/pcc/mip/manifest.h
@@ -0,0 +1,316 @@
+/* $Id: manifest.h,v 1.1 2007/09/15 18:12:35 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+#ifndef MANIFEST
+#define MANIFEST
+
+#include <stdio.h>
+#include "../config.h"
+#include "macdefs.h"
+#include "node.h"
+
+/*
+ * Node types
+ */
+#define LTYPE 02 /* leaf */
+#define UTYPE 04 /* unary */
+#define BITYPE 010 /* binary */
+
+/*
+ * DSIZE is the size of the dope array
+ */
+#define DSIZE (MAXOP+1)
+
+/*
+ * Type names, used in symbol table building.
+ * The order of the integer types are important.
+ * Signed types must have bit 0 unset, unsigned types set (used below).
+ */
+#define UNDEF 0 /* free symbol table entry */
+#define FARG 1 /* function argument */
+#define CHAR 2
+#define UCHAR 3
+#define SHORT 4
+#define USHORT 5
+#define INT 6
+#define UNSIGNED 7
+#define LONG 8
+#define ULONG 9
+#define LONGLONG 10
+#define ULONGLONG 11
+#define FLOAT 12
+#define DOUBLE 13
+#define LDOUBLE 14
+#define STRTY 15
+#define UNIONTY 16
+#define ENUMTY 17
+#define MOETY 18 /* member of enum */
+#define VOID 19
+
+#define MAXTYPES 19 /* highest type+1 to be used by lang code */
+/*
+ * Various flags
+ */
+#define NOLAB (-1)
+
+/*
+ * Type modifiers.
+ */
+#define PTR 0x20
+#define FTN 0x40
+#define ARY 0x60
+#define CON 0x20
+#define VOL 0x40
+
+/*
+ * Type packing constants
+ */
+#define TMASK 0x060
+#define TMASK1 0x180
+#define TMASK2 0x1e0
+#define BTMASK 0x1f
+#define BTSHIFT 5
+#define TSHIFT 2
+
+/*
+ * Macros
+ */
+#define MODTYPE(x,y) x = ((x)&(~BTMASK))|(y) /* set basic type of x to y */
+#define BTYPE(x) ((x)&BTMASK) /* basic type of x */
+#define ISLONGLONG(x) ((x) == LONGLONG || (x) == ULONGLONG)
+#define ISUNSIGNED(x) (((x) <= ULONGLONG) && (((x) & 1) == (UNSIGNED & 1)))
+#define UNSIGNABLE(x) (((x)<=ULONGLONG&&(x)>=CHAR) && !ISUNSIGNED(x))
+#define ENUNSIGN(x) ((x)|1)
+#define DEUNSIGN(x) ((x)&~1)
+#define ISPTR(x) (((x)&TMASK)==PTR)
+#define ISFTN(x) (((x)&TMASK)==FTN) /* is x a function type? */
+#define ISARY(x) (((x)&TMASK)==ARY) /* is x an array type? */
+#define ISCON(x) (((x)&CON)==CON) /* is x const? */
+#define ISVOL(x) (((x)&VOL)==VOL) /* is x volatile? */
+#define INCREF(x) ((((x)&~BTMASK)<<TSHIFT)|PTR|((x)&BTMASK))
+#define INCQAL(x) ((((x)&~BTMASK)<<TSHIFT)|((x)&BTMASK))
+#define DECREF(x) ((((x)>>TSHIFT)&~BTMASK)|((x)&BTMASK))
+#define DECQAL(x) ((((x)>>TSHIFT)&~BTMASK)|((x)&BTMASK))
+#define SETOFF(x,y) { if ((x)%(y) != 0) (x) = (((x)/(y) + 1) * (y)); }
+ /* advance x to a multiple of y */
+#define NOFIT(x,y,z) (((x)%(z) + (y)) > (z))
+ /* can y bits be added to x without overflowing z */
+
+#ifndef SPECIAL_INTEGERS
+#define ASGLVAL(lval, val)
+#endif
+
+/*
+ * Pack and unpack field descriptors (size and offset)
+ */
+#define PKFIELD(s,o) (((o)<<6)| (s))
+#define UPKFSZ(v) ((v)&077)
+#define UPKFOFF(v) ((v)>>6)
+
+/*
+ * Operator information
+ */
+#define TYFLG 016
+#define ASGFLG 01
+#define LOGFLG 020
+
+#define SIMPFLG 040
+#define COMMFLG 0100
+#define DIVFLG 0200
+#define FLOFLG 0400
+#define LTYFLG 01000
+#define CALLFLG 02000
+#define MULFLG 04000
+#define SHFFLG 010000
+#define ASGOPFLG 020000
+
+#define SPFLG 040000
+
+/*
+ * Location counters
+ */
+#define PROG 0 /* (ro) program segment */
+#define DATA 1 /* (rw) data segment */
+#define RDATA 2 /* (ro) data segment */
+#define STRNG 3 /* (ro) string segment */
+
+
+/*
+ *
+ */
+extern int bdebug, tdebug, edebug;
+extern int ddebug, xdebug, f2debug;
+extern int iTflag, oTflag;
+extern int vdebug, sflag, nflag, gflag;
+extern int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
+ Wimplicit_function_declaration;
+extern int xssaflag, xtailcallflag, xtemps, xdeljumps;
+
+int yyparse(void);
+void yyaccpt(void);
+
+/*
+ * List handling macros, similar to those in 4.4BSD.
+ * The double-linked list is insque-style.
+ */
+/* Double-linked list macros */
+#define DLIST_INIT(h,f) { (h)->f.q_forw = (h); (h)->f.q_back = (h); }
+#define DLIST_ENTRY(t) struct { struct t *q_forw, *q_back; }
+#define DLIST_NEXT(h,f) (h)->f.q_forw
+#define DLIST_PREV(h,f) (h)->f.q_back
+#define DLIST_ISEMPTY(h,f) ((h)->f.q_forw == (h))
+#define DLIST_FOREACH(v,h,f) \
+ for ((v) = (h)->f.q_forw; (v) != (h); (v) = (v)->f.q_forw)
+#define DLIST_FOREACH_REVERSE(v,h,f) \
+ for ((v) = (h)->f.q_back; (v) != (h); (v) = (v)->f.q_back)
+#define DLIST_INSERT_BEFORE(h,e,f) { \
+ (e)->f.q_forw = (h); \
+ (e)->f.q_back = (h)->f.q_back; \
+ (e)->f.q_back->f.q_forw = (e); \
+ (h)->f.q_back = (e); \
+}
+#define DLIST_INSERT_AFTER(h,e,f) { \
+ (e)->f.q_forw = (h)->f.q_forw; \
+ (e)->f.q_back = (h); \
+ (e)->f.q_forw->f.q_back = (e); \
+ (h)->f.q_forw = (e); \
+}
+#define DLIST_REMOVE(e,f) { \
+ (e)->f.q_forw->f.q_back = (e)->f.q_back; \
+ (e)->f.q_back->f.q_forw = (e)->f.q_forw; \
+}
+
+/* Single-linked list */
+#define SLIST_INIT(h) \
+ { (h)->q_forw = NULL; (h)->q_last = &(h)->q_forw; }
+#define SLIST_ENTRY(t) struct { struct t *q_forw; }
+#define SLIST_HEAD(n,t) struct n { struct t *q_forw, **q_last; }
+#define SLIST_FIRST(h) ((h)->q_forw)
+#define SLIST_FOREACH(v,h,f) \
+ for ((v) = (h)->q_forw; (v) != NULL; (v) = (v)->f.q_forw)
+#define SLIST_INSERT_LAST(h,e,f) { \
+ (e)->f.q_forw = NULL; \
+ *(h)->q_last = (e); \
+ (h)->q_last = &(e)->f.q_forw; \
+}
+
+/*
+ * Functions for inter-pass communication.
+ *
+ */
+struct interpass {
+ DLIST_ENTRY(interpass) qelem;
+ int type;
+ int lineno;
+ union {
+ NODE *_p;
+ int _locctr;
+ int _label;
+ int _curoff;
+ char *_name;
+ } _un;
+};
+
+/*
+ * Special struct for prologue/epilogue.
+ * - ip_lblnum contains the lowest/highest+1 label used
+ * - ip_lbl is set before/after all code and after/before the prolog/epilog.
+ */
+struct interpass_prolog {
+ struct interpass ipp_ip;
+ char *ipp_name; /* Function name */
+ int ipp_vis; /* Function visibility */
+ TWORD ipp_type; /* Function type */
+ int ipp_regs; /* Bitmask of registers to save */
+ int ipp_autos; /* Size on stack needed */
+ int ip_tmpnum; /* # allocated temp nodes so far */
+ int ip_lblnum; /* # used labels so far */
+};
+
+/*
+ * Epilog/prolog takes following arguments (in order):
+ * - type
+ * - regs
+ * - autos
+ * - name
+ * - type
+ * - retlab
+ */
+
+#define ip_node _un._p
+#define ip_locc _un._locctr
+#define ip_lbl _un._label
+#define ip_name _un._name
+#define ip_asm _un._name
+#define ip_off _un._curoff
+
+/* Types of inter-pass structs */
+#define IP_NODE 1
+#define IP_PROLOG 2
+#define IP_EPILOG 4
+#define IP_DEFLAB 5
+#define IP_DEFNAM 6
+#define IP_ASM 7
+#define MAXIP 7
+
+void send_passt(int type, ...);
+/*
+ * External declarations, typedefs and the like
+ */
+char *hash(char *s);
+char *savestr(char *cp);
+char *tstr(char *cp);
+
+/* memory management stuff */
+void *permalloc(int size);
+void *tmpcalloc(int size);
+void *tmpalloc(int size);
+void tmpfree(void);
+char *newstring(char *, int len);
+
+void tprint(FILE *, TWORD, TWORD);
+
+/* pass t communication subroutines */
+void topt_compile(struct interpass *);
+
+/* pass 2 communication subroutines */
+void pass2_compile(struct interpass *);
+
+/* node routines */
+NODE *nfree(NODE *);
+void fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down);
+
+extern int nerrors; /* number of errors seen so far */
+#endif
diff --git a/usr.bin/pcc/mip/match.c b/usr.bin/pcc/mip/match.c
new file mode 100644
index 00000000000..503b4698ab0
--- /dev/null
+++ b/usr.bin/pcc/mip/match.c
@@ -0,0 +1,995 @@
+/* $Id: match.c,v 1.1 2007/09/15 18:12:36 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <strings.h>
+
+void prttype(int t);
+void setclass(int tmp, int class);
+int getclass(int tmp);
+
+int fldsz, fldshf;
+
+int s2debug = 0;
+
+extern char *ltyp[], *rtyp[];
+
+static char *srtyp[] = { "SRNOPE", "SRDIR", "SROREG", "SRREG" };
+
+/*
+ * return true if shape is appropriate for the node p
+ * side effect for SFLD is to set up fldsz, etc
+ *
+ * Return values:
+ * SRNOPE Cannot match this shape.
+ * SRDIR Direct match, may or may not traverse down.
+ * SRREG Will match if put in a regster XXX - kill this?
+ */
+int
+tshape(NODE *p, int shape)
+{
+ int o, mask;
+
+ o = p->n_op;
+
+#ifdef PCC_DEBUG
+ if (s2debug)
+ printf("tshape(%p, %s) op = %s\n", p, prcook(shape), opst[o]);
+#endif
+
+ if (shape & SPECIAL) {
+
+ switch (shape) {
+ case SZERO:
+ case SONE:
+ case SMONE:
+ case SSCON:
+ case SCCON:
+ if (o != ICON || p->n_name[0])
+ return SRNOPE;
+ if (p->n_lval == 0 && shape == SZERO)
+ return SRDIR;
+ if (p->n_lval == 1 && shape == SONE)
+ return SRDIR;
+ if (p->n_lval == -1 && shape == SMONE)
+ return SRDIR;
+ if (p->n_lval > -257 && p->n_lval < 256 &&
+ shape == SCCON)
+ return SRDIR;
+ if (p->n_lval > -32769 && p->n_lval < 32768 &&
+ shape == SSCON)
+ return SRDIR;
+ return SRNOPE;
+
+ case SSOREG: /* non-indexed OREG */
+ if (o == OREG && !R2TEST(p->n_rval))
+ return SRDIR;
+ return SRNOPE;
+
+ default:
+ return (special(p, shape));
+ }
+ }
+
+ if (shape & SANY)
+ return SRDIR;
+
+ if ((shape&INTEMP) && shtemp(p)) /* XXX remove? */
+ return SRDIR;
+
+ if ((shape&SWADD) && (o==NAME||o==OREG))
+ if (BYTEOFF(p->n_lval))
+ return SRNOPE;
+
+ switch (o) {
+
+ case NAME:
+ if (shape & SNAME)
+ return SRDIR;
+ break;
+
+ case ICON:
+ if (shape & SCON)
+ return SRDIR;
+ break;
+
+ case FLD:
+ if (shape & SFLD) {
+ int sh;
+
+ if ((sh = flshape(p->n_left)) == SRNOPE)
+ return sh;
+ /* it is a FIELD shape; make side-effects */
+ /* XXX - this will not work for multi-matches */
+ o = p->n_rval;
+ fldsz = UPKFSZ(o);
+# ifdef RTOLBYTES
+ fldshf = UPKFOFF(o);
+# else
+ fldshf = SZINT - fldsz - UPKFOFF(o);
+# endif
+ return sh;
+ }
+ break;
+
+ case CCODES:
+ if (shape & SCC)
+ return SRDIR;
+ break;
+
+ case REG:
+ case TEMP:
+ mask = PCLASS(p);
+ if (shape & mask)
+ return SRDIR;
+ break;
+
+ case OREG:
+ if (shape & SOREG)
+ return SRDIR;
+ break;
+
+ case UMUL:
+ if (shumul(p->n_left) & shape)
+ return SROREG; /* Calls offstar to traverse down */
+ break;
+
+ }
+ return SRNOPE;
+}
+
+/*
+ * does the type t match tword
+ */
+int
+ttype(TWORD t, int tword)
+{
+ if (tword & TANY)
+ return(1);
+
+#ifdef PCC_DEBUG
+ if (t2debug)
+ printf("ttype(%o, %o)\n", t, tword);
+#endif
+ if (ISPTR(t) && ISFTN(DECREF(t)) && (tword & TFTN)) {
+ /* For funny function pointers */
+ return 1;
+ }
+ if (ISPTR(t) && (tword&TPTRTO)) {
+ do {
+ t = DECREF(t);
+ } while (ISARY(t));
+ /* arrays that are left are usually only
+ * in structure references...
+ */
+ return (ttype(t, tword&(~TPTRTO)));
+ }
+ if (t != BTYPE(t))
+ return (tword & TPOINT); /* TPOINT means not simple! */
+ if (tword & TPTRTO)
+ return(0);
+
+ switch (t) {
+ case CHAR:
+ return( tword & TCHAR );
+ case SHORT:
+ return( tword & TSHORT );
+ case STRTY:
+ case UNIONTY:
+ return( tword & TSTRUCT );
+ case INT:
+ return( tword & TINT );
+ case UNSIGNED:
+ return( tword & TUNSIGNED );
+ case USHORT:
+ return( tword & TUSHORT );
+ case UCHAR:
+ return( tword & TUCHAR );
+ case ULONG:
+ return( tword & TULONG );
+ case LONG:
+ return( tword & TLONG );
+ case LONGLONG:
+ return( tword & TLONGLONG );
+ case ULONGLONG:
+ return( tword & TULONGLONG );
+ case FLOAT:
+ return( tword & TFLOAT );
+ case DOUBLE:
+ return( tword & TDOUBLE );
+ case LDOUBLE:
+ return( tword & TLDOUBLE );
+ }
+
+ return(0);
+}
+
+/*
+ * generate code by interpreting table entry
+ */
+void
+expand(NODE *p, int cookie, char *cp)
+{
+ CONSZ val;
+
+ for( ; *cp; ++cp ){
+ switch( *cp ){
+
+ default:
+ PUTCHAR( *cp );
+ continue; /* this is the usual case... */
+
+ case 'Z': /* special machine dependent operations */
+ zzzcode( p, *++cp );
+ continue;
+
+ case 'F': /* this line deleted if FOREFF is active */
+ if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
+ continue;
+
+ case 'S': /* field size */
+ printf( "%d", fldsz );
+ continue;
+
+ case 'H': /* field shift */
+ printf( "%d", fldshf );
+ continue;
+
+ case 'M': /* field mask */
+ case 'N': /* complement of field mask */
+ val = 1;
+ val <<= fldsz;
+ --val;
+ val <<= fldshf;
+ adrcon( *cp=='M' ? val : ~val );
+ continue;
+
+ case 'L': /* output special label field */
+ if (*++cp == 'C')
+ printf(LABFMT, p->n_label);
+ else
+ printf(LABFMT, (int)getlr(p,*cp)->n_lval);
+ continue;
+
+ case 'O': /* opcode string */
+ hopcode( *++cp, p->n_op );
+ continue;
+
+ case 'B': /* byte offset in word */
+ val = getlr(p,*++cp)->n_lval;
+ val = BYTEOFF(val);
+ printf( CONFMT, val );
+ continue;
+
+ case 'C': /* for constant value only */
+ conput(stdout, getlr( p, *++cp ) );
+ continue;
+
+ case 'I': /* in instruction */
+ insput( getlr( p, *++cp ) );
+ continue;
+
+ case 'A': /* address of */
+ adrput(stdout, getlr( p, *++cp ) );
+ continue;
+
+ case 'U': /* for upper half of address, only */
+ upput(getlr(p, *++cp), SZLONG);
+ continue;
+
+ }
+
+ }
+
+ }
+
+NODE resc[4];
+
+NODE *
+getlr(NODE *p, int c)
+{
+ NODE *q;
+
+ /* return the pointer to the left or right side of p, or p itself,
+ depending on the optype of p */
+
+ switch (c) {
+
+ case '1':
+ case '2':
+ case '3':
+ case 'D':
+ if (c == 'D')
+ c = 0;
+ else
+ c -= '0';
+ q = &resc[c];
+ q->n_op = REG;
+ q->n_type = p->n_type; /* XXX should be correct type */
+ q->n_rval = DECRA(p->n_reg, c);
+ q->n_su = p->n_su;
+ return q;
+
+ case 'L':
+ return( optype( p->n_op ) == LTYPE ? p : p->n_left );
+
+ case 'R':
+ return( optype( p->n_op ) != BITYPE ? p : p->n_right );
+
+ }
+ cerror( "bad getlr: %c", c );
+ /* NOTREACHED */
+ return NULL;
+}
+
+static char *tarr[] = {
+ "CHAR", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE", "POINT", "UCHAR",
+ "USHORT", "UINT", "ULONG", "PTRTO", "ANY", "STRUCT", "LONGLONG",
+ "ULONGLONG",
+};
+
+void
+prttype(int t)
+{
+ int i, gone = 0;
+
+ for (i = 0; i < 16; i++)
+ if ((t >> i) & 1) {
+ if (gone) putchar('|');
+ gone++;
+ printf("%s", tarr[i]);
+ }
+}
+
+
+#ifdef PCC_DEBUG
+#define F2DEBUG(x) if (f2debug) printf x
+#define F2WALK(x) if (f2debug) fwalk(x, e2print, 0)
+#else
+#define F2DEBUG(x)
+#define F2WALK(x)
+#endif
+
+/*
+ * Convert a node to REG or OREG.
+ * Shape is register class where we want the result.
+ * Returns register class if register nodes.
+ * If w is: (should be shapes)
+ * - LREG - result in register, call geninsn().
+ * - LOREG - create OREG; call offstar().
+ * - 0 - clear su, walk down.
+ */
+static int
+swmatch(NODE *p, int shape, int w)
+{
+ int rv = 0;
+
+ switch (w) {
+ case LREG:
+ rv = geninsn(p, shape);
+ break;
+
+ case LOREG:
+ /* should be here only if op == UMUL */
+ if (p->n_op != UMUL && p->n_op != FLD)
+ comperr("swmatch %p", p);
+ if (p->n_op == FLD) {
+ offstar(p->n_left->n_left, shape);
+ p->n_left->n_su = 0;
+ } else
+ offstar(p->n_left, shape);
+ p->n_su = 0;
+ rv = ffs(shape)-1;
+ break;
+
+ case 0:
+ if (optype(p->n_op) == BITYPE)
+ swmatch(p->n_right, 0, 0);
+ if (optype(p->n_op) != LTYPE)
+ swmatch(p->n_left, 0, 0);
+ p->n_su = 0;
+ }
+ return rv;
+
+}
+
+/*
+ * Help routines for find*() functions.
+ * If the node will be a REG node and it will be rewritten in the
+ * instruction, ask for it to be put in a register.
+ */
+static int
+chcheck(NODE *p, int shape, int rew)
+{
+ int sh, sha;
+
+ sha = shape;
+ if (shape & SPECIAL)
+ shape = 0;
+
+ switch ((sh = tshape(p, sha))) {
+ case SRNOPE:
+ if (shape & INREGS)
+ sh = SRREG;
+ break;
+
+ case SROREG:
+ case SRDIR:
+ if (rew == 0)
+ break;
+ if (shape & INREGS)
+ sh = SRREG;
+ else
+ sh = SRNOPE;
+ break;
+ }
+ return sh;
+}
+
+/*
+ * Check how to walk further down.
+ * Merge with swmatch()?
+ * sh - shape for return value (register class).
+ * p - node (for this leg)
+ * shape - given shape for this leg
+ * cookie - cookie given for parent node
+ * rv - switch key for traversing down
+ * returns register class.
+ */
+static int
+shswitch(int sh, NODE *p, int shape, int cookie, int rew, int go)
+{
+ int lsh;
+
+ switch (go) {
+ case SRDIR: /* direct match, just clear su */
+ (void)swmatch(p, 0, 0);
+ break;
+
+ case SROREG: /* call offstar to prepare for OREG conversion */
+ (void)swmatch(p, shape, LOREG);
+ break;
+
+ case SRREG: /* call geninsn() to get value into register */
+ lsh = shape & INREGS;
+ if (rew && cookie != FOREFF)
+ lsh &= (cookie & INREGS);
+ lsh = swmatch(p, lsh, LREG);
+ if (rew)
+ sh = lsh;
+ break;
+ }
+ return sh;
+}
+
+/*
+ * Find the best instruction to evaluate the given tree.
+ * Best is to match both subnodes directly, second-best is if
+ * subnodes must be evaluated into OREGs, thereafter if nodes
+ * must be put into registers.
+ * Whether 2-op instructions or 3-op is preferred is depending on in
+ * which order they are found in the table.
+ * mtchno is set to the count of regs needed for its legs.
+ */
+int
+findops(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q, *qq = NULL;
+ int i, shl, shr, *ixp, sh;
+ int lvl = 10, idx = 0, gol = 0, gor = 0;
+ NODE *l, *r;
+
+ F2DEBUG(("findops node %p (%s)\n", p, prcook(cookie)));
+ F2WALK(p);
+
+ ixp = qtable[p->n_op];
+ l = getlr(p, 'L');
+ r = getlr(p, 'R');
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("findop: ixp %d\n", ixp[i]));
+ if (ttype(l->n_type, q->ltype) == 0 ||
+ ttype(r->n_type, q->rtype) == 0)
+ continue; /* Types must be correct */
+
+ if ((cookie & q->visit) == 0)
+ continue; /* must get a result */
+
+ F2DEBUG(("findop got types\n"));
+
+ if ((shl = chcheck(l, q->lshape, q->rewrite & RLEFT)) == SRNOPE)
+ continue;
+
+ F2DEBUG(("findop lshape %d\n", shl));
+ F2WALK(l);
+
+ if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT))== SRNOPE) continue;
+
+ F2DEBUG(("findop rshape %d\n", shr));
+ F2WALK(r);
+
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ if (lvl <= (shl + shr))
+ continue;
+ lvl = shl + shr;
+ qq = q;
+ idx = ixp[i];
+ gol = shl;
+ gor = shr;
+ }
+ if (lvl == 10) {
+ F2DEBUG(("findops failed\n"));
+ if (setbin(p))
+ return FRETRY;
+ return FFAIL;
+ }
+
+ F2DEBUG(("findops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
+
+ sh = -1;
+
+ sh = shswitch(sh, p->n_left, qq->lshape, cookie,
+ qq->rewrite & RLEFT, gol);
+ sh = shswitch(sh, p->n_right, qq->rshape, cookie,
+ qq->rewrite & RRIGHT, gor);
+
+ if (sh == -1) {
+ if (cookie == FOREFF)
+ sh = 0;
+ else
+ sh = ffs(cookie & qq->visit & INREGS)-1;
+ }
+ F2DEBUG(("findops: node %p (%s)\n", p, prcook(1 << sh)));
+ p->n_su = MKIDX(idx, 0);
+ SCLASS(p->n_su, sh);
+ return sh;
+}
+
+/*
+ * Find the best relation op for matching the two trees it has.
+ * This is a sub-version of the function findops() above.
+ * The instruction with the lowest grading is emitted.
+ *
+ * Level assignment for priority:
+ * left right prio
+ * - - -
+ * direct direct 1
+ * direct OREG 2 # make oreg
+ * OREG direct 2 # make oreg
+ * OREG OREG 2 # make both oreg
+ * direct REG 3 # put in reg
+ * OREG REG 3 # put in reg, make oreg
+ * REG direct 3 # put in reg
+ * REG OREG 3 # put in reg, make oreg
+ * REG REG 4 # put both in reg
+ */
+int
+relops(NODE *p)
+{
+ extern int *qtable[];
+ struct optab *q;
+ int i, shl = 0, shr = 0;
+ NODE *l, *r;
+ int *ixp, idx = 0;
+ int lvl = 10, gol = 0, gor = 0;
+
+ F2DEBUG(("relops tree:\n"));
+ F2WALK(p);
+
+ l = getlr(p, 'L');
+ r = getlr(p, 'R');
+ ixp = qtable[p->n_op];
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("relops: ixp %d\n", ixp[i]));
+ if (ttype(l->n_type, q->ltype) == 0 ||
+ ttype(r->n_type, q->rtype) == 0)
+ continue; /* Types must be correct */
+
+ F2DEBUG(("relops got types\n"));
+ if ((shl = chcheck(l, q->lshape, 0)) == SRNOPE)
+ continue;
+ F2DEBUG(("relops lshape %d\n", shl));
+ F2WALK(p);
+ if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE)
+ continue;
+ F2DEBUG(("relops rshape %d\n", shr));
+ F2WALK(p);
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ if (lvl <= (shl + shr))
+ continue;
+ lvl = shl + shr;
+ idx = ixp[i];
+ gol = shl;
+ gor = shr;
+ }
+ if (lvl == 10) {
+ F2DEBUG(("relops failed\n"));
+ if (setbin(p))
+ return FRETRY;
+ return FFAIL;
+ }
+ F2DEBUG(("relops entry %d(%s %s)\n", idx, srtyp[gol], srtyp[gor]));
+
+ q = &table[idx];
+
+ (void)shswitch(-1, p->n_left, q->lshape, FORCC,
+ q->rewrite & RLEFT, gol);
+
+ (void)shswitch(-1, p->n_right, q->rshape, FORCC,
+ q->rewrite & RRIGHT, gor);
+
+ F2DEBUG(("findops: node %p\n", p));
+ p->n_su = MKIDX(idx, 0);
+ SCLASS(p->n_su, CLASSA); /* XXX */
+ return 0;
+}
+
+/*
+ * Find a matching assign op.
+ *
+ * Level assignment for priority:
+ * left right prio
+ * - - -
+ * direct direct 1
+ * direct REG 2
+ * direct OREG 3
+ * OREG direct 4
+ * OREG REG 5
+ * OREG OREG 6
+ */
+int
+findasg(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q;
+ int i, sh, shl, shr, lvl = 10;
+ NODE *l, *r;
+ int *ixp;
+ struct optab *qq = NULL; /* XXX gcc */
+ int idx = 0, gol = 0, gor = 0;
+
+ shl = shr = 0;
+
+ F2DEBUG(("findasg tree: %s\n", prcook(cookie)));
+ F2WALK(p);
+
+ ixp = qtable[p->n_op];
+ l = getlr(p, 'L');
+ r = getlr(p, 'R');
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("asgop: ixp %d\n", ixp[i]));
+ if (ttype(l->n_type, q->ltype) == 0 ||
+ ttype(r->n_type, q->rtype) == 0)
+ continue; /* Types must be correct */
+
+ if ((cookie & q->visit) == 0)
+ continue; /* must get a result */
+
+ F2DEBUG(("asgop got types\n"));
+ if ((shl = tshape(l, q->lshape)) == SRNOPE)
+ continue;
+
+ if (shl == SRREG)
+ continue;
+
+ F2DEBUG(("asgop lshape %d\n", shl));
+ F2WALK(l);
+
+ if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT))== SRNOPE)
+ continue;
+
+ F2DEBUG(("asgop rshape %d\n", shr));
+ F2WALK(r);
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ if (lvl <= (shl + shr))
+ continue;
+
+ lvl = shl + shr;
+ qq = q;
+ idx = ixp[i];
+ gol = shl;
+ gor = shr;
+ }
+
+ if (lvl == 10) {
+ F2DEBUG(("findasg failed\n"));
+ if (setasg(p, cookie))
+ return FRETRY;
+ return FFAIL;
+ }
+ F2DEBUG(("findasg entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
+
+ sh = -1;
+ sh = shswitch(sh, p->n_left, qq->lshape, cookie,
+ qq->rewrite & RLEFT, gol);
+
+ sh = shswitch(sh, p->n_right, qq->rshape, cookie,
+ qq->rewrite & RRIGHT, gor);
+
+ if (sh == -1) {
+ if (cookie == FOREFF)
+ sh = 0;
+ else
+ sh = ffs(cookie & qq->visit & INREGS)-1;
+ }
+ F2DEBUG(("findasg: node %p class %d\n", p, sh));
+
+ p->n_su = MKIDX(idx, 0);
+ SCLASS(p->n_su, sh);
+
+ return sh;
+}
+
+/*
+ * Search for an UMUL table entry that can turn an indirect node into
+ * a move from an OREG.
+ */
+int
+findumul(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q = NULL; /* XXX gcc */
+ int i, shl = 0, shr = 0, sh;
+ int *ixp;
+
+ F2DEBUG(("findumul p %p (%s)\n", p, prcook(cookie)));
+ F2WALK(p);
+
+ ixp = qtable[p->n_op];
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("findumul: ixp %d\n", ixp[i]));
+ if ((q->visit & cookie) == 0)
+ continue; /* wrong registers */
+
+ if (ttype(p->n_type, q->rtype) == 0)
+ continue; /* Types must be correct */
+
+
+ F2DEBUG(("findumul got types, rshape %s\n", prcook(q->rshape)));
+ /*
+ * Try to create an OREG of the node.
+ * Fake left even though it's right node,
+ * to be sure of conversion if going down left.
+ */
+ if ((shl = chcheck(p, q->rshape, 0)) == SRNOPE)
+ continue;
+
+ shr = 0;
+
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ F2DEBUG(("findumul got shape %s\n", srtyp[shl]));
+
+ break; /* XXX search better matches */
+ }
+ if (ixp[i] < 0) {
+ F2DEBUG(("findumul failed\n"));
+ if (setuni(p, cookie))
+ return FRETRY;
+ return FFAIL;
+ }
+ F2DEBUG(("findumul entry %d(%s %s)\n", ixp[i], srtyp[shl], srtyp[shr]));
+
+ sh = shswitch(-1, p, q->rshape, cookie, q->rewrite & RLEFT, shl);
+ if (sh == -1)
+ sh = ffs(cookie & q->visit & INREGS)-1;
+
+ F2DEBUG(("findumul: node %p (%s)\n", p, prcook(1 << sh)));
+ p->n_su = MKIDX(ixp[i], 0);
+ SCLASS(p->n_su, sh);
+ return sh;
+}
+
+/*
+ * Find a leaf type node that puts the value into a register.
+ */
+int
+findleaf(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q = NULL; /* XXX gcc */
+ int i, sh;
+ int *ixp;
+
+ F2DEBUG(("findleaf p %p (%s)\n", p, prcook(cookie)));
+ F2WALK(p);
+
+ ixp = qtable[p->n_op];
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("findleaf: ixp %d\n", ixp[i]));
+ if ((q->visit & cookie) == 0)
+ continue; /* wrong registers */
+
+ if (ttype(p->n_type, q->rtype) == 0 ||
+ ttype(p->n_type, q->ltype) == 0)
+ continue; /* Types must be correct */
+
+ F2DEBUG(("findleaf got types, rshape %s\n", prcook(q->rshape)));
+
+ if (chcheck(p, q->rshape, 0) != SRDIR)
+ continue;
+
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ break;
+ }
+ if (ixp[i] < 0) {
+ F2DEBUG(("findleaf failed\n"));
+ if (setuni(p, cookie))
+ return FRETRY;
+ return FFAIL;
+ }
+ F2DEBUG(("findleaf entry %d\n", ixp[i]));
+
+ sh = ffs(cookie & q->visit & INREGS)-1;
+ F2DEBUG(("findleaf: node %p (%s)\n", p, prcook(1 << sh)));
+ p->n_su = MKIDX(ixp[i], 0);
+ SCLASS(p->n_su, sh);
+ return sh;
+}
+
+/*
+ * Find a UNARY op that satisfy the needs.
+ * For now, the destination is always a register.
+ * Both source and dest types must match, but only source (left)
+ * shape is of interest.
+ */
+int
+finduni(NODE *p, int cookie)
+{
+ extern int *qtable[];
+ struct optab *q;
+ NODE *l, *r;
+ int i, shl = 0, num = 4;
+ int *ixp, idx = 0;
+ int sh;
+
+ F2DEBUG(("finduni tree: %s\n", prcook(cookie)));
+ F2WALK(p);
+
+ l = getlr(p, 'L');
+ if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL)
+ r = p;
+ else
+ r = getlr(p, 'R');
+ ixp = qtable[p->n_op];
+ for (i = 0; ixp[i] >= 0; i++) {
+ q = &table[ixp[i]];
+
+ F2DEBUG(("finduni: ixp %d\n", ixp[i]));
+ if (ttype(l->n_type, q->ltype) == 0)
+ continue; /* Type must be correct */
+
+ F2DEBUG(("finduni got left type\n"));
+ if (ttype(r->n_type, q->rtype) == 0)
+ continue; /* Type must be correct */
+
+ F2DEBUG(("finduni got types\n"));
+ if ((shl = chcheck(l, q->lshape, q->rewrite & RLEFT)) == SRNOPE)
+ continue;
+
+ F2DEBUG(("finduni got shapes %d\n", shl));
+
+ if ((cookie & q->visit) == 0) /* check correct return value */
+ continue; /* XXX - should check needs */
+
+ /* avoid clobbering of longlived regs */
+ /* let register allocator coalesce */
+ if ((q->rewrite & RLEFT) && (shl == SRDIR) /* && isreg(l) */)
+ shl = SRREG;
+
+ F2DEBUG(("finduni got cookie\n"));
+ if (q->needs & REWRITE)
+ break; /* Done here */
+
+ if (shl >= num)
+ continue;
+ num = shl;
+ idx = ixp[i];
+
+ if (shl == SRDIR)
+ break;
+ }
+
+ if (num == 4) {
+ F2DEBUG(("finduni failed\n"));
+ } else
+ F2DEBUG(("finduni entry %d(%s)\n", idx, srtyp[num]));
+
+ if (num == 4) {
+ if (setuni(p, cookie))
+ return FRETRY;
+ return FFAIL;
+ }
+ q = &table[idx];
+
+ sh = shswitch(-1, p->n_left, q->lshape, cookie,
+ q->rewrite & RLEFT, num);
+ if (sh == -1)
+ sh = ffs(cookie & q->visit & INREGS)-1;
+ if (sh == -1)
+ sh = 0;
+
+ F2DEBUG(("finduni: node %p (%s)\n", p, prcook(1 << sh)));
+ p->n_su = MKIDX(idx, 0);
+ SCLASS(p->n_su, sh);
+ return sh;
+}
diff --git a/usr.bin/pcc/mip/mkext.c b/usr.bin/pcc/mip/mkext.c
new file mode 100644
index 00000000000..347dd8ee43f
--- /dev/null
+++ b/usr.bin/pcc/mip/mkext.c
@@ -0,0 +1,318 @@
+
+/*
+ * Generate defines for the needed hardops.
+ */
+#include "pass2.h"
+
+#include <string.h>
+
+int chkop[MAXOP];
+
+void mktables(void);
+
+char *cname = "external.c";
+char *hname = "external.h";
+FILE *fc, *fh;
+
+/*
+ * masks for matching dope with shapes
+ */
+int mamask[] = {
+ SIMPFLG, /* OPSIMP */
+ SIMPFLG|ASGFLG, /* ASG OPSIMP */
+ COMMFLG, /* OPCOMM */
+ COMMFLG|ASGFLG, /* ASG OPCOMM */
+ MULFLG, /* OPMUL */
+ MULFLG|ASGFLG, /* ASG OPMUL */
+ DIVFLG, /* OPDIV */
+ DIVFLG|ASGFLG, /* ASG OPDIV */
+ UTYPE, /* OPUNARY */
+ TYFLG, /* ASG OPUNARY is senseless */
+ LTYPE, /* OPLEAF */
+ TYFLG, /* ASG OPLEAF is senseless */
+ 0, /* OPANY */
+ ASGOPFLG|ASGFLG, /* ASG OPANY */
+ LOGFLG, /* OPLOG */
+ TYFLG, /* ASG OPLOG is senseless */
+ FLOFLG, /* OPFLOAT */
+ FLOFLG|ASGFLG, /* ASG OPFLOAT */
+ SHFFLG, /* OPSHFT */
+ SHFFLG|ASGFLG, /* ASG OPSHIFT */
+ SPFLG, /* OPLTYPE */
+ TYFLG, /* ASG OPLTYPE is senseless */
+ };
+
+
+struct checks {
+ int op, type;
+ char *name;
+} checks[] = {
+ { MUL, TLONGLONG, "SMULLL", },
+ { DIV, TLONGLONG, "SDIVLL", },
+ { MOD, TLONGLONG, "SMODLL", },
+ { PLUS, TLONGLONG, "SPLUSLL", },
+ { MINUS, TLONGLONG, "SMINUSLL", },
+ { MUL, TULONGLONG, "UMULLL", },
+ { DIV, TULONGLONG, "UDIVLL", },
+ { MOD, TULONGLONG, "UMODLL", },
+ { PLUS, TULONGLONG, "UPLUSLL", },
+ { MINUS, TULONGLONG, "UMINUSLL", },
+ { 0, 0, 0, },
+};
+
+int rstatus[] = { RSTATUS };
+int roverlay[MAXREGS][MAXREGS] = { ROVERLAP };
+int regclassmap[NUMCLASS][MAXREGS];
+
+static void
+compl(struct optab *q, char *str)
+{
+ printf("table entry %td, op %s: %s\n", q - table, opst[q->op], str);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct optab *q;
+ struct checks *ch;
+ int i, j, areg, breg, creg, dreg, mx;
+ char *bitary;
+ int bitsz, rval, nelem;
+
+ mkdope();
+
+ for (q = table; q->op != FREE; q++) {
+ if (q->op >= OPSIMP)
+ continue;
+ if ((q->ltype & TLONGLONG) &&
+ (q->rtype & TLONGLONG))
+ chkop[q->op] |= TLONGLONG;
+ if ((q->ltype & TULONGLONG) &&
+ (q->rtype & TULONGLONG))
+ chkop[q->op] |= TULONGLONG;
+ }
+ if ((fc = fopen(cname, "w")) == NULL) {
+ perror("open cfile");
+ return(1);
+ }
+ if ((fh = fopen(hname, "w")) == NULL) {
+ perror("open hfile");
+ return(1);
+ }
+ for (ch = checks; ch->op != 0; ch++) {
+ if ((chkop[ch->op] & ch->type) == 0)
+ fprintf(fh, "#define NEED_%s\n", ch->name);
+ }
+
+ fprintf(fc, "#include \"pass2.h\"\n");
+ /* create fast-lookup tables */
+ mktables();
+
+ /* create efficient bitset sizes */
+ if (sizeof(long) == 8) { /* 64-bit arch */
+ bitary = "long";
+ bitsz = 64;
+ } else {
+ bitary = "int";
+ bitsz = sizeof(int) == 4 ? 32 : 16;
+ }
+ fprintf(fh, "#define NUMBITS %d\n", bitsz);
+ fprintf(fh, "#define BITSET(arr, bit) "
+ "(arr[bit/NUMBITS] |= (1 << (bit & (NUMBITS-1))))\n");
+ fprintf(fh, "#define BITCLEAR(arr, bit) "
+ "(arr[bit/NUMBITS] &= ~(1 << (bit & (NUMBITS-1))))\n");
+ fprintf(fh, "#define TESTBIT(arr, bit) "
+ "(arr[bit/NUMBITS] & (1 << (bit & (NUMBITS-1))))\n");
+ fprintf(fh, "typedef %s bittype;\n", bitary);
+
+ /* register class definitions, used by graph-coloring */
+ /* TODO */
+
+ /* Sanity-check the table */
+ rval = 0;
+ for (q = table; q->op != FREE; q++) {
+ if (q->op == ASSIGN) {
+#define F(x) (q->visit & x && q->rewrite & (RLEFT|RRIGHT) && \
+ q->lshape & ~x && q->rshape & ~x)
+ if (F(INAREG) || F(INBREG) || F(INCREG) || F(INDREG)) {
+ compl(q, "may match without result register");
+ rval++;
+ }
+#undef F
+ if ((q->visit & INREGS) && q->rewrite != RDEST) {
+ compl(q, "ASSIGN reclaim must be RDEST");
+ rval++;
+ }
+ }
+ if (q->rewrite & (RESC1|RESC2|RESC1) && q->visit & FOREFF)
+ compl(q, "FOREFF may cause reclaim of wrong class");
+ }
+
+ /* print out list of scratched and permanent registers */
+ fprintf(fh, "extern int tempregs[], permregs[];\n");
+ fprintf(fc, "int tempregs[] = { ");
+ for (i = j = 0; i < MAXREGS; i++)
+ if (rstatus[i] & TEMPREG)
+ fprintf(fc, "%d, ", i), j++;
+ fprintf(fc, "-1 };\n");
+ fprintf(fh, "#define NTEMPREG %d\n", j+1);
+ fprintf(fh, "#define FREGS %d\n", j); /* XXX - to die */
+ fprintf(fc, "int permregs[] = { ");
+ for (i = j = 0; i < MAXREGS; i++)
+ if (rstatus[i] & PERMREG)
+ fprintf(fc, "%d, ", i), j++;
+ fprintf(fc, "-1 };\n");
+ fprintf(fh, "#define NPERMREG %d\n", j+1);
+
+ /*
+ * The register allocator uses bitmasks of registers for each class.
+ */
+ areg = breg = creg = dreg = 0;
+ for (i = 0; i < MAXREGS; i++) {
+ regclassmap[0][i] = regclassmap[1][i] = regclassmap[2][i] =
+ regclassmap[3][i] = -1;
+ if (rstatus[i] & SAREG) regclassmap[0][i] = areg++;
+ if (rstatus[i] & SBREG) regclassmap[1][i] = breg++;
+ if (rstatus[i] & SCREG) regclassmap[2][i] = creg++;
+ if (rstatus[i] & SDREG) regclassmap[3][i] = dreg++;
+ }
+ fprintf(fh, "#define AREGCNT %d\n", areg);
+ fprintf(fh, "#define BREGCNT %d\n", breg);
+ fprintf(fh, "#define CREGCNT %d\n", creg);
+ fprintf(fh, "#define DREGCNT %d\n", dreg);
+ if (areg > bitsz)
+ printf("%d regs in class A (max %d)\n", areg, bitsz), rval++;
+ if (breg > bitsz)
+ printf("%d regs in class B (max %d)\n", breg, bitsz), rval++;
+ if (creg > bitsz)
+ printf("%d regs in class C (max %d)\n", creg, bitsz), rval++;
+ if (dreg > bitsz)
+ printf("%d regs in class D (max %d)\n", dreg, bitsz), rval++;
+
+ fprintf(fc, "static int amap[MAXREGS][NUMCLASS] = {\n");
+ for (i = 0; i < MAXREGS; i++) {
+ int ba, bb, bc, bd, r;
+ ba = bb = bc = bd = 0;
+ if (rstatus[i] & SAREG) ba = (1 << regclassmap[0][i]);
+ if (rstatus[i] & SBREG) bb = (1 << regclassmap[1][i]);
+ if (rstatus[i] & SCREG) bc = (1 << regclassmap[2][i]);
+ if (rstatus[i] & SDREG) bd = (1 << regclassmap[3][i]);
+ for (j = 0; roverlay[i][j] >= 0; j++) {
+ r = roverlay[i][j];
+ if (rstatus[r] & SAREG)
+ ba |= (1 << regclassmap[0][r]);
+ if (rstatus[r] & SBREG)
+ bb |= (1 << regclassmap[1][r]);
+ if (rstatus[r] & SCREG)
+ bc |= (1 << regclassmap[2][r]);
+ if (rstatus[r] & SDREG)
+ bd |= (1 << regclassmap[3][r]);
+ }
+ fprintf(fc, "\t{ 0x%x,0x%x,0x%x,0x%x },\n", ba, bb, bc, bd);
+ }
+ fprintf(fc, "};\n");
+
+ fprintf(fh, "int aliasmap(int class, int regnum);\n");
+ fprintf(fc, "int\naliasmap(int class, int regnum)\n{\n");
+ fprintf(fc, " return amap[regnum][class-1];\n}\n");
+
+ /* routines to convert back from color to regnum */
+ mx = areg;
+ if (breg > mx) mx = breg;
+ if (creg > mx) mx = creg;
+ if (dreg > mx) mx = dreg;
+ fprintf(fc, "static int rmap[NUMCLASS][%d] = {\n", mx);
+ for (j = 0; j < NUMCLASS; j++) {
+ int cl = (1 << (j+1));
+ fprintf(fc, "\t{ ");
+ for (i = 0; i < MAXREGS; i++)
+ if (rstatus[i] & cl) fprintf(fc, "%d, ", i);
+ fprintf(fc, "},\n");
+ }
+ fprintf(fc, "};\n\n");
+
+ fprintf(fh, "int color2reg(int color, int class);\n");
+ fprintf(fc, "int\ncolor2reg(int color, int class)\n{\n");
+ fprintf(fc, " return rmap[class-1][color];\n}\n");
+
+ /* used by register allocator */
+ fprintf(fc, "int regK[] = { 0, %d, %d, %d, %d };\n",
+ areg, breg, creg, dreg);
+ fprintf(fc, "int\nclassmask(int class)\n{\n");
+ fprintf(fc, "\tif(class == CLASSA) return 0x%x;\n", (1 << areg)-1);
+ fprintf(fc, "\tif(class == CLASSB) return 0x%x;\n", (1 << breg)-1);
+ fprintf(fc, "\tif(class == CLASSC) return 0x%x;\n", (1 << creg)-1);
+ fprintf(fc, "\treturn 0x%x;\n}\n", (1 << dreg)-1);
+
+ fprintf(fh, "int interferes(int reg1, int reg2);\n");
+ nelem = (MAXREGS+bitsz-1)/bitsz;
+ fprintf(fc, "static bittype ovlarr[MAXREGS][%d] = {\n", nelem);
+ for (i = 0; i < MAXREGS; i++) {
+ int el[10];
+ memset(el, 0, sizeof(el));
+ el[i/bitsz] = 1 << (i % bitsz);
+ for (j = 0; roverlay[i][j] >= 0; j++) {
+ int k = roverlay[i][j];
+ el[k/bitsz] |= (1 << (k % bitsz));
+ }
+ fprintf(fc, "{ ");
+ for (j = 0; j < MAXREGS; j += bitsz)
+ fprintf(fc, "0x%x, ", el[j/bitsz]);
+ fprintf(fc, " },\n");
+ }
+ fprintf(fc, "};\n");
+
+ fprintf(fc, "int\ninterferes(int reg1, int reg2)\n{\n");
+ fprintf(fc, "return TESTBIT(ovlarr[reg1], reg2);\n}\n");
+ fclose(fc);
+ fclose(fh);
+ return rval;
+}
+
+#define P(x) fprintf x
+
+void
+mktables()
+{
+ struct optab *op;
+ int mxalen = 0, curalen;
+ int i;
+
+// P((fc, "#include \"pass2.h\"\n\n"));
+ for (i = 0; i <= MAXOP; i++) {
+ curalen = 0;
+ P((fc, "static int op%d[] = { ", i));
+ if (dope[i] != 0)
+ for (op = table; op->op != FREE; op++) {
+ if (op->op < OPSIMP) {
+ if (op->op == i) {
+ P((fc, "%td, ", op - table));
+ curalen++;
+ }
+ } else {
+ int opmtemp;
+ if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) {
+ if (i==NAME || i==ICON || i==TEMP ||
+ i==OREG || i == REG) {
+ P((fc, "%td, ", op - table));
+ curalen++;
+ }
+ } else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){
+ P((fc, "%td, ", op - table));
+ curalen++;
+ }
+ }
+ }
+ if (curalen > mxalen)
+ mxalen = curalen;
+ P((fc, "-1 };\n"));
+ }
+ P((fc, "\n"));
+
+ P((fc, "int *qtable[] = { \n"));
+ for (i = 0; i <= MAXOP; i++) {
+ P((fc, " op%d,\n", i));
+ }
+ P((fc, "};\n"));
+ P((fh, "#define MAXOPLEN %d\n", mxalen+1));
+}
diff --git a/usr.bin/pcc/mip/node.h b/usr.bin/pcc/mip/node.h
new file mode 100644
index 00000000000..3d42df7500c
--- /dev/null
+++ b/usr.bin/pcc/mip/node.h
@@ -0,0 +1,194 @@
+/* $Id: node.h,v 1.1 2007/09/15 18:12:36 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * The node structure is the basic element in the compiler.
+ * Depending on the operator, it may be one of several types.
+ *
+ * This is rewritten to be a struct instead of a union as it
+ * was in the old compiler.
+ */
+typedef unsigned int TWORD;
+#define NIL (NODE *)0
+
+struct symtab;
+struct suedef;
+struct regw;
+
+typedef struct node {
+ struct node *next;
+ int n_op;
+ union {
+ int _reg;
+ struct regw *_regw;
+ } n_3;
+#define n_reg n_3._reg
+#define n_regw n_3._regw
+ TWORD n_type;
+ TWORD n_qual;
+ int n_su;
+ union {
+ char * _name;
+ int _stsize;
+ union dimfun *_df;
+ } n_5;
+ union {
+ int _label;
+ int _stalign;
+ struct suedef *_sue;
+ } n_6;
+ union {
+ struct {
+ union {
+ struct node *_left;
+ CONSZ _lval;
+#ifdef SPECIAL_INTEGERS
+ SPECLVAL _slval;
+#endif
+ } n_l;
+ union {
+ struct node *_right;
+ int _rval;
+ struct symtab *_sp;
+ } n_r;
+ } n_u;
+ long double _dcon;
+ } n_f;
+} NODE;
+
+#define n_name n_5._name
+#define n_stsize n_5._stsize
+#define n_df n_5._df
+
+#define n_label n_6._label
+#define n_stalign n_6._stalign
+#define n_sue n_6._sue
+
+#define n_left n_f.n_u.n_l._left
+#define n_lval n_f.n_u.n_l._lval
+#define n_slval n_f.n_u.n_l._slval
+#define n_right n_f.n_u.n_r._right
+#define n_rval n_f.n_u.n_r._rval
+#define n_sp n_f.n_u.n_r._sp
+#define n_dcon n_f._dcon
+
+/*
+ * Node types.
+ *
+ * MAXOP is the highest number used by the backend.
+ */
+
+#define FREE 1
+/*
+ * Value nodes.
+ */
+#define NAME 2
+#define ICON 4
+#define FCON 5
+#define REG 6
+#define OREG 7
+#define TEMP 8
+#define MOVE 9 /* Special reg-reg move node */
+
+/*
+ * Arithmetic nodes.
+ */
+#define PLUS 10
+#define MINUS 11
+#define DIV 12
+#define MOD 13
+#define MUL 14
+
+/*
+ * Bitwise operations.
+ */
+#define AND 15
+#define OR 16
+#define ER 17
+#define LS 18
+#define RS 19
+#define COMPL 20
+
+#define UMUL 23
+#define UMINUS 24
+
+/*
+ * Logical compare nodes.
+ */
+#define EQ 25
+#define NE 26
+#define LE 27
+#define LT 28
+#define GE 29
+#define GT 30
+#define ULE 31
+#define ULT 32
+#define UGE 33
+#define UGT 34
+
+/*
+ * Branch nodes.
+ */
+#define CBRANCH 35
+
+/*
+ * Convert types.
+ */
+#define FLD 36
+#define SCONV 37
+#define PCONV 38
+#define PMCONV 39
+#define PVCONV 40
+
+/*
+ * Function calls.
+ */
+#define CALL 41
+#define UCALL 42
+#define FORTCALL 43
+#define UFORTCALL 44
+#define STCALL 45
+#define USTCALL 46
+
+/*
+ * Other used nodes.
+ */
+#define CCODES 47
+#define CM 48
+#define ASSIGN 49
+#define STASG 50
+#define STARG 51
+#define FORCE 52
+/* #define INIT 53 */
+#define GOTO 54
+#define RETURN 55
+#define STREF 56
+#define FUNARG 57
+#define ADDROF 58
+
+#define MAXOP 58
diff --git a/usr.bin/pcc/mip/optim2.c b/usr.bin/pcc/mip/optim2.c
new file mode 100644
index 00000000000..fcf367eb412
--- /dev/null
+++ b/usr.bin/pcc/mip/optim2.c
@@ -0,0 +1,882 @@
+/* $Id: optim2.c,v 1.1 2007/09/15 18:12:36 otto Exp $ */
+/*
+ * Copyright (c) 2004 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>
+#include <stdlib.h>
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define BDEBUG(x) if (b2debug) printf x
+
+static int dfsnum;
+
+void saveip(struct interpass *ip);
+void deljumps(struct interpass *);
+void optdump(struct interpass *ip);
+void printip(struct interpass *pole);
+
+static struct varinfo defsites;
+struct interpass *storesave;
+static struct interpass_prolog *ipp, *epp; /* prolog/epilog */
+
+void bblocks_build(struct interpass *, struct labelinfo *, struct bblockinfo *);
+void cfg_build(struct labelinfo *labinfo);
+void cfg_dfs(struct basicblock *bb, unsigned int parent,
+ struct bblockinfo *bbinfo);
+void dominators(struct bblockinfo *bbinfo);
+struct basicblock *
+ancestorwithlowestsemi(struct basicblock *bblock, struct bblockinfo *bbinfo);
+void link(struct basicblock *parent, struct basicblock *child);
+void computeDF(struct basicblock *bblock, struct bblockinfo *bbinfo);
+void findTemps(struct interpass *ip);
+void placePhiFunctions(struct bblockinfo *bbinfo);
+void remunreach(void);
+
+struct basicblock bblocks;
+int nbblocks;
+static struct interpass *cvpole;
+
+struct addrof {
+ struct addrof *next;
+ int tempnum;
+ int oregoff;
+} *otlink;
+
+static int
+getoff(int num)
+{
+ struct addrof *w;
+
+ for (w = otlink; w; w = w->next)
+ if (w->tempnum == num)
+ return w->oregoff;
+ return 0;
+}
+
+/*
+ * Use stack argument addresses instead of copying if & is used on a var.
+ */
+static int
+setargs(int tval, struct addrof *w)
+{
+ struct interpass *ip;
+ NODE *p;
+
+ ip = DLIST_NEXT(cvpole, qelem); /* PROLOG */
+ ip = DLIST_NEXT(ip, qelem); /* first DEFLAB */
+ ip = DLIST_NEXT(ip, qelem); /* first NODE */
+ for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
+ p = ip->ip_node;
+#ifdef PCC_DEBUG
+ if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
+ comperr("temparg");
+#endif
+ if (p->n_right->n_op != OREG)
+ continue; /* arg in register */
+ if (tval != p->n_left->n_lval)
+ continue; /* wrong assign */
+ w->oregoff = p->n_right->n_lval;
+ tfree(p);
+ DLIST_REMOVE(ip, qelem);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Search for ADDROF elements and, if found, record them.
+ */
+static void
+findaddrof(NODE *p)
+{
+ struct addrof *w;
+
+ if (p->n_op != ADDROF)
+ return;
+ if (getoff(p->n_left->n_lval))
+ return;
+ w = tmpalloc(sizeof(struct addrof));
+ w->tempnum = p->n_left->n_lval;
+ if (setargs(p->n_left->n_lval, w) == 0)
+ w->oregoff = BITOOR(freetemp(szty(p->n_left->n_type)));
+ w->next = otlink;
+ otlink = w;
+}
+
+
+/*
+ * Convert address-taken temps to OREGs.
+ */
+static void
+cvtaddrof(NODE *p)
+{
+ NODE *l;
+ int n;
+
+ if (p->n_op != ADDROF && p->n_op != TEMP)
+ return;
+ if (p->n_op == TEMP) {
+ n = getoff(p->n_lval);
+ if (n == 0)
+ return;
+ p->n_op = OREG;
+ p->n_lval = n;
+ p->n_rval = FPREG;
+ } else {
+ l = p->n_left;
+ l->n_type = p->n_type;
+ p->n_right = mklnode(ICON, l->n_lval, 0, l->n_type);
+ p->n_op = PLUS;
+ l->n_op = REG;
+ l->n_lval = 0;
+ l->n_rval = FPREG;
+
+ }
+}
+
+void
+optimize(struct interpass *ipole)
+{
+ struct interpass *ip;
+ struct labelinfo labinfo;
+ struct bblockinfo bbinfo;
+
+ ipp = (struct interpass_prolog *)DLIST_NEXT(ipole, qelem);
+ epp = (struct interpass_prolog *)DLIST_PREV(ipole, qelem);
+
+ if (b2debug) {
+ printf("initial links\n");
+ printip(ipole);
+ }
+
+ /*
+ * Convert ADDROF TEMP to OREGs.
+ */
+ if (xtemps) {
+ otlink = NULL;
+ cvpole = ipole;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ walkf(ip->ip_node, findaddrof);
+ }
+ if (otlink) {
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ walkf(ip->ip_node, cvtaddrof);
+ }
+ }
+ }
+
+ if (xdeljumps)
+ deljumps(ipole); /* Delete redundant jumps and dead code */
+
+#ifdef PCC_DEBUG
+ if (b2debug) {
+ printf("links after deljumps\n");
+ printip(ipole);
+ }
+#endif
+ if (xssaflag || xtemps) {
+ DLIST_INIT(&bblocks, bbelem);
+ bblocks_build(ipole, &labinfo, &bbinfo);
+ BDEBUG(("Calling cfg_build\n"));
+ cfg_build(&labinfo);
+ }
+ if (xssaflag) {
+ BDEBUG(("Calling dominators\n"));
+ dominators(&bbinfo);
+ BDEBUG(("Calling computeDF\n"));
+ computeDF(DLIST_NEXT(&bblocks, bbelem), &bbinfo);
+ BDEBUG(("Calling remunreach\n"));
+ remunreach();
+#if 0
+ dfg = dfg_build(cfg);
+ ssa = ssa_build(cfg, dfg);
+#endif
+ }
+
+#ifdef PCC_DEBUG
+ if (epp->ipp_regs != 0)
+ comperr("register error");
+#endif
+
+#ifdef MYOPTIM
+ myoptim((struct interpass *)ipp);
+#endif
+}
+
+/*
+ * Delete unused labels, excess of labels, gotos to gotos.
+ * This routine can be made much more efficient.
+ */
+void
+deljumps(struct interpass *ipole)
+{
+ struct interpass *ip, *n, *ip2;
+ int gotone,low, high;
+ int *lblary, sz, o, i;
+
+ low = ipp->ip_lblnum;
+ high = epp->ip_lblnum;
+
+#ifdef notyet
+ mark = tmpmark(); /* temporary used memory */
+#endif
+
+ sz = (high-low) * sizeof(int);
+ lblary = tmpalloc(sz);
+
+again: gotone = 0;
+ memset(lblary, 0, sz);
+
+ /* refcount and coalesce all labels */
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type == IP_DEFLAB) {
+ n = DLIST_NEXT(ip, qelem);
+ while (n->type == IP_DEFLAB) {
+ if (n->type == IP_DEFLAB &&
+ lblary[n->ip_lbl-low] >= 0)
+ lblary[n->ip_lbl-low] = -ip->ip_lbl;
+ n = DLIST_NEXT(n, qelem);
+ }
+ }
+ if (ip->type != IP_NODE)
+ continue;
+ o = ip->ip_node->n_op;
+ if (o == GOTO)
+ i = ip->ip_node->n_left->n_lval;
+ else if (o == CBRANCH)
+ i = ip->ip_node->n_right->n_lval;
+ else
+ continue;
+ lblary[i-low] |= 1;
+ }
+
+ /* delete coalesced/unused labels and rename gotos */
+ DLIST_FOREACH(ip, ipole, qelem) {
+ n = DLIST_NEXT(ip, qelem);
+ if (n->type == IP_DEFLAB) {
+ if (lblary[n->ip_lbl-low] <= 0) {
+ DLIST_REMOVE(n, qelem);
+ gotone = 1;
+ }
+ continue;
+ }
+ if (n->type != IP_NODE)
+ continue;
+ o = n->ip_node->n_op;
+ if (o == GOTO)
+ i = n->ip_node->n_left->n_lval;
+ else if (o == CBRANCH)
+ i = n->ip_node->n_right->n_lval;
+ else
+ continue;
+ if (lblary[i-low] < 0) {
+ if (o == GOTO)
+ n->ip_node->n_left->n_lval = -lblary[i-low];
+ else
+ n->ip_node->n_right->n_lval = -lblary[i-low];
+ }
+ }
+
+ /* Delete gotos to the next statement */
+ DLIST_FOREACH(ip, ipole, qelem) {
+ n = DLIST_NEXT(ip, qelem);
+ if (n->type != IP_NODE)
+ continue;
+ o = n->ip_node->n_op;
+ if (o == GOTO)
+ i = n->ip_node->n_left->n_lval;
+ else if (o == CBRANCH)
+ i = n->ip_node->n_right->n_lval;
+ else
+ continue;
+
+ ip2 = n;
+ ip2 = DLIST_NEXT(ip2, qelem);
+
+ if (ip2->type != IP_DEFLAB)
+ continue;
+ if (ip2->ip_lbl == i) {
+ tfree(n->ip_node);
+ DLIST_REMOVE(n, qelem);
+ gotone = 1;
+ }
+ }
+
+ if (gotone)
+ goto again;
+
+#ifdef notyet
+ tmpfree(mark);
+#endif
+}
+
+void
+optdump(struct interpass *ip)
+{
+ static char *nm[] = { "node", "prolog", "newblk", "epilog", "locctr",
+ "deflab", "defnam", "asm" };
+ printf("type %s\n", nm[ip->type-1]);
+ switch (ip->type) {
+ case IP_NODE:
+ fwalk(ip->ip_node, e2print, 0);
+ break;
+ case IP_DEFLAB:
+ printf("label " LABFMT "\n", ip->ip_lbl);
+ break;
+ case IP_ASM:
+ printf(": %s\n", ip->ip_asm);
+ break;
+ }
+}
+
+/*
+ * Build the basic blocks, algorithm 9.1, pp 529 in Compilers.
+ *
+ * Also fills the labelinfo struct with information about which bblocks
+ * that contain which label.
+ */
+
+void
+bblocks_build(struct interpass *ipole, struct labelinfo *labinfo,
+ struct bblockinfo *bbinfo)
+{
+ struct interpass *ip;
+ struct basicblock *bb = NULL;
+ int low, high;
+ int count = 0;
+ int i;
+
+ BDEBUG(("bblocks_build (%p, %p)\n", labinfo, bbinfo));
+ low = ipp->ip_lblnum;
+ high = epp->ip_lblnum;
+
+ /*
+ * First statement is a leader.
+ * Any statement that is target of a jump is a leader.
+ * Any statement that immediately follows a jump is a leader.
+ */
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (bb == NULL || (ip->type == IP_EPILOG) ||
+ (ip->type == IP_DEFLAB) || (ip->type == IP_DEFNAM)) {
+ bb = tmpalloc(sizeof(struct basicblock));
+ bb->first = ip;
+ SLIST_INIT(&bb->children);
+ SLIST_INIT(&bb->parents);
+ bb->dfnum = 0;
+ bb->dfparent = 0;
+ bb->semi = 0;
+ bb->ancestor = 0;
+ bb->idom = 0;
+ bb->samedom = 0;
+ bb->bucket = NULL;
+ bb->df = NULL;
+ bb->dfchildren = NULL;
+ bb->Aorig = NULL;
+ bb->Aphi = NULL;
+ bb->bbnum = count;
+ DLIST_INSERT_BEFORE(&bblocks, bb, bbelem);
+ count++;
+ }
+ bb->last = ip;
+ if ((ip->type == IP_NODE) && (ip->ip_node->n_op == GOTO ||
+ ip->ip_node->n_op == CBRANCH))
+ bb = NULL;
+ if (ip->type == IP_PROLOG)
+ bb = NULL;
+ }
+ nbblocks = count;
+
+ if (b2debug) {
+ printf("Basic blocks in func: %d, low %d, high %d\n",
+ count, low, high);
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ printf("bb %p: first %p last %p\n", bb,
+ bb->first, bb->last);
+ }
+ }
+
+ labinfo->low = low;
+ labinfo->size = high - low + 1;
+ labinfo->arr = tmpalloc(labinfo->size * sizeof(struct basicblock *));
+ for (i = 0; i < labinfo->size; i++) {
+ labinfo->arr[i] = NULL;
+ }
+
+ bbinfo->size = count + 1;
+ bbinfo->arr = tmpalloc(bbinfo->size * sizeof(struct basicblock *));
+ for (i = 0; i < bbinfo->size; i++) {
+ bbinfo->arr[i] = NULL;
+ }
+
+ /* Build the label table */
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ if (bb->first->type == IP_DEFLAB)
+ labinfo->arr[bb->first->ip_lbl - low] = bb;
+ }
+
+ if (b2debug) {
+ printf("Label table:\n");
+ for (i = 0; i < labinfo->size; i++)
+ if (labinfo->arr[i])
+ printf("Label %d bblock %p\n", i+low,
+ labinfo->arr[i]);
+ }
+}
+
+/*
+ * Build the control flow graph.
+ */
+
+void
+cfg_build(struct labelinfo *labinfo)
+{
+ /* Child and parent nodes */
+ struct cfgnode *cnode;
+ struct cfgnode *pnode;
+ struct basicblock *bb;
+
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+
+ if (bb->first->type == IP_EPILOG) {
+ break;
+ }
+
+ cnode = tmpalloc(sizeof(struct cfgnode));
+ pnode = tmpalloc(sizeof(struct cfgnode));
+ pnode->bblock = bb;
+
+ if ((bb->last->type == IP_NODE) &&
+ (bb->last->ip_node->n_op == GOTO)) {
+ if (bb->last->ip_node->n_left->n_lval - labinfo->low >
+ labinfo->size) {
+ comperr("Label out of range: %d, base %d",
+ bb->last->ip_node->n_left->n_lval,
+ labinfo->low);
+ }
+ cnode->bblock = labinfo->arr[bb->last->ip_node->n_left->n_lval - labinfo->low];
+ SLIST_INSERT_LAST(&cnode->bblock->parents, pnode, cfgelem);
+ SLIST_INSERT_LAST(&bb->children, cnode, cfgelem);
+ continue;
+ }
+ if ((bb->last->type == IP_NODE) &&
+ (bb->last->ip_node->n_op == CBRANCH)) {
+ if (bb->last->ip_node->n_right->n_lval - labinfo->low >
+ labinfo->size)
+ comperr("Label out of range: %d",
+ bb->last->ip_node->n_left->n_lval);
+
+ cnode->bblock = labinfo->arr[bb->last->ip_node->n_right->n_lval - labinfo->low];
+ SLIST_INSERT_LAST(&cnode->bblock->parents, pnode, cfgelem);
+ SLIST_INSERT_LAST(&bb->children, cnode, cfgelem);
+ cnode = tmpalloc(sizeof(struct cfgnode));
+ pnode = tmpalloc(sizeof(struct cfgnode));
+ pnode->bblock = bb;
+ }
+
+ cnode->bblock = DLIST_NEXT(bb, bbelem);
+ SLIST_INSERT_LAST(&cnode->bblock->parents, pnode, cfgelem);
+ SLIST_INSERT_LAST(&bb->children, cnode, cfgelem);
+ }
+}
+
+void
+cfg_dfs(struct basicblock *bb, unsigned int parent, struct bblockinfo *bbinfo)
+{
+ struct cfgnode *cnode;
+
+ if (bb->dfnum != 0)
+ return;
+
+ bb->dfnum = ++dfsnum;
+ bb->dfparent = parent;
+ bbinfo->arr[bb->dfnum] = bb;
+ SLIST_FOREACH(cnode, &bb->children, cfgelem) {
+ cfg_dfs(cnode->bblock, bb->dfnum, bbinfo);
+ }
+ /* Don't bring in unreachable nodes in the future */
+ bbinfo->size = dfsnum + 1;
+}
+
+static bittype *
+setalloc(int nelem)
+{
+ bittype *b;
+ int sz = (nelem+NUMBITS-1)/NUMBITS;
+
+ b = tmpalloc(sz * sizeof(bittype));
+ memset(b, 0, sz * sizeof(bittype));
+ return b;
+}
+
+/*
+ * Algorithm 19.9, pp 414 from Appel.
+ */
+
+void
+dominators(struct bblockinfo *bbinfo)
+{
+ struct cfgnode *cnode;
+ struct basicblock *bb, *y, *v;
+ struct basicblock *s, *sprime, *p;
+ int h, i;
+
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ bb->bucket = setalloc(bbinfo->size);
+ bb->df = setalloc(bbinfo->size);
+ bb->dfchildren = setalloc(bbinfo->size);
+ }
+
+ dfsnum = 0;
+ cfg_dfs(DLIST_NEXT(&bblocks, bbelem), 0, bbinfo);
+
+ if (b2debug) {
+ struct basicblock *bbb;
+ struct cfgnode *ccnode;
+
+ DLIST_FOREACH(bbb, &bblocks, bbelem) {
+ printf("Basic block %d, parents: ", bbb->dfnum);
+ SLIST_FOREACH(ccnode, &bbb->parents, cfgelem) {
+ printf("%d, ", ccnode->bblock->dfnum);
+ }
+ printf("\nChildren: ");
+ SLIST_FOREACH(ccnode, &bbb->children, cfgelem) {
+ printf("%d, ", ccnode->bblock->dfnum);
+ }
+ printf("\n");
+ }
+ }
+
+ for(h = bbinfo->size - 1; h > 1; h--) {
+ bb = bbinfo->arr[h];
+ p = s = bbinfo->arr[bb->dfparent];
+ SLIST_FOREACH(cnode, &bb->parents, cfgelem) {
+ if (cnode->bblock->dfnum <= bb->dfnum)
+ sprime = cnode->bblock;
+ else
+ sprime = bbinfo->arr[ancestorwithlowestsemi
+ (cnode->bblock, bbinfo)->semi];
+ if (sprime->dfnum < s->dfnum)
+ s = sprime;
+ }
+ bb->semi = s->dfnum;
+ BITSET(s->bucket, bb->dfnum);
+ link(p, bb);
+ for (i = 1; i < bbinfo->size; i++) {
+ if(TESTBIT(p->bucket, i)) {
+ v = bbinfo->arr[i];
+ y = ancestorwithlowestsemi(v, bbinfo);
+ if (y->semi == v->semi)
+ v->idom = p->dfnum;
+ else
+ v->samedom = y->dfnum;
+ }
+ }
+ memset(p->bucket, 0, (bbinfo->size + 7)/8);
+ }
+
+ if (b2debug) {
+ printf("Num\tSemi\tAncest\tidom\n");
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ printf("%d\t%d\t%d\t%d\n", bb->dfnum, bb->semi,
+ bb->ancestor, bb->idom);
+ }
+ }
+
+ for(h = 2; h < bbinfo->size; h++) {
+ bb = bbinfo->arr[h];
+ if (bb->samedom != 0) {
+ bb->idom = bbinfo->arr[bb->samedom]->idom;
+ }
+ }
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ if (bb->idom != 0 && bb->idom != bb->dfnum) {
+ BDEBUG(("Setting child %d of %d\n",
+ bb->dfnum, bbinfo->arr[bb->idom]->dfnum));
+ BITSET(bbinfo->arr[bb->idom]->dfchildren, bb->dfnum);
+ }
+ }
+}
+
+
+struct basicblock *
+ancestorwithlowestsemi(struct basicblock *bblock, struct bblockinfo *bbinfo)
+{
+ struct basicblock *u = bblock;
+ struct basicblock *v = bblock;
+
+ while (v->ancestor != 0) {
+ if (bbinfo->arr[v->semi]->dfnum <
+ bbinfo->arr[u->semi]->dfnum)
+ u = v;
+ v = bbinfo->arr[v->ancestor];
+ }
+ return u;
+}
+
+void
+link(struct basicblock *parent, struct basicblock *child)
+{
+ child->ancestor = parent->dfnum;
+}
+
+void
+computeDF(struct basicblock *bblock, struct bblockinfo *bbinfo)
+{
+ struct cfgnode *cnode;
+ int h, i;
+
+ SLIST_FOREACH(cnode, &bblock->children, cfgelem) {
+ if (cnode->bblock->idom != bblock->dfnum)
+ BITSET(bblock->df, cnode->bblock->dfnum);
+ }
+ for (h = 1; h < bbinfo->size; h++) {
+ if (!TESTBIT(bblock->dfchildren, h))
+ continue;
+ computeDF(bbinfo->arr[h], bbinfo);
+ for (i = 1; i < bbinfo->size; i++) {
+ if (TESTBIT(bbinfo->arr[h]->df, i) &&
+ (bbinfo->arr[h] == bblock ||
+ (bblock->idom != bbinfo->arr[h]->dfnum)))
+ BITSET(bblock->df, i);
+ }
+ }
+}
+
+static struct basicblock *currbb;
+static struct interpass *currip;
+
+/* Helper function for findTemps, Find assignment nodes. */
+static void
+searchasg(NODE *p)
+{
+ struct pvarinfo *pv;
+
+ if (p->n_op != ASSIGN)
+ return;
+
+ if (p->n_left->n_op != TEMP)
+ return;
+
+ pv = tmpcalloc(sizeof(struct pvarinfo));
+ pv->next = defsites.arr[p->n_left->n_lval];
+ pv->bb = currbb;
+ pv->top = currip->ip_node;
+ pv->n = p->n_left;
+ BITSET(currbb->Aorig, p->n_left->n_lval);
+
+ defsites.arr[p->n_left->n_lval] = pv;
+}
+
+/* Walk the interpass looking for assignment nodes. */
+void findTemps(struct interpass *ip)
+{
+ if (ip->type != IP_NODE)
+ return;
+
+ currip = ip;
+
+ walkf(ip->ip_node, searchasg);
+}
+
+/*
+ * Algorithm 19.6 from Appel.
+ */
+
+void
+placePhiFunctions(struct bblockinfo *bbinfo)
+{
+ struct basicblock *bb;
+ struct interpass *ip;
+ int maxtmp, i, j, k, l;
+ struct pvarinfo *n;
+ struct cfgnode *cnode;
+ TWORD ntype;
+ NODE *p;
+ struct pvarinfo *pv;
+
+ bb = DLIST_NEXT(&bblocks, bbelem);
+ defsites.low = ((struct interpass_prolog *)bb->first)->ip_tmpnum;
+ bb = DLIST_PREV(&bblocks, bbelem);
+ maxtmp = ((struct interpass_prolog *)bb->first)->ip_tmpnum;
+ defsites.size = maxtmp - defsites.low + 1;
+ defsites.arr = tmpcalloc(defsites.size*sizeof(struct pvarinfo *));
+
+ /* Find all defsites */
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ currbb = bb;
+ ip = bb->first;
+ bb->Aorig = setalloc(defsites.size);
+ bb->Aphi = setalloc(defsites.size);
+
+
+ while (ip != bb->last) {
+ findTemps(ip);
+ ip = DLIST_NEXT(ip, qelem);
+ }
+ /* Make sure we get the last statement in the bblock */
+ findTemps(ip);
+ }
+ /* For each variable */
+ for (i = defsites.low; i < defsites.size; i++) {
+ /* While W not empty */
+ while (defsites.arr[i] != NULL) {
+ /* Remove some node n from W */
+ n = defsites.arr[i];
+ defsites.arr[i] = n->next;
+ /* For each y in n->bb->df */
+ for (j = 0; j < bbinfo->size; j++) {
+ if (!TESTBIT(n->bb->df, j))
+ continue;
+
+ if (TESTBIT(bbinfo->arr[j]->Aphi, i))
+ continue;
+
+ ntype = n->n->n_type;
+ k = 0;
+ /* Amount of predecessors for y */
+ SLIST_FOREACH(cnode, &n->bb->parents, cfgelem)
+ k++;
+ /* Construct phi(...) */
+ p = mklnode(TEMP, i, 0, ntype);
+ for (l = 0; l < k-1; l++)
+ p = mkbinode(PHI, p,
+ mklnode(TEMP, i, 0, ntype), ntype);
+ ip = ipnode(mkbinode(ASSIGN,
+ mklnode(TEMP, i, 0, ntype), p, ntype));
+ /* Insert phi at top of basic block */
+ DLIST_INSERT_BEFORE(((struct interpass*)&n->bb->first), ip, qelem);
+ n->bb->first = ip;
+ BITSET(bbinfo->arr[j]->Aphi, i);
+ if (!TESTBIT(bbinfo->arr[j]->Aorig, i)) {
+ pv = tmpalloc(sizeof(struct pvarinfo));
+ // XXXpj Ej fullständig information.
+ pv->bb = bbinfo->arr[j];
+ pv->next = defsites.arr[i]->next;
+ defsites.arr[i] = pv;
+ }
+
+
+ }
+ }
+ }
+}
+
+/*
+ * Remove unreachable nodes in the CFG.
+ */
+
+void
+remunreach(void)
+{
+ struct basicblock *bb, *nbb;
+ struct interpass *next, *ctree;
+
+ bb = DLIST_NEXT(&bblocks, bbelem);
+ while (bb != &bblocks) {
+ nbb = DLIST_NEXT(bb, bbelem);
+
+ /* Code with dfnum 0 is unreachable */
+ if (bb->dfnum != 0) {
+ bb = nbb;
+ continue;
+ }
+
+ /* Need the epilogue node for other parts of the
+ compiler, set its label to 0 and backend will
+ handle it. */
+ if (bb->first->type == IP_EPILOG) {
+ bb->first->ip_lbl = 0;
+ bb = nbb;
+ continue;
+ }
+
+ next = bb->first;
+ do {
+ ctree = next;
+ next = DLIST_NEXT(ctree, qelem);
+
+ if (ctree->type == IP_NODE)
+ tfree(ctree->ip_node);
+ DLIST_REMOVE(ctree, qelem);
+ } while (ctree != bb->last);
+
+ DLIST_REMOVE(bb, bbelem);
+ bb = nbb;
+ }
+}
+
+void
+printip(struct interpass *pole)
+{
+ static char *foo[] = {
+ 0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" };
+ struct interpass *ip;
+ struct interpass_prolog *ipp, *epp;
+
+ DLIST_FOREACH(ip, pole, qelem) {
+ if (ip->type > MAXIP)
+ printf("IP(%d) (%p): ", ip->type, ip);
+ else
+ printf("%s (%p): ", foo[ip->type], ip);
+ switch (ip->type) {
+ case IP_NODE: printf("\n");
+ fwalk(ip->ip_node, e2print, 0); break;
+ case IP_PROLOG:
+ ipp = (struct interpass_prolog *)ip;
+ printf("%s %s regs %x autos %d mintemp %d minlbl %d\n",
+ ipp->ipp_name, ipp->ipp_vis ? "(local)" : "",
+ ipp->ipp_regs, ipp->ipp_autos, ipp->ip_tmpnum,
+ ipp->ip_lblnum);
+ break;
+ case IP_EPILOG:
+ epp = (struct interpass_prolog *)ip;
+ printf("%s %s regs %x autos %d mintemp %d minlbl %d\n",
+ epp->ipp_name, epp->ipp_vis ? "(local)" : "",
+ epp->ipp_regs, epp->ipp_autos, epp->ip_tmpnum,
+ epp->ip_lblnum);
+ break;
+ case IP_DEFLAB: printf(LABFMT "\n", ip->ip_lbl); break;
+ case IP_DEFNAM: printf("\n"); break;
+ case IP_ASM: printf("%s\n", ip->ip_asm); break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/usr.bin/pcc/mip/pass2.h b/usr.bin/pcc/mip/pass2.h
new file mode 100644
index 00000000000..35ccb7f4220
--- /dev/null
+++ b/usr.bin/pcc/mip/pass2.h
@@ -0,0 +1,418 @@
+/* $Id: pass2.h,v 1.1 2007/09/15 18:12:36 otto Exp $ */
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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 <sys/types.h>
+
+#include "manifest.h"
+#include "protos.h"
+#ifndef MKEXT
+#include "external.h"
+#else
+typedef int bittype; /* XXX - for basicblock */
+#endif
+
+/* cookies, used as arguments to codgen */
+#define FOREFF 01 /* compute for effects only */
+#define INAREG 02 /* compute into a register */
+#define INBREG 04 /* compute into a register */
+#define INCREG 010 /* compute into a register */
+#define INDREG 020 /* compute into a register */
+#define INREGS (INAREG|INBREG|INCREG|INDREG)
+#define FORCC 040 /* compute for condition codes only */
+#define INTEMP 010000 /* compute into a temporary location */
+#define FORREW 040000 /* search the table for a rewrite rule */
+
+/*
+ * OP descriptors,
+ * the ASG operator may be used on some of these
+ */
+#define OPSIMP 010000 /* +, -, &, |, ^ */
+#define OPCOMM 010002 /* +, &, |, ^ */
+#define OPMUL 010004 /* *, / */
+#define OPDIV 010006 /* /, % */
+#define OPUNARY 010010 /* unary ops */
+#define OPLEAF 010012 /* leaves */
+#define OPANY 010014 /* any op... */
+#define OPLOG 010016 /* logical ops */
+#define OPFLOAT 010020 /* +, -, *, or / (for floats) */
+#define OPSHFT 010022 /* <<, >> */
+#define OPLTYPE 010024 /* leaf type nodes (e.g, NAME, ICON, etc.) */
+
+/* shapes */
+#define SANY 01 /* same as FOREFF */
+#define SAREG 02 /* same as INAREG */
+#define SBREG 04 /* same as INBREG */
+#define SCREG 010 /* same as INCREG */
+#define SDREG 020 /* same as INDREG */
+#define SCC 040 /* same as FORCC */
+#define SNAME 0100
+#define SCON 0200
+#define SFLD 0400
+#define SOREG 01000
+#define STARNM 02000
+#define STARREG 04000
+#define SWADD 040000
+#define SPECIAL 0100000
+#define SZERO SPECIAL
+#define SONE (SPECIAL|1)
+#define SMONE (SPECIAL|2)
+#define SCCON (SPECIAL|3) /* -256 <= constant < 256 */
+#define SSCON (SPECIAL|4) /* -32768 <= constant < 32768 */
+#define SSOREG (SPECIAL|5) /* non-indexed OREG */
+#define MAXSPECIAL (SPECIAL|5)
+
+/* These are used in rstatus[] in conjunction with SxREG */
+#define TEMPREG 0100
+#define PERMREG 0200
+
+/* tshape() return values */
+#define SRNOPE 0 /* Cannot match any shape */
+#define SRDIR 1 /* Direct match */
+#define SROREG 2 /* Can convert into OREG */
+#define SRREG 3 /* Must put into REG */
+
+/* find*() return values */
+#define FRETRY -2
+#define FFAIL -1
+
+/* INTEMP is carefully not conflicting with shapes */
+
+/* types */
+#define TCHAR 01 /* char */
+#define TSHORT 02 /* short */
+#define TINT 04 /* int */
+#define TLONG 010 /* long */
+#define TFLOAT 020 /* float */
+#define TDOUBLE 040 /* double */
+#define TPOINT 0100 /* pointer to something */
+#define TUCHAR 0200 /* unsigned char */
+#define TUSHORT 0400 /* unsigned short */
+#define TUNSIGNED 01000 /* unsigned int */
+#define TULONG 02000 /* unsigned long */
+#define TPTRTO 04000 /* pointer to one of the above */
+#define TANY 010000 /* matches anything within reason */
+#define TSTRUCT 020000 /* structure or union */
+#define TLONGLONG 040000 /* long long */
+#define TULONGLONG 0100000 /* unsigned long long */
+#define TLDOUBLE 0200000 /* long double; exceeds 16 bit */
+#define TFTN 0400000 /* function pointer; exceeds 16 bit */
+
+/* reclamation cookies */
+#define RNULL 0 /* clobber result */
+#define RLEFT 01
+#define RRIGHT 02
+#define RESC1 04
+#define RESC2 010
+#define RESC3 020
+#define RDEST 040
+#define RESCC 04000
+#define RNOP 010000 /* DANGER: can cause loops.. */
+
+/* needs */
+#define NAREG 0000001
+#define NACOUNT 0000003
+#define NAMASK 0000017
+#define NASL 0000004 /* may share left register */
+#define NASR 0000010 /* may share right register */
+#define NBREG 0000020
+#define NBCOUNT 0000060
+#define NBMASK 0000360
+#define NBSL 0000100
+#define NBSR 0000200
+#define NTEMP 0000400
+#define NTMASK 0001400
+#define NSPECIAL 0040000 /* need special register treatment */
+#define REWRITE 0100000
+#define NCSL 0x10000 /* Above 16 bit */
+#define NCSR 0x20000 /* Above 16 bit */
+#define NCREG 0x40000 /* Above 16 bit */
+#define NCCOUNT 0xc0000
+#define NDSL 0x100000 /* Above 16 bit */
+#define NDSR 0x200000 /* Above 16 bit */
+#define NDREG 0x400000 /* Above 16 bit */
+#define NDCOUNT 0xc00000
+
+/* special treatment */
+#define NLEFT (0001) /* left leg register (moveadd) */
+#define NOLEFT (0002) /* avoid regs for left (addedge) */
+#define NRIGHT (0004) /* right leg register */
+#define NORIGHT (0010) /* avoid reg for right */
+#define NEVER (0020) /* registers trashed (addalledges) */
+#define NRES (0040) /* result register (moveadd) */
+#define NMOVTO (0100) /* move between classes */
+
+
+#define MUSTDO 010000 /* force register requirements */
+#define NOPREF 020000 /* no preference for register assignment */
+
+#define isreg(p) (p->n_op == REG || p->n_op == TEMP)
+
+#define TBUSY 01000
+
+#define SETSTO(x,y) (stotree = (x), stocook = (y))
+extern int stocook;
+
+extern NODE *stotree;
+extern int callflag;
+
+extern int fregs;
+
+/* code tables */
+extern struct optab {
+ int op;
+ int visit;
+ int lshape;
+ int ltype;
+ int rshape;
+ int rtype;
+ int needs;
+ int rewrite;
+ char *cstring;
+} table[];
+
+/* Special needs for register allocations */
+struct rspecial {
+ int op, num;
+#if 0
+ int left; /* left leg register */
+ int noleft; /* avoid regs for left */
+ int right; /* right leg register */
+ int noright; /* avoid right leg register */
+ int *rmask; /* array of destroyed registers */
+ int res; /* Result ends up here */
+// void (*rew)(struct optab *, NODE *); /* special rewrite */
+#endif
+};
+
+extern NODE resc[];
+
+extern int p2autooff, p2maxautooff;
+
+extern NODE
+ *talloc(void),
+ *eread(void),
+ *tcopy(NODE *),
+ *mklnode(int, CONSZ, int, TWORD),
+ *mkbinode(int, NODE *, NODE *, TWORD),
+ *mkunode(int, NODE *, int, TWORD),
+ *getlr(NODE *p, int);
+
+void eoftn(struct interpass_prolog *);
+void prologue(struct interpass_prolog *);
+void setlocc(int locctr);
+void e2print(NODE *p, int down, int *a, int *b);
+void myoptim(struct interpass *);
+void cbgen(int op, int label);
+struct optab *nxtmatch(struct optab *);
+int chkmatch(NODE *, int, int, int);
+int match(NODE *p, int cookie);
+int nmatch(NODE *p, int what);
+#ifndef special
+int special(NODE *, int);
+#endif
+int setasg(NODE *, int);
+int setuni(NODE *, int);
+int sucomp(NODE *);
+int nsucomp(NODE *);
+int setorder(NODE *);
+int geninsn(NODE *, int cookie);
+void adrput(FILE *, NODE *);
+void comperr(char *str, ...);
+void genregs(NODE *p);
+void ngenregs(struct interpass *);
+NODE *store(NODE *);
+void gencall(NODE *, NODE *prev);
+struct interpass *ipnode(NODE *);
+void deflab(int);
+void rmove(int, int, TWORD);
+int rspecial(struct optab *, int);
+struct rspecial *nspecial(struct optab *q);
+void printip(struct interpass *pole);
+int findops(NODE *p, int);
+int findasg(NODE *p, int);
+int finduni(NODE *p, int);
+int findumul(NODE *p, int);
+int findleaf(NODE *p, int);
+int relops(NODE *p);
+void offstar(NODE *p, int shape);
+int gclass(TWORD);
+void lastcall(NODE *);
+void myreader(struct interpass *pole);
+int oregok(NODE *p, int sharp);
+void myormake(NODE *);
+
+char *prcook(int);
+
+void conput(FILE *, NODE *);
+
+extern char *rnames[];
+extern int rstatus[];
+extern int roverlap[MAXREGS][MAXREGS];
+
+extern int classmask(int), tclassmask(int);
+extern void cmapinit(void);
+extern int aliasmap(int adjclass, int regnum);
+extern int regK[];
+#define CLASSA 1
+#define CLASSB 2
+#define CLASSC 3
+#define CLASSD 4
+#define CLASSE 5
+
+/* routines to handle double indirection */
+#ifdef R2REGS
+void makeor2(NODE *p, NODE *q, int, int);
+int base(NODE *);
+int offset(NODE *p, int);
+#endif
+
+extern int lineno;
+extern int fldshf, fldsz;
+extern int lflag, x2debug, udebug, e2debug, odebug, mdebug;
+extern int rdebug, radebug, t2debug, s2debug, b2debug, c2debug;
+extern int kflag;
+#ifdef FORT
+extern int Oflag;
+#endif
+
+#ifndef callchk
+#define callchk(x) allchk()
+#endif
+
+#ifndef PUTCHAR
+#define PUTCHAR(x) putchar(x)
+#endif
+
+#define optype(o) (dope[o]&TYFLG)
+#define asgop(o) (dope[o]&ASGFLG)
+#define logop(o) (dope[o]&LOGFLG)
+#define callop(o) (dope[o]&CALLFLG)
+extern int dope[]; /* a vector containing operator information */
+extern char *opst[]; /* a vector containing names for ops */
+
+ /* macros for doing double indexing */
+#define R2PACK(x,y,z) (0200*((x)+1)+y+040000*z)
+#define R2UPK1(x) ((((x)>>7)-1)&0177)
+#define R2UPK2(x) ((x)&0177)
+#define R2UPK3(x) (x>>14)
+#define R2TEST(x) ((x)>=0200)
+
+/*
+ * Layout of findops() return value:
+ * bit 0-1 where to store left node.
+ * bit 2-3 where to store right node.
+ * bit 4 set if right leg should be evaluated first
+ * bit 5- table index
+ *
+ * LOREG means: walk down left node, after code emission call canon() to
+ * convert the tree to an OREG.
+ */
+#define LREG 001
+#define LOREG 002
+#define LTEMP 003
+#define LDIR 003
+#define LMASK 003
+#define RREG 004
+#define ROREG 010
+#define RTEMP 014
+#define RDIR 014
+#define RMASK 014
+#define DORIGHT 020
+#define SCLASS(v,x) ((v) |= ((x) << 5))
+#define TCLASS(x) (((x) >> 5) & 7)
+#define TBSH 8
+#define TBLIDX(idx) ((idx) >> TBSH)
+#define MKIDX(tbl,mod) (((tbl) << TBSH) | (mod))
+
+#ifndef BREGS
+#define BREGS 0
+#define TBREGS 0
+#endif
+#define REGBIT(x) (1 << (x))
+
+void emit(struct interpass *);
+void optimize(struct interpass *);
+
+struct basicblock {
+ DLIST_ENTRY(basicblock) bbelem;
+ SLIST_HEAD(, cfgnode) children; /* CFG - children to this node */
+ SLIST_HEAD(, cfgnode) parents; /* CFG - parents to this node */
+ int bbnum; /* this basic block number */
+ unsigned int dfnum; /* DFS-number */
+ unsigned int dfparent; /* Parent in DFS */
+ unsigned int semi;
+ unsigned int ancestor;
+ unsigned int idom;
+ unsigned int samedom;
+ bittype *bucket;
+ bittype *df;
+ bittype *dfchildren;
+ bittype *Aorig;
+ bittype *Aphi;
+ struct interpass *first; /* first element of basic block */
+ struct interpass *last; /* last element of basic block */
+};
+
+struct labelinfo {
+ struct basicblock **arr;
+ unsigned int size;
+ unsigned int low;
+};
+
+struct bblockinfo {
+ unsigned int size;
+ struct basicblock **arr;
+};
+
+struct varinfo {
+ struct pvarinfo **arr;
+ int size;
+ int low;
+};
+
+struct pvarinfo {
+ struct pvarinfo *next;
+ struct basicblock *bb;
+ NODE *top, *n;
+};
+
+struct cfgnode {
+ SLIST_ENTRY(cfgnode) cfgelem;
+ struct basicblock *bblock;
+};
+
+/*
+ * C compiler second pass extra defines.
+ */
+#define PHI (MAXOP + 1) /* Used in SSA trees */
diff --git a/usr.bin/pcc/mip/protos.h b/usr.bin/pcc/mip/protos.h
new file mode 100644
index 00000000000..a0a436fdd45
--- /dev/null
+++ b/usr.bin/pcc/mip/protos.h
@@ -0,0 +1,83 @@
+
+struct optab;
+struct symtab;
+struct sw;
+
+void cerror(char *s, ...);
+void werror(char *s, ...);
+void uerror(char *s, ...);
+void reclaim(NODE *p, int, int);
+void walkf(NODE *, void (*f)(NODE *));
+void allchk(void);
+void tfree(NODE *);
+int tshape(NODE *, int);
+void prtdcon(NODE *p);
+void tinit(void);
+void tcheck(void);
+void mkdope(void);
+int tshape(NODE *p, int shape);
+int shtemp(NODE *p);
+int flshape(NODE *p);
+int shumul(NODE *p);
+int ttype(TWORD t, int tword);
+void expand(NODE *, int, char *);
+void hopcode(int, int);
+void adrcon(CONSZ);
+void zzzcode(NODE *, int);
+void insput(NODE *);
+void upput(NODE *, int);
+void econvert(NODE *);
+int andable(NODE *);
+int conval(NODE *, int, NODE *);
+int ispow2(CONSZ);
+void defid(NODE *q, int class);
+int getlab(void);
+void ftnend(void);
+void efcode(void);
+void dclargs(void);
+void fixarg(struct symtab *);
+void cendarg(void);
+void defalign(int);
+int fldal(unsigned int);
+void vfdzero(int);
+void zecode(int);
+void putbyte(int v);
+void ecomp(NODE *p);
+void cinit(NODE *, int);
+void bccode(void);
+int upoff(int size, int alignment, int *poff);
+void fldty(struct symtab *p);
+void nidcl(NODE *p, int class);
+int noinit(void);
+void eprint(NODE *, int, int *, int *);
+int uclass(int class);
+int fixclass(int, TWORD type);
+void lineid(int, char *);
+void mycanon(NODE *);
+void delay(NODE *);
+int delay1(NODE *);
+void delay2(NODE *);
+void setregs(void);
+int autoincr(NODE *);
+int deltest(NODE *);
+void canon(NODE *);
+void order(NODE *, int);
+int tlen(NODE *p);
+int setincr(NODE *);
+int setbin(NODE *);
+void stoarg(NODE *p, int);
+void constore(NODE *);
+void markcall(NODE *);
+void oreg2(NODE *p);
+int notoff(TWORD, int, CONSZ, char *);
+void bycode(int, int);
+void pstab(char *, int);
+void psline(void);
+int notlval(NODE *);
+int icons(NODE *);
+void ecode(NODE *p);
+int yylex(void);
+void yyerror(char *s);
+void p2tree(NODE *p);
+int rewfld(NODE *p);
+int freetemp(int k);
diff --git a/usr.bin/pcc/mip/reader.c b/usr.bin/pcc/mip/reader.c
new file mode 100644
index 00000000000..01135685094
--- /dev/null
+++ b/usr.bin/pcc/mip/reader.c
@@ -0,0 +1,1098 @@
+/* $Id: reader.c,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+/*
+ * 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.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
+ */
+
+/*
+ * Everything is entered via pass2_compile(). Three functions are
+ * allowed to recurse into pass2_compile(), so be careful:
+ * - deluseless()
+ * - myreader()
+ * Especially in myreader note that trees may be rewritten twice if
+ * things are not carefully handled.
+ */
+
+# include "pass2.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* some storage declarations */
+int nrecur;
+int lflag;
+int x2debug;
+int udebug = 0;
+int thisline;
+int fregs;
+int p2autooff, p2maxautooff;
+
+NODE *nodepole;
+FILE *prfil;
+
+void saveip(struct interpass *ip);
+void deljumps(void);
+void deltemp(NODE *p);
+void mkhardops(NODE *p);
+void optdump(struct interpass *ip);
+void cvtemps(struct interpass *epil);
+NODE *store(NODE *);
+void rcount(void);
+void compile2(struct interpass *ip);
+void compile3(struct interpass *ip);
+void compile4(struct interpass *ip);
+
+static void gencode(NODE *p, int cookie);
+
+char *ltyp[] = { "", "LREG", "LOREG", "LTEMP" };
+char *rtyp[] = { "", "RREG", "ROREG", "RTEMP" };
+
+/* used when removing nodes */
+struct tmpsave {
+ struct tmpsave *next;
+ CONSZ tempaddr;
+ int tempno;
+} *tmpsave;
+
+#ifdef PCC_DEBUG
+static void
+cktree(NODE *p)
+{
+ if (p->n_op > MAXOP)
+ cerror("op %d slipped through", p->n_op);
+ if (BTYPE(p->n_type) > MAXTYPES)
+ cerror("type %x slipped through", p->n_type);
+ if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
+ cerror("not logop branch");
+ if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
+ cerror("asgop %d slipped through", p->n_op);
+}
+#endif
+
+/*
+ * Check if a node has side effects.
+ */
+static int
+isuseless(NODE *n)
+{
+ switch (n->n_op) {
+ case FUNARG:
+ case UCALL:
+ case UFORTCALL:
+ case FORCE:
+/* case INIT: */
+ case ASSIGN:
+ case CALL:
+ case FORTCALL:
+ case CBRANCH:
+ case RETURN:
+ case GOTO:
+ case STCALL:
+ case USTCALL:
+ case STASG:
+ case STARG:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+/*
+ * Delete statements with no meaning (like a+b; or 513.4;)
+ */
+static NODE *
+deluseless(NODE *p)
+{
+ struct interpass *ip;
+ NODE *l, *r;
+
+ if (optype(p->n_op) == LTYPE) {
+ nfree(p);
+ return NULL;
+ }
+ if (isuseless(p) == 0)
+ return p;
+
+ if (optype(p->n_op) == UTYPE) {
+ l = p->n_left;
+ nfree(p);
+ return deluseless(l);
+ }
+
+ /* Be sure that both leaves may be valid */
+ l = deluseless(p->n_left);
+ r = deluseless(p->n_right);
+ nfree(p);
+ if (l && r) {
+ /* Put left on queue first */
+ ip = tmpalloc(sizeof(*ip));
+ ip->type = IP_NODE;
+ ip->lineno = 0; /* XXX */
+ ip->ip_node = l;
+ pass2_compile(ip);
+ return r;
+ } else if (l)
+ return l;
+ else if (r)
+ return r;
+ return NULL;
+}
+
+static struct interpass ipole;
+struct interpass_prolog *ipp, *epp;
+
+/*
+ * Receives interpass structs from pass1.
+ */
+void
+pass2_compile(struct interpass *ip)
+{
+ if (ip->type == IP_PROLOG) {
+ tmpsave = NULL;
+ ipp = (struct interpass_prolog *)ip;
+ DLIST_INIT(&ipole, qelem);
+ }
+ DLIST_INSERT_BEFORE(&ipole, ip, qelem);
+ if (ip->type != IP_EPILOG)
+ return;
+
+#ifdef PCC_DEBUG
+ if (e2debug) {
+ printf("Entering pass2\n");
+ printip(&ipole);
+ }
+#endif
+
+ epp = (struct interpass_prolog *)DLIST_PREV(&ipole, qelem);
+ p2maxautooff = p2autooff = epp->ipp_autos;
+
+ myreader(&ipole); /* local massage of input */
+
+ DLIST_FOREACH(ip, &ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ if (xtemps == 0)
+ walkf(ip->ip_node, deltemp);
+ }
+ DLIST_FOREACH(ip, &ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ canon(ip->ip_node);
+ walkf(ip->ip_node, cktree);
+ if ((ip->ip_node = deluseless(ip->ip_node)) == NULL)
+ DLIST_REMOVE(ip, qelem);
+ }
+
+ optimize(&ipole);
+ ngenregs(&ipole);
+
+ DLIST_FOREACH(ip, &ipole, qelem)
+ emit(ip);
+}
+
+void
+emit(struct interpass *ip)
+{
+ NODE *p;
+ int o;
+
+ switch (ip->type) {
+ case IP_NODE:
+ p = ip->ip_node;
+
+ nodepole = p;
+//printf("bu:\n");
+//fwalk(p, e2print, 0);
+ canon(p); /* may convert stuff after genregs */
+//fwalk(p, e2print, 0);
+ switch (p->n_op) {
+ case CBRANCH:
+ /* Only emit branch insn if RESCC */
+ if (table[TBLIDX(p->n_left->n_su)].rewrite & RESCC) {
+ o = p->n_left->n_op;
+ gencode(p, FORCC);
+ cbgen(o, p->n_right->n_lval);
+ } else
+ gencode(p, FORCC);
+ break;
+ case FORCE:
+ gencode(p->n_left, INREGS);
+ break;
+ default:
+ if (p->n_op != REG || p->n_type != VOID) /* XXX */
+ gencode(p, FOREFF); /* Emit instructions */
+ }
+
+ tfree(p);
+ break;
+ case IP_PROLOG:
+ prologue((struct interpass_prolog *)ip);
+ break;
+ case IP_EPILOG:
+ eoftn((struct interpass_prolog *)ip);
+ tmpsave = NULL; /* Always forget old nodes */
+ p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
+ break;
+ case IP_DEFLAB:
+ deflab(ip->ip_lbl);
+ break;
+ case IP_ASM:
+ printf("\t%s\n", ip->ip_asm);
+ break;
+ default:
+ cerror("compile4 %d", ip->type);
+ }
+}
+
+#ifdef PCC_DEBUG
+char *cnames[] = {
+ "SANY",
+ "SAREG",
+ "SBREG",
+ "SCREG",
+ "SDREG",
+ "SCC",
+ "SNAME",
+ "SCON",
+ "SFLD",
+ "SOREG",
+ "STARNM",
+ "STARREG",
+ "INTEMP",
+ "FORARG",
+ "SWADD",
+ 0,
+};
+
+/*
+ * print a nice-looking description of cookie
+ */
+char *
+prcook(int cookie)
+{
+ static char buf[50];
+ int i, flag;
+
+ if (cookie & SPECIAL) {
+ switch (cookie) {
+ case SZERO:
+ return "SZERO";
+ case SONE:
+ return "SONE";
+ case SMONE:
+ return "SMONE";
+ default:
+ snprintf(buf, sizeof(buf), "SPECIAL+%d", cookie & ~SPECIAL);
+ return buf;
+ }
+ }
+
+ flag = 0;
+ buf[0] = 0;
+ for (i = 0; cnames[i]; ++i) {
+ if (cookie & (1<<i)) {
+ if (flag)
+ strlcat(buf, "|", sizeof(buf));
+ ++flag;
+ strlcat(buf, cnames[i], sizeof(buf));
+ }
+ }
+ return buf;
+}
+
+#endif
+
+int odebug = 0;
+
+int
+geninsn(NODE *p, int cookie)
+{
+ NODE *p1, *p2;
+ int o, rv = 0;
+
+#ifdef PCC_DEBUG
+ if (odebug) {
+ printf("geninsn(%p, %s)\n", p, prcook(cookie));
+ fwalk(p, e2print, 0);
+ }
+#endif
+
+again: switch (o = p->n_op) {
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case ULE:
+ case ULT:
+ case UGE:
+ case UGT:
+ rv = relops(p);
+ break;
+
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ case MOD:
+ case AND:
+ case OR:
+ case ER:
+ case LS:
+ case RS:
+ rv = findops(p, cookie);
+ break;
+
+ case ASSIGN:
+ case STASG:
+ rv = findasg(p, cookie);
+ break;
+
+ case UMUL: /* May turn into an OREG */
+ rv = findumul(p, cookie);
+ break;
+
+ case REG:
+ case TEMP:
+ case NAME:
+ case ICON:
+ case OREG:
+ rv = findleaf(p, cookie);
+ break;
+
+ case STCALL:
+ case CALL:
+ /* CALL arguments are handled special */
+ for (p1 = p->n_right; p1->n_op == CM; p1 = p1->n_left)
+ geninsn(p1->n_right, FOREFF);
+ geninsn(p1, FOREFF);
+ /* FALLTHROUGH */
+ case COMPL:
+ case UMINUS:
+ case PCONV:
+ case SCONV:
+/* case INIT: */
+ case GOTO:
+ case FUNARG:
+ case STARG:
+ case UCALL:
+ case USTCALL:
+ rv = finduni(p, cookie);
+ break;
+
+ case CBRANCH:
+ p1 = p->n_left;
+ p2 = p->n_right;
+ p1->n_label = p2->n_lval;
+ o = p1->n_op;
+ geninsn(p1, FORCC);
+ p->n_su = 0;
+ break;
+
+ case FORCE: /* XXX needed? */
+ geninsn(p->n_left, INREGS);
+ p->n_su = 0; /* su calculations traverse left */
+ break;
+
+ default:
+ comperr("geninsn: bad op %s, node %p", opst[o], p);
+ }
+ if (rv == FFAIL)
+ comperr("Cannot generate code, node %p op %s", p,opst[p->n_op]);
+ if (rv == FRETRY)
+ goto again;
+ return rv;
+}
+
+/*
+ * Store a given subtree in a temporary location.
+ * Return an OREG node where it is located.
+ */
+NODE *
+store(NODE *p)
+{
+ extern struct interpass *storesave;
+ struct interpass *ip;
+ NODE *q, *r;
+ int s;
+
+ s = BITOOR(freetemp(szty(p->n_type)));
+ q = mklnode(OREG, s, FPREG, p->n_type);
+ r = mklnode(OREG, s, FPREG, p->n_type);
+ ip = ipnode(mkbinode(ASSIGN, q, p, p->n_type));
+
+ storesave = ip;
+ return r;
+}
+
+#ifdef PCC_DEBUG
+#define CDEBUG(x) if (c2debug) printf x
+#else
+#define CDEBUG(x)
+#endif
+
+/*
+ * Do a register-register move if necessary.
+ */
+static void
+ckmove(NODE *p, NODE *q)
+{
+ if (q->n_op != REG || p->n_reg == -1)
+ return; /* no register */
+ if (DECRA(p->n_reg, 0) == DECRA(q->n_reg, 0))
+ return; /* no move necessary */
+ CDEBUG(("rmove: node %p, %s -> %s\n", p, rnames[DECRA(q->n_reg, 0)],
+ rnames[DECRA(p->n_reg, 0)]));
+ rmove(DECRA(q->n_reg, 0), DECRA(p->n_reg, 0), p->n_type);
+ q->n_reg = q->n_rval = DECRA(p->n_reg, 0);
+}
+
+/*
+ * Rewrite node to register after instruction emit.
+ */
+static void
+rewrite(NODE *p, int rewrite, int cookie)
+{
+ NODE *l, *r;
+ int o;
+
+ l = getlr(p, 'L');
+ r = getlr(p, 'R');
+ o = p->n_op;
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_name = "";
+
+ if (o == ASSIGN) {
+ /* special rewrite care */
+ int reg = DECRA(p->n_reg, 0);
+#define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
+ if (p->n_reg == -1)
+ ;
+ else if (TL(l) && (DECRA(l->n_reg, 0) == reg))
+ ;
+ else if (TL(r) && (DECRA(r->n_reg, 0) == reg))
+ ;
+ else if (TL(l))
+ rmove(DECRA(l->n_reg, 0), reg, p->n_type);
+ else if (TL(r))
+ rmove(DECRA(r->n_reg, 0), reg, p->n_type);
+#if 0
+ else
+ comperr("rewrite");
+#endif
+#undef TL
+ }
+ if (optype(o) != LTYPE)
+ tfree(l);
+ if (optype(o) == BITYPE)
+ tfree(r);
+ if (rewrite == 0)
+ return;
+ CDEBUG(("rewrite: %p, reg %s\n", p, rnames[DECRA(p->n_reg, 0)]));
+ p->n_rval = DECRA(p->n_reg, 0);
+}
+
+void
+gencode(NODE *p, int cookie)
+{
+ struct optab *q = &table[TBLIDX(p->n_su)];
+ NODE *p1, *l, *r;
+ int o = optype(p->n_op);
+
+ l = p->n_left;
+ r = p->n_right;
+
+ if (TBLIDX(p->n_su) == 0) {
+ if (o == BITYPE && (p->n_su & DORIGHT))
+ gencode(r, 0);
+ if (optype(p->n_op) != LTYPE)
+ gencode(l, 0);
+ if (o == BITYPE && !(p->n_su & DORIGHT))
+ gencode(r, 0);
+ return;
+ }
+
+ CDEBUG(("gencode: node %p\n", p));
+
+ if (p->n_op == REG && DECRA(p->n_reg, 0) == p->n_rval)
+ return; /* meaningless move to itself */
+
+ if (callop(p->n_op))
+ lastcall(p); /* last chance before function args */
+ if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
+ /* Print out arguments first */
+ for (p1 = r; p1->n_op == CM; p1 = p1->n_left)
+ gencode(p1->n_right, FOREFF);
+ gencode(p1, FOREFF);
+ o = UTYPE; /* avoid going down again */
+ }
+
+ if (o == BITYPE && (p->n_su & DORIGHT)) {
+ gencode(r, INREGS);
+ if (q->rewrite & RRIGHT)
+ ckmove(p, r);
+ }
+ if (o != LTYPE) {
+ gencode(l, INREGS);
+ if (q->rewrite & RLEFT)
+ ckmove(p, l);
+ }
+ if (o == BITYPE && !(p->n_su & DORIGHT)) {
+ gencode(r, INREGS);
+ if (q->rewrite & RRIGHT)
+ ckmove(p, r);
+ }
+
+ canon(p);
+
+ if (q->needs & NSPECIAL) {
+ int rr = rspecial(q, NRIGHT);
+ int lr = rspecial(q, NLEFT);
+
+ if (rr >= 0) {
+ if (r->n_op != REG)
+ comperr("gencode: rop != REG");
+ if (rr != r->n_rval)
+ rmove(r->n_rval, rr, r->n_type);
+ r->n_rval = r->n_reg = rr;
+ }
+ if (lr >= 0) {
+ if (l->n_op != REG)
+ comperr("gencode: %p lop != REG", p);
+ if (lr != l->n_rval)
+ rmove(l->n_rval, lr, l->n_type);
+ l->n_rval = l->n_reg = lr;
+ }
+ if (rr >= 0 && lr >= 0 && (l->n_reg == rr || r->n_reg == lr))
+ comperr("gencode: cross-reg-move");
+ }
+
+ if (p->n_op == ASSIGN &&
+ p->n_left->n_op == REG && p->n_right->n_op == REG &&
+ p->n_left->n_rval == p->n_right->n_rval){
+ /* do not emit anything */
+ CDEBUG(("gencode(%p) assign nothing\n", p));
+ rewrite(p, q->rewrite, cookie);
+ return;
+ }
+
+ CDEBUG(("emitting node %p\n", p));
+ if (TBLIDX(p->n_su) == 0)
+ return;
+
+ expand(p, cookie, q->cstring);
+ if (callop(p->n_op) && cookie != FOREFF &&
+ DECRA(p->n_reg, 0) != RETREG(p->n_type)) {
+ CDEBUG(("gencode(%p) retreg\n", p));
+ rmove(RETREG(p->n_type), DECRA(p->n_reg, 0), p->n_type);
+ } else if (q->needs & NSPECIAL) {
+ int rr = rspecial(q, NRES);
+
+ if (rr >= 0 && DECRA(p->n_reg, 0) != rr) {
+ CDEBUG(("gencode(%p) nspec retreg\n", p));
+ rmove(rr, DECRA(p->n_reg, 0), p->n_type);
+ }
+ } else if ((q->rewrite & RESC1) &&
+ (DECRA(p->n_reg, 1) != DECRA(p->n_reg, 0))) {
+ CDEBUG(("gencode(%p) RESC1 retreg\n", p));
+ rmove(DECRA(p->n_reg, 1), DECRA(p->n_reg, 0), p->n_type);
+ }
+#if 0
+ /* XXX - kolla upp det här */
+ else if (p->n_op == ASSIGN) {
+ /* may need move added if RLEFT/RRIGHT */
+ /* XXX should be handled in sucomp() */
+ if ((q->rewrite & RLEFT) && (p->n_left->n_op == REG) &&
+ (p->n_left->n_rval != DECRA(p->n_reg, 0)) &&
+ TCLASS(p->n_su)) {
+ rmove(p->n_left->n_rval, DECRA(p->n_reg, 0), p->n_type);
+ } else if ((q->rewrite & RRIGHT) && (p->n_right->n_op == REG) &&
+ (p->n_right->n_rval != DECRA(p->n_reg, 0)) &&
+ TCLASS(p->n_su)) {
+ rmove(p->n_right->n_rval, DECRA(p->n_reg, 0), p->n_type);
+ }
+ }
+#endif
+ rewrite(p, q->rewrite, cookie);
+}
+
+int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */
+
+#ifdef PCC_DEBUG
+#undef PRTABLE
+void
+e2print(NODE *p, int down, int *a, int *b)
+{
+#ifdef PRTABLE
+ extern int tablesize;
+#endif
+
+ prfil = stdout;
+ *a = *b = down+1;
+ while( down >= 2 ){
+ fprintf(prfil, "\t");
+ down -= 2;
+ }
+ if( down-- ) fprintf(prfil, " " );
+
+
+ fprintf(prfil, "%p) %s", p, opst[p->n_op] );
+ switch( p->n_op ) { /* special cases */
+
+ case REG:
+ fprintf(prfil, " %s", rnames[p->n_rval] );
+ break;
+
+ case TEMP:
+ fprintf(prfil, " " CONFMT, p->n_lval);
+ break;
+
+ case ICON:
+ case NAME:
+ case OREG:
+ fprintf(prfil, " " );
+ adrput(prfil, p );
+ break;
+
+ case STCALL:
+ case USTCALL:
+ case STARG:
+ case STASG:
+ fprintf(prfil, " size=%d", p->n_stsize );
+ fprintf(prfil, " align=%d", p->n_stalign );
+ break;
+ }
+
+ fprintf(prfil, ", " );
+ tprint(prfil, p->n_type, p->n_qual);
+ fprintf(prfil, ", " );
+ {
+ int gregn(struct regw *);
+ if (p->n_reg == -1)
+ fprintf(prfil, "REG <undef>");
+ else if (p->n_reg < 100000) /* XXX */
+ fprintf(prfil, "REG %s", rnames[DECRA(p->n_reg, 0)]);
+ else
+ fprintf(prfil, "TEMP %d", gregn(p->n_regw));
+ }
+ fprintf(prfil, ", SU= %d(%cREG,%s,%s,%s,%s)\n",
+ TBLIDX(p->n_su),
+ TCLASS(p->n_su)+'@',
+#ifdef PRTABLE
+ TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
+ table[TBLIDX(p->n_su)].cstring : "",
+#else
+ "",
+#endif
+ ltyp[LMASK&p->n_su],
+ rtyp[(p->n_su&RMASK) >> 2], p->n_su & DORIGHT ? "DORIGHT" : "");
+}
+#endif
+
+#ifndef FIELDOPS
+/*
+ * do this if there is no special hardware support for fields
+ */
+static void
+ffld(NODE *p, int down, int *down1, int *down2 )
+{
+ /*
+ * look for fields that are not in an lvalue context,
+ * and rewrite them...
+ */
+ NODE *shp;
+ int s, o, v, ty;
+
+ *down1 = asgop( p->n_op );
+ *down2 = 0;
+
+ if( !down && p->n_op == FLD ){ /* rewrite the node */
+
+ if( !rewfld(p) ) return;
+
+ ty = p->n_type;
+ v = p->n_rval;
+ s = UPKFSZ(v);
+# ifdef RTOLBYTES
+ o = UPKFOFF(v); /* amount to shift */
+# else
+ o = szty(p->n_type)*SZINT - s - UPKFOFF(v); /* amount to shift */
+#endif
+
+ /* make & mask part */
+
+ p->n_left->n_type = ty;
+
+ p->n_op = AND;
+ p->n_right = mklnode(ICON, (1 << s)-1, 0, ty);
+
+ /* now, if a shift is needed, do it */
+
+ if( o != 0 ){
+ shp = mkbinode(RS, p->n_left,
+ mklnode(ICON, o, 0, INT), ty);
+ p->n_left = shp;
+ /* whew! */
+ }
+ }
+}
+#endif
+
+/*
+ * change left TEMPs into OREGs
+ */
+void
+deltemp(NODE *p)
+{
+ struct tmpsave *w;
+ NODE *l;
+
+ if (p->n_op == TEMP) {
+ /* Check if already existing */
+ for (w = tmpsave; w; w = w->next)
+ if (w->tempno == p->n_lval)
+ break;
+ if (w == NULL) {
+ /* new on stack */
+ w = tmpalloc(sizeof(struct tmpsave));
+ w->tempno = p->n_lval;
+ w->tempaddr = BITOOR(freetemp(szty(p->n_type)));
+ w->next = tmpsave;
+ tmpsave = w;
+ }
+ p->n_op = OREG;
+ p->n_rval = FPREG;
+ p->n_lval = w->tempaddr;
+ } else if (p->n_op == ADDROF) {
+ /* TEMPs are already converted to OREGs */
+ if ((l = p->n_left)->n_op != OREG)
+ comperr("bad U&");
+ p->n_op = PLUS;
+ l->n_op = REG;
+ l->n_type = INCREF(l->n_type);
+ p->n_right = mklnode(ICON, l->n_lval, 0, INT);
+ }
+}
+
+/*
+ * for pointer/integer arithmetic, set pointer at left node
+ */
+static void
+setleft(NODE *p)
+{
+ NODE *q;
+
+ /* only additions for now */
+ if (p->n_op != PLUS)
+ return;
+ if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
+ q = p->n_right;
+ p->n_right = p->n_left;
+ p->n_left = q;
+ }
+}
+
+/* It is OK to have these as externals */
+static int oregr;
+static CONSZ oregtemp;
+static char *oregcp;
+/*
+ * look for situations where we can turn * into OREG
+ * If sharp then do not allow temps.
+ */
+int
+oregok(NODE *p, int sharp)
+{
+
+ NODE *q;
+ NODE *ql, *qr;
+ int r;
+ CONSZ temp;
+ char *cp;
+
+ q = p->n_left;
+#if 0
+ if ((q->n_op == REG || (q->n_op == TEMP && !sharp)) &&
+ q->n_rval == DECRA(q->n_reg, 0)) {
+#endif
+ if (q->n_op == REG || (q->n_op == TEMP && !sharp)) {
+ temp = q->n_lval;
+ r = q->n_rval;
+ cp = q->n_name;
+ goto ormake;
+ }
+
+ if (q->n_op != PLUS && q->n_op != MINUS)
+ return 0;
+ ql = q->n_left;
+ qr = q->n_right;
+
+#ifdef R2REGS
+
+ /* look for doubly indexed expressions */
+ /* XXX - fix checks */
+
+ if( q->n_op == PLUS) {
+ int i;
+ if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
+ makeor2(p, ql, r, i);
+ return;
+ } else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
+ makeor2(p, qr, r, i);
+ return;
+ }
+ }
+
+
+#endif
+
+#if 0
+ if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
+ (ql->n_op==REG || (ql->n_op==TEMP && !sharp)) &&
+ szty(qr->n_type)==1 &&
+ (ql->n_rval == DECRA(ql->n_reg, 0) ||
+ /* XXX */
+ ql->n_rval == FPREG || ql->n_rval == STKREG)) {
+#endif
+ if ((q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
+ (ql->n_op==REG || (ql->n_op==TEMP && !sharp))) {
+
+ temp = qr->n_lval;
+ if( q->n_op == MINUS ) temp = -temp;
+ r = ql->n_rval;
+ temp += ql->n_lval;
+ cp = qr->n_name;
+ if( *cp && ( q->n_op == MINUS || *ql->n_name ) )
+ return 0;
+ if( !*cp ) cp = ql->n_name;
+
+ ormake:
+ if( notoff( p->n_type, r, temp, cp ))
+ return 0;
+ oregtemp = temp;
+ oregr = r;
+ oregcp = cp;
+ return 1;
+ }
+ return 0;
+}
+
+static void
+ormake(NODE *p)
+{
+ NODE *q = p->n_left;
+
+ p->n_op = OREG;
+ p->n_rval = oregr;
+ p->n_lval = oregtemp;
+ p->n_name = oregcp;
+ tfree(q);
+}
+
+/*
+ * look for situations where we can turn * into OREG
+ */
+void
+oreg2(NODE *p)
+{
+ if (p->n_op != UMUL)
+ return;
+ if (oregok(p, 1))
+ ormake(p);
+ if (p->n_op == UMUL)
+ myormake(p);
+}
+
+void
+canon(p) NODE *p; {
+ /* put p in canonical form */
+
+ walkf(p, setleft); /* ptrs at left node for arithmetic */
+ walkf(p, oreg2); /* look for and create OREG nodes */
+#ifndef FIELDOPS
+ fwalk(p, ffld, 0); /* look for field operators */
+# endif
+#ifdef MYCANON
+ MYCANON(p); /* your own canonicalization routine(s) */
+#endif
+
+}
+
+void
+comperr(char *str, ...)
+{
+ extern char *ftitle;
+ va_list ap;
+
+ va_start(ap, str);
+ fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
+ vfprintf(stderr, str, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ prfil = stderr;
+
+ if (nodepole && nodepole->n_op != FREE)
+ fwalk(nodepole, e2print, 0);
+ exit(1);
+}
+
+/*
+ * allocate k integers worth of temp space
+ * we also make the convention that, if the number of words is
+ * more than 1, it must be aligned for storing doubles...
+ * Returns bits offset from base register.
+ * XXX - redo this.
+ */
+int
+freetemp(int k)
+{
+#ifndef BACKTEMP
+ int t;
+
+ if (k > 1)
+ SETOFF(p2autooff, ALDOUBLE/ALCHAR);
+
+ t = p2autooff;
+ p2autooff += k*(SZINT/SZCHAR);
+ if (p2autooff > p2maxautooff)
+ p2maxautooff = p2autooff;
+ return (t);
+
+#else
+ p2autooff += k*(SZINT/SZCHAR);
+ if (k > 1)
+ SETOFF(p2autooff, ALDOUBLE/ALCHAR);
+
+ if (p2autooff > p2maxautooff)
+ p2maxautooff = p2autooff;
+ return( -p2autooff );
+#endif
+ }
+
+NODE *
+mklnode(int op, CONSZ lval, int rval, TWORD type)
+{
+ NODE *p = talloc();
+
+ p->n_name = "";
+ p->n_qual = 0;
+ p->n_op = op;
+ p->n_lval = lval;
+ p->n_rval = rval;
+ p->n_type = type;
+ p->n_regw = NULL;
+ p->n_su = 0;
+ return p;
+}
+
+NODE *
+mkbinode(int op, NODE *left, NODE *right, TWORD type)
+{
+ NODE *p = talloc();
+
+ p->n_name = "";
+ p->n_qual = 0;
+ p->n_op = op;
+ p->n_left = left;
+ p->n_right = right;
+ p->n_type = type;
+ p->n_regw = NULL;
+ return p;
+}
+
+NODE *
+mkunode(int op, NODE *left, int rval, TWORD type)
+{
+ NODE *p = talloc();
+
+ p->n_name = "";
+ p->n_qual = 0;
+ p->n_op = op;
+ p->n_left = left;
+ p->n_rval = rval;
+ p->n_type = type;
+ p->n_regw = NULL;
+ return p;
+}
+
+struct interpass *
+ipnode(NODE *p)
+{
+ struct interpass *ip = tmpalloc(sizeof(struct interpass));
+
+ ip->ip_node = p;
+ ip->type = IP_NODE;
+ ip->lineno = thisline;
+ return ip;
+}
+
+int
+rspecial(struct optab *q, int what)
+{
+ struct rspecial *r = nspecial(q);
+ while (r->op) {
+ if (r->op == what)
+ return r->num;
+ r++;
+ }
+ return -1;
+}
diff --git a/usr.bin/pcc/mip/regs.c b/usr.bin/pcc/mip/regs.c
new file mode 100644
index 00000000000..3371b4bee79
--- /dev/null
+++ b/usr.bin/pcc/mip/regs.c
@@ -0,0 +1,2244 @@
+/* $Id: regs.c,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+/*
+ * Copyright (c) 2005 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>
+#include <stdlib.h>
+
+#define MAXLOOP 20 /* Max number of allocation loops XXX 3 should be enough */
+
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+/*
+ * New-style register allocator using graph coloring.
+ * The design is based on the George and Appel paper
+ * "Iterated Register Coalescing", ACM Transactions, No 3, May 1996.
+ */
+
+#define BIT2BYTE(bits) ((((bits)+NUMBITS-1)/NUMBITS)*(NUMBITS/8))
+#define BITALLOC(ptr,all,sz) { \
+ int __s = BIT2BYTE(sz); ptr = all(__s); memset(ptr, 0, __s); }
+
+#undef COMPERR_PERM_MOVE
+#define RDEBUG(x) if (rdebug) printf x
+#define RRDEBUG(x) if (rdebug > 1) printf x
+#define RPRINTIP(x) if (rdebug) printip(x)
+#define RDX(x) x
+#define UDEBUG(x) if (udebug) printf x
+
+/*
+ * Data structure overview for this implementation of graph coloring:
+ *
+ * Each temporary (called "node") is described by the type REGW.
+ * Space for all nodes is allocated initially as an array, so
+ * the nodes can be can be referenced both by the node number and
+ * by pointer.
+ *
+ * All moves are represented by the type REGM, allocated when needed.
+ *
+ * The "live" set used during graph building is represented by a bitset.
+ *
+ * Interference edges are represented by struct AdjSet, hashed and linked
+ * from index into the edgehash array.
+ *
+ * A mapping from each node to the moves it is assiciated with is
+ * maintained by an array moveList which for each node number has a linked
+ * list of MOVL types, each pointing to a REGM.
+ *
+ * Adjacency list is maintained by the adjList array, indexed by the
+ * node number. Each adjList entry points to an ADJL type, and is a
+ * single-linked list for all adjacent nodes.
+ *
+ * degree, alias and color are integer arrays indexed by node number.
+ */
+
+/*
+ * linked list of adjacent nodes.
+ */
+typedef struct regw3 {
+ struct regw3 *r_next;
+ struct regw *a_temp;
+} ADJL;
+
+/*
+ * Structure describing a move.
+ */
+typedef struct regm {
+ DLIST_ENTRY(regm) link;
+ struct regw *src, *dst;
+ int queue;
+} REGM;
+
+typedef struct movlink {
+ struct movlink *next;
+ REGM *regm;
+} MOVL;
+
+/*
+ * Structure describing a temporary.
+ */
+typedef struct regw {
+ DLIST_ENTRY(regw) link;
+ ADJL *r_adjList; /* linked list of adjacent nodes */
+ int r_class; /* this nodes class */
+ int r_nclass[NUMCLASS+1]; /* count of adjacent classes */
+ struct regw *r_alias; /* aliased temporary */
+ int r_color; /* final node color */
+ struct regw *r_onlist; /* which work list this node belongs to */
+ MOVL *r_moveList; /* moves associated with this node */
+#ifdef PCC_DEBUG
+ int nodnum; /* Debug number */
+#endif
+} REGW;
+
+/*
+ * Worklists, a node is always on exactly one of these lists.
+ */
+static REGW precolored, simplifyWorklist, freezeWorklist, spillWorklist,
+ spilledNodes, coalescedNodes, coloredNodes, selectStack;
+static REGW initial, *nblock;
+static void insnwalk(NODE *p);
+#ifdef PCC_DEBUG
+int nodnum = 100;
+#define SETNUM(x) (x)->nodnum = nodnum++
+#define ASGNUM(x) (x)->nodnum
+#else
+#define SETNUM(x)
+#define ASGNUM(x)
+#endif
+
+#define ALLNEEDS (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT)
+
+/* XXX */
+REGW *ablock;
+
+static int tempmin, tempmax, basetemp, xbits;
+/*
+ * nsavregs is an array that matches the permregs array.
+ * Each entry in the array may have the values:
+ * 0 : register coalesced, just ignore.
+ * 1 : save register on stack
+ * If the entry is 0 but the resulting color differs from the
+ * corresponding permregs index, add moves.
+ * XXX - should be a bitfield!
+ */
+static int *nsavregs, *ndontregs;
+
+/*
+ * Return the REGW struct for a temporary.
+ * If first time touched, enter into list for existing vars.
+ * Only called from sucomp().
+ */
+static REGW *
+newblock(NODE *p)
+{
+ REGW *nb = &nblock[(int)p->n_lval];
+ if (nb->link.q_forw == 0) {
+ DLIST_INSERT_AFTER(&initial, nb, link);
+ ASGNUM(nb) = p->n_lval;
+ RDEBUG(("Adding longtime %d for tmp %d\n",
+ nb->nodnum, (int)p->n_lval));
+ }
+ if (nb->r_class == 0)
+ nb->r_class = gclass(p->n_type);
+ RDEBUG(("newblock: p %p, node %d class %d\n",
+ p, nb->nodnum, nb->r_class));
+ return nb;
+}
+
+/*
+ * Count the number of registers needed to evaluate a tree.
+ * This is only done to find the evaluation order of the tree.
+ * While here, assign temp numbers to the registers that will
+ * be needed when the tree is evaluated.
+ *
+ * While traversing the tree, assign REGW nodes to the registers
+ * used by all instructions:
+ * - n_regw[0] is always set to the outgoing node. If the
+ * instruction is 2-op (addl r0,r1) then an implicit move
+ * is inserted just before the left (clobbered) operand.
+ * - if the instruction has needs then REGW nodes are
+ * allocated as n_regw[1] etc.
+ */
+int
+nsucomp(NODE *p)
+{
+ struct optab *q;
+ int left, right;
+ int nreg, need, i, nxreg, o;
+ int nareg, nbreg, ncreg, ndreg;
+ REGW *w;
+
+ o = optype(p->n_op);
+
+ UDEBUG(("entering nsucomp, node %p\n", p));
+
+ if (TBLIDX(p->n_su) == 0) {
+ int a = 0, b;
+
+ p->n_regw = NULL;
+ if (o == LTYPE ) {
+ if (p->n_op == TEMP)
+ p->n_regw = newblock(p);
+ } else
+ a = nsucomp(p->n_left);
+ if (o == BITYPE) {
+ b = nsucomp(p->n_right);
+ if (b > a)
+ p->n_su |= DORIGHT;
+ a = MAX(a, b);
+ }
+ return a;
+ }
+
+ q = &table[TBLIDX(p->n_su)];
+ nareg = (q->needs & NACOUNT);
+
+ for (i = (q->needs & NBCOUNT), nbreg = 0; i; i -= NBREG)
+ nbreg++;
+ for (i = (q->needs & NCCOUNT), ncreg = 0; i; i -= NCREG)
+ ncreg++;
+ for (i = (q->needs & NDCOUNT), ndreg = 0; i; i -= NDREG)
+ ndreg++;
+
+ nxreg = nareg + nbreg + ncreg + ndreg;
+ nreg = nxreg;
+ if (callop(p->n_op))
+ nreg = MAX(fregs, nreg);
+
+ if (o == BITYPE) {
+ right = nsucomp(p->n_right);
+ } else
+ right = 0;
+
+ if (o != LTYPE)
+ left = nsucomp(p->n_left);
+ else
+ left = 0;
+
+ UDEBUG(("node %p left %d right %d\n", p, left, right));
+
+ if (o == BITYPE) {
+ /* Two children */
+ if (right == left) {
+ need = left + MAX(nreg, 1);
+ } else {
+ need = MAX(right, left);
+ need = MAX(need, nreg);
+ }
+ if (setorder(p) == 0) {
+ /* XXX - should take care of overlapping needs */
+ if (right > left) {
+ p->n_su |= DORIGHT;
+ } else if (right == left) {
+ /* A favor to 2-operand architectures */
+ if ((q->rewrite & RRIGHT) == 0)
+ p->n_su |= DORIGHT;
+ }
+ }
+ } else if (o != LTYPE) {
+ /* One child */
+ need = MAX(right, left) + nreg;
+ } else
+ need = nreg;
+
+ if (p->n_op == TEMP)
+ (void)newblock(p);
+
+ if (TCLASS(p->n_su) == 0 && nxreg == 0) {
+ UDEBUG(("node %p no class\n", p));
+ p->n_regw = NULL; /* may be set earlier */
+ return need;
+ }
+
+#define ADCL(n, cl) \
+ for (i = 0; i < n; i++, w++) { w->r_class = cl; \
+ DLIST_INSERT_BEFORE(&initial, w, link); SETNUM(w); \
+ UDEBUG(("Adding " #n " %d\n", w->nodnum)); \
+ }
+
+ UDEBUG(("node %p numregs %d\n", p, nxreg+1));
+ w = p->n_regw = tmpalloc(sizeof(REGW) * (nxreg+1));
+ memset(w, 0, sizeof(REGW) * (nxreg+1));
+
+ w->r_class = TCLASS(p->n_su);
+ if (w->r_class == 0)
+ w->r_class = gclass(p->n_type);
+ SETNUM(w);
+ if (w->r_class)
+ DLIST_INSERT_BEFORE(&initial, w, link);
+ UDEBUG(("Adding short %d calss %d\n", w->nodnum, w->r_class));
+ w++;
+ ADCL(nareg, CLASSA);
+ ADCL(nbreg, CLASSB);
+ ADCL(ncreg, CLASSC);
+ ADCL(ndreg, CLASSD);
+
+ if (q->rewrite & RESC1) {
+ w = p->n_regw + 1;
+ w->r_class = -1;
+ DLIST_REMOVE(w,link);
+ } else if (q->rewrite & RESC2) {
+ w = p->n_regw + 2;
+ w->r_class = -1;
+ DLIST_REMOVE(w,link);
+ } else if (q->rewrite & RESC3) {
+ w = p->n_regw + 3;
+ w->r_class = -1;
+ DLIST_REMOVE(w,link);
+ }
+
+ UDEBUG(("node %p return regs %d\n", p, need));
+
+ return need;
+}
+
+#define CLASS(x) (x)->r_class
+#define NCLASS(x,c) (x)->r_nclass[c]
+#define ADJLIST(x) (x)->r_adjList
+#define ALIAS(x) (x)->r_alias
+#define ONLIST(x) (x)->r_onlist
+#define MOVELIST(x) (x)->r_moveList
+#define COLOR(x) (x)->r_color
+
+static bittype *live;
+
+#define PUSHWLIST(w, l) DLIST_INSERT_AFTER(&l, w, link); w->r_onlist = &l
+#define POPWLIST(l) popwlist(&l);
+#define DELWLIST(w) DLIST_REMOVE(w, link)
+#define WLISTEMPTY(h) DLIST_ISEMPTY(&h,link)
+#define PUSHMLIST(w, l, q) DLIST_INSERT_AFTER(&l, w, link); w->queue = q
+#define POPMLIST(l) popmlist(&l);
+
+#define trivially_colorable(x) \
+ trivially_colorable_p((x)->r_class, (x)->r_nclass)
+/*
+ * Determine if a node is trivially colorable ("degree < K").
+ * This implementation is a dumb one, without considering speed.
+ */
+static int
+trivially_colorable_p(int c, int *n)
+{
+ int r[NUMCLASS+1];
+ int i;
+
+ for (i = 1; i < NUMCLASS+1; i++)
+ r[i] = n[i] < regK[i] ? n[i] : regK[i];
+
+#if 0
+ /* add the exclusion nodes. */
+ /* XXX can we do someything smart here? */
+ /* worst-case for exclusion nodes are better than the `worst-case' */
+ for (; excl; excl >>= 1)
+ if (excl & 1)
+ r[c]++;
+#endif
+
+ i = COLORMAP(c, r);
+if (i < 0 || i > 1)
+ comperr("trivially_colorable_p");
+//printf("trivially_colorable_p: n[1] %d n[2] %d n[3] %d n[4] %d class %d, triv %d\n", n[1], n[2], n[3], n[4], c, i);
+ return i;
+}
+
+static int
+ncnt(int needs)
+{
+ int i = 0;
+
+ while (needs & NACOUNT)
+ needs -= NAREG, i++;
+ while (needs & NBCOUNT)
+ needs -= NBREG, i++;
+ while (needs & NCCOUNT)
+ needs -= NCREG, i++;
+ while (needs & NDCOUNT)
+ needs -= NDREG, i++;
+ return i;
+}
+
+static inline REGW *
+popwlist(REGW *l)
+{
+ REGW *w = DLIST_NEXT(l, link);
+
+ DLIST_REMOVE(w, link);
+ w->r_onlist = NULL;
+ return w;
+}
+
+/*
+ * Move lists, a move node is always on only one list.
+ */
+static REGM coalescedMoves, constrainedMoves, frozenMoves,
+ worklistMoves, activeMoves;
+enum { COAL, CONSTR, FROZEN, WLIST, ACTIVE };
+
+static inline REGM *
+popmlist(REGM *l)
+{
+ REGM *w = DLIST_NEXT(l, link);
+
+ DLIST_REMOVE(w, link);
+ return w;
+}
+
+/*
+ * About data structures used in liveness analysis:
+ *
+ * The temporaries generated in pass1 are numbered between tempmin and
+ * tempmax. Temporaries generated in pass2 are numbered above tempmax,
+ * so they are sequentially numbered.
+ *
+ * Bitfields are used for liveness. Bit arrays are allocated on the
+ * heap for the "live" variable and on the stack for the in, out, gen
+ * and kill variables. Therefore, for a temp number, the bit number must
+ * be biased with tempmin.
+ *
+ * There may be an idea to use a different data structure to store
+ * pass2 allocated temporaries, because they are very sparse.
+ */
+
+#ifdef PCC_DEBUG
+static void
+LIVEADD(int x)
+{
+ RDEBUG(("Liveadd: %d\n", x));
+ if (x < tempmin || x >= tempmax)
+ comperr("LIVEADD: out of range");
+ BITSET(live, (x-tempmin));
+}
+static void
+LIVEDEL(int x)
+{
+ RDEBUG(("Livedel: %d\n", x));
+ if (x < tempmin || x >= tempmax)
+ comperr("LIVEDEL: out of range");
+ BITCLEAR(live, (x-tempmin));
+}
+#else
+#define LIVEADD(x) BITSET(live, (x-tempmin))
+#define LIVEDEL(x) BITCLEAR(live, (x-tempmin))
+#endif
+
+static struct lives {
+ DLIST_ENTRY(lives) link;
+ REGW *var;
+} lused, lunused;
+
+static void
+LIVEADDR(REGW *x)
+{
+ struct lives *l;
+
+#ifdef PCC_DEBUG
+ RDEBUG(("LIVEADDR: %d\n", x->nodnum));
+ DLIST_FOREACH(l, &lused, link)
+ if (l->var == x)
+ return;
+// comperr("LIVEADDR: multiple %d", ASGNUM(x));
+#endif
+ if (!DLIST_ISEMPTY(&lunused, link)) {
+ l = DLIST_NEXT(&lunused, link);
+ DLIST_REMOVE(l, link);
+ } else
+ l = tmpalloc(sizeof(struct lives));
+
+ l->var = x;
+ DLIST_INSERT_AFTER(&lused, l, link);
+}
+
+static void
+LIVEDELR(REGW *x)
+{
+ struct lives *l;
+
+ RDEBUG(("LIVEDELR: %d\n", x->nodnum));
+ DLIST_FOREACH(l, &lused, link) {
+ if (l->var != x)
+ continue;
+ DLIST_REMOVE(l, link);
+ DLIST_INSERT_AFTER(&lunused, l, link);
+ return;
+ }
+// comperr("LIVEDELR: %p not found", x);
+}
+
+#define MOVELISTADD(t, p) movelistadd(t, p)
+#define WORKLISTMOVEADD(s,d) worklistmoveadd(s,d)
+
+static void
+movelistadd(REGW *t, REGM *p)
+{
+ MOVL *w = tmpalloc(sizeof(MOVL));
+
+ w->regm = p;
+ w->next = t->r_moveList;
+ t->r_moveList = w;
+}
+
+static REGM *
+worklistmoveadd(REGW *src, REGW *dst)
+{
+ REGM *w = tmpalloc(sizeof(REGM));
+
+ DLIST_INSERT_AFTER(&worklistMoves, w, link);
+ w->src = src;
+ w->dst = dst;
+ w->queue = WLIST;
+ return w;
+}
+
+struct AdjSet {
+ struct AdjSet *next;
+ REGW *u, *v;
+} *edgehash[256];
+
+/* Check if a node pair is adjacent */
+static int
+adjSet(REGW *u, REGW *v)
+{
+ struct AdjSet *w;
+ REGW *t;
+
+ if (ONLIST(u) == &precolored) {
+ ADJL *a = ADJLIST(v);
+ /*
+ * Check if any of the registers that have edges against v
+ * alias to u.
+ */
+ for (; a; a = a->r_next) {
+ if (ONLIST(a->a_temp) != &precolored)
+ continue;
+ t = a->a_temp;
+ if (interferes(t - ablock, u - ablock))
+ return 1;
+ }
+ }
+ if (u > v)
+ t = v, v = u, u = t;
+ w = edgehash[((int)u+(int)v) & 255];
+ for (; w; w = w->next) {
+ if (u == w->u && v == w->v)
+ return 1;
+ }
+ return 0;
+}
+
+/* Add a pair to adjset. No check for dups */
+static void
+adjSetadd(REGW *u, REGW *v)
+{
+ struct AdjSet *w;
+ int x;
+ REGW *t;
+
+ if (u > v)
+ t = v, v = u, u = t;
+ x = ((int)u+(int)v) & 255;
+ w = tmpalloc(sizeof(struct AdjSet));
+ w->u = u, w->v = v;
+ w->next = edgehash[x];
+ edgehash[x] = w;
+}
+
+/*
+ * Add an interference edge between two nodes.
+ */
+static void
+AddEdge(REGW *u, REGW *v)
+{
+ ADJL *x;
+
+ RRDEBUG(("AddEdge: u %d v %d\n", ASGNUM(u), ASGNUM(v)));
+
+#ifdef PCC_DEBUG
+#if 0
+ if (ASGNUM(u) == 0)
+ comperr("AddEdge 0");
+#endif
+ if (CLASS(u) == 0 || CLASS(v) == 0)
+ comperr("AddEdge class == 0 (%d=%d, %d=%d)",
+ CLASS(u), ASGNUM(u), CLASS(v), ASGNUM(v));
+#endif
+
+ if (u == v)
+ return;
+ if (adjSet(u, v))
+ return;
+
+ adjSetadd(u, v);
+
+#if 0
+ if (ONLIST(u) == &precolored || ONLIST(v) == &precolored)
+ comperr("precolored node in AddEdge");
+#endif
+
+ if (ONLIST(u) != &precolored) {
+ x = tmpalloc(sizeof(ADJL));
+ x->a_temp = v;
+ x->r_next = u->r_adjList;
+ u->r_adjList = x;
+ NCLASS(u, CLASS(v))++;
+ }
+
+ if (ONLIST(v) != &precolored) {
+ x = tmpalloc(sizeof(ADJL));
+ x->a_temp = u;
+ x->r_next = v->r_adjList;
+ v->r_adjList = x;
+ NCLASS(v, CLASS(u))++;
+ }
+
+#if 0
+ RDEBUG(("AddEdge: u %d(d %d) v %d(d %d)\n", u, DEGREE(u), v, DEGREE(v)));
+#endif
+}
+
+static int
+MoveRelated(REGW *n)
+{
+ MOVL *l;
+ REGM *w;
+
+ for (l = MOVELIST(n); l; l = l->next) {
+ w = l->regm;
+ if (w->queue == ACTIVE || w->queue == WLIST)
+ return 1;
+ }
+ return 0;
+}
+
+static void
+MkWorklist(void)
+{
+ REGW *w;
+
+ RDX(int s=0);
+ RDX(int f=0);
+ RDX(int d=0);
+
+ DLIST_INIT(&precolored, link);
+ DLIST_INIT(&simplifyWorklist, link);
+ DLIST_INIT(&freezeWorklist, link);
+ DLIST_INIT(&spillWorklist, link);
+ DLIST_INIT(&spilledNodes, link);
+ DLIST_INIT(&coalescedNodes, link);
+ DLIST_INIT(&coloredNodes, link);
+ DLIST_INIT(&selectStack, link);
+
+ /*
+ * Remove all nodes from the initial list and put them on
+ * one of the worklists.
+ */
+ while (!DLIST_ISEMPTY(&initial, link)) {
+ w = DLIST_NEXT(&initial, link);
+ DLIST_REMOVE(w, link);
+ if (!trivially_colorable(w)) {
+ PUSHWLIST(w, spillWorklist);
+ RDX(s++);
+ } else if (MoveRelated(w)) {
+ PUSHWLIST(w, freezeWorklist);
+ RDX(f++);
+ } else {
+ PUSHWLIST(w, simplifyWorklist);
+ RDX(d++);
+ }
+ }
+ RDEBUG(("MkWorklist: spill %d freeze %d simplify %d\n", s,f,d));
+}
+
+static void
+addalledges(REGW *e)
+{
+ int i, j, k;
+ int nbits = xbits;
+ struct lives *l;
+
+ RDEBUG(("addalledges for %d\n", e->nodnum));
+
+ if (e->r_class == -1)
+ return; /* unused */
+
+ if (ONLIST(e) != &precolored) {
+ for (i = 0; ndontregs[i] >= 0; i++)
+ AddEdge(e, &ablock[ndontregs[i]]);
+ }
+
+ /* First add to long-lived temps */
+ RDEBUG(("addalledges longlived "));
+ for (i = 0; i < nbits; i += NUMBITS) {
+ if ((k = live[i/NUMBITS]) == 0)
+ continue;
+ while (k) {
+ j = ffs(k)-1;
+ AddEdge(&nblock[i+j+tempmin], e);
+ RRDEBUG(("%d ", i+j+tempmin));
+ k &= ~(1 << j);
+ }
+ }
+ RDEBUG(("done\n"));
+ /* short-lived temps */
+ RDEBUG(("addalledges shortlived "));
+ DLIST_FOREACH(l, &lused, link) {
+ RRDEBUG(("%d ", ASGNUM(l->var)));
+ AddEdge(l->var, e);
+ }
+ RDEBUG(("done\n"));
+}
+
+/*
+ * Add a move edge between def and use.
+ */
+static void
+moveadd(REGW *def, REGW *use)
+{
+ REGM *r;
+
+ if (def == use)
+ return; /* no move to itself XXX - ``shouldn't happen'' */
+ RDEBUG(("moveadd: def %d use %d\n", ASGNUM(def), ASGNUM(use)));
+
+ r = WORKLISTMOVEADD(use, def);
+ MOVELISTADD(def, r);
+ MOVELISTADD(use, r);
+}
+
+/*
+ * Traverse arguments backwards.
+ * XXX - can this be tricked in some other way?
+ */
+static void
+argswalk(NODE *p)
+{
+
+ if (p->n_op == CM) {
+ argswalk(p->n_left);
+ insnwalk(p->n_right);
+ } else
+ insnwalk(p);
+}
+
+/*
+ * Add to (or remove from) live set variables that must not
+ * be clobbered when traversing down on the other leg for
+ * a BITYPE node.
+ */
+static void
+setlive(NODE *p, int set, REGW *rv)
+{
+ if (rv != NULL)
+ return set ? LIVEADDR(rv) : LIVEDELR(rv);
+
+ if (p->n_regw != NULL)
+ return set ? LIVEADDR(p->n_regw) : LIVEDELR(p->n_regw);
+
+ switch (optype(p->n_op)) {
+ case LTYPE:
+ if (p->n_op == TEMP)
+ set ? LIVEADD((int)p->n_lval) : LIVEDEL((int)p->n_lval);
+#ifdef notyet
+ else if (p->n_op == REG)
+ ...
+#endif
+ break;
+ case BITYPE:
+ setlive(p->n_right, set, rv);
+ /* FALLTHROUGH */
+ case UTYPE:
+ setlive(p->n_left, set, rv);
+ break;
+ }
+}
+
+/*
+ * Add edges for temporary w against all temporaries that may be
+ * used simultaneously (like index registers).
+ */
+static void
+addedge_r(NODE *p, REGW *w)
+{
+ if (p->n_regw != NULL)
+ return AddEdge(p->n_regw, w);
+
+ if (optype(p->n_op) == BITYPE)
+ addedge_r(p->n_right, w);
+ if (optype(p->n_op) != LTYPE)
+ addedge_r(p->n_left, w);
+}
+
+/*
+ * Do the in-tree part of liveness analysis. (the difficult part)
+ *
+ * Walk down the tree in reversed-evaluation order (backwards).
+ * The moves and edges inserted and evaluation order for
+ * instructions when code is emitted is described here, hence
+ * this code runs the same but backwards.
+ *
+ * 2-op reclaim LEFT: eval L, move to DEST, eval R.
+ * moveadd L,DEST; addedge DEST,R
+ * 2-op reclaim LEFT DORIGHT: eval R, eval L, move to DEST.
+ * moveadd L,DEST; addedge DEST,R; addedge L,R
+ * 2-op reclaim RIGHT; eval L, eval R, move to DEST.
+ * moveadd R,DEST; addedge DEST,L; addedge L,R
+ * 2-op reclaim RIGHT DORIGHT: eval R, move to DEST, eval L.
+ * moveadd R,DEST; addedge DEST,L
+ * 3-op: eval L, eval R
+ * addedge L,R
+ * 3-op DORIGHT: eval R, eval L
+ * addedge L,R
+ *
+ * Instructions with special needs are handled just like these variants,
+ * with the exception of extra added moves and edges.
+ * Moves to special regs are scheduled after the evaluation of both legs.
+ */
+
+#define ASGLEFT(p) (p->n_op == ASSIGN && p->n_left->n_op == TEMP)
+
+static void
+insnwalk(NODE *p)
+{
+ int o = p->n_op;
+ struct optab *q = &table[TBLIDX(p->n_su)];
+ REGW *lr, *rr, *rv, *r, *rrv, *lrv;
+ int i, n;
+
+ RDEBUG(("insnwalk %p\n", p));
+
+ rv = p->n_regw;
+
+ rrv = lrv = NULL;
+ if (ASGLEFT(p)) {
+ int v = p->n_left->n_lval;
+ LIVEDEL(v); /* remove assigned temp from live set */
+ addalledges(&nblock[v]);
+ }
+
+ /* Add edges for the result of this node */
+ if (rv && (q->visit & INREGS || o == TEMP))
+ addalledges(rv);
+
+ /* special handling of CALL operators */
+ if (callop(o)) {
+ if (rv)
+ moveadd(rv, &ablock[RETREG(p->n_type)]);
+ for (i = 0; tempregs[i] >= 0; i++)
+ addalledges(&ablock[tempregs[i]]);
+ }
+
+ /* for special return value registers add moves */
+ if ((q->needs & NSPECIAL) && (n = rspecial(q, NRES)) >= 0) {
+ rv = &ablock[n];
+ moveadd(p->n_regw, rv);
+ }
+
+ /* Check leaves for results in registers */
+ lr = optype(o) != LTYPE ? p->n_left->n_regw : NULL;
+ rr = optype(o) == BITYPE ? p->n_right->n_regw : NULL;
+
+ /* simple needs */
+ n = ncnt(q->needs);
+ for (i = 0; i < n; i++) {
+#if 1
+ static int ncl[] = { 0, NASL, NBSL, NCSL, NDSL };
+ static int ncr[] = { 0, NASR, NBSR, NCSR, NDSR };
+
+ /* edges are already added */
+ if ((r = &p->n_regw[1+i])->r_class == -1)
+ r = p->n_regw;
+ else
+ addalledges(r);
+ if (optype(o) != LTYPE && (q->needs & ncl[CLASS(r)]) == 0)
+ addedge_r(p->n_left, r);
+ if (optype(o) == BITYPE && (q->needs & ncr[CLASS(r)]) == 0)
+ addedge_r(p->n_right, r);
+#else
+ if ((r = &p->n_regw[1+i])->r_class == -1)
+ continue;
+ addalledges(r);
+ if (optype(o) != LTYPE && (q->needs & NASL) == 0)
+ addedge_r(p->n_left, r);
+ if (optype(o) == BITYPE && (q->needs & NASR) == 0)
+ addedge_r(p->n_right, r);
+#endif
+ }
+
+ /* special needs */
+ if (q->needs & NSPECIAL) {
+ struct rspecial *rc;
+ for (rc = nspecial(q); rc->op; rc++) {
+ switch (rc->op) {
+#define ONLY(c,s) if (c) s(c, &ablock[rc->num])
+ case NLEFT:
+ addalledges(&ablock[rc->num]);
+ ONLY(lr, moveadd);
+ break;
+ case NOLEFT:
+ addedge_r(p->n_left, &ablock[rc->num]);
+ break;
+ case NRIGHT:
+ addalledges(&ablock[rc->num]);
+ ONLY(rr, moveadd);
+ break;
+ case NORIGHT:
+ addedge_r(p->n_right, &ablock[rc->num]);
+ break;
+ case NEVER:
+ addalledges(&ablock[rc->num]);
+ break;
+#undef ONLY
+ }
+ }
+ }
+
+ if (o == ASSIGN) {
+ /* needs special treatment */
+ if (lr && rr)
+ moveadd(lr, rr);
+ if (lr && rv)
+ moveadd(lr, rv);
+ if (rr && rv)
+ moveadd(rr, rv);
+ } else if (callop(o)) {
+#ifdef notdef
+ /* calls needs special treatment */
+ for (i = 0; tempregs[i] >= 0; i++)
+ addalledges(&ablock[i]);
+ if (rv)
+ moveadd(rv, &ablock[RETREG(p->n_type)]);
+#endif
+ /* XXX - here must all live arg registers be added
+ * for archs with arguments in registers */
+ } else if (q->rewrite & (RESC1|RESC2|RESC3)) {
+ if (lr && rr)
+ AddEdge(lr, rr);
+ } else if (q->rewrite & RLEFT) {
+ if (lr && rv)
+ moveadd(rv, lr), lrv = rv;
+ if (rr && rv)
+ AddEdge(rr, rv);
+ } else if (q->rewrite & RRIGHT) {
+ if (rr && rv)
+ moveadd(rv, rr), rrv = rv;
+ if (lr && rv)
+ AddEdge(lr, rv);
+ }
+
+ switch (optype(o)) {
+ case BITYPE:
+ if (ASGLEFT(p)) {
+ /* only go down right node */
+ insnwalk(p->n_right);
+ } else if (callop(o)) {
+ insnwalk(p->n_left);
+ /* Do liveness analysis on arguments (backwards) */
+ argswalk(p->n_right);
+ } else if ((p->n_su & DORIGHT) == 0) {
+ setlive(p->n_left, 1, lrv);
+ insnwalk(p->n_right);
+ setlive(p->n_left, 0, lrv);
+ insnwalk(p->n_left);
+ } else {
+ setlive(p->n_right, 1, rrv);
+ insnwalk(p->n_left);
+ setlive(p->n_right, 0, rrv);
+ insnwalk(p->n_right);
+ }
+ break;
+
+ case UTYPE:
+ insnwalk(p->n_left);
+ break;
+
+ case LTYPE:
+ switch (o) {
+ case TEMP:
+ rr = &nblock[(int)p->n_lval];
+ if (rv != rr) {
+ addalledges(rr);
+ moveadd(rv, rr);
+ }
+ LIVEADD((int)p->n_lval);
+ break;
+ case REG:
+ case OREG:
+ /* Liveness for regs??? */
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+}
+
+static bittype **gen, **kill, **in, **out;
+
+static void
+unionize(NODE *p, int bb)
+{
+ int i, o, ty;
+
+ if ((o = p->n_op) == TEMP) {
+#ifdef notyet
+ for (i = 0; i < szty(p->n_type); i++) {
+ BITSET(gen[bb], ((int)p->n_lval - tempmin+i));
+ }
+#else
+ i = 0;
+ BITSET(gen[bb], ((int)p->n_lval - tempmin+i));
+#endif
+ }
+ if (asgop(o) && p->n_left->n_op == TEMP) {
+ int b = p->n_left->n_lval - tempmin;
+#ifdef notyet
+ for (i = 0; i < szty(p->n_type); i++) {
+ BITCLEAR(gen[bb], (b+i));
+ BITSET(kill[bb], (b+i));
+ }
+#else
+ i = 0;
+ BITCLEAR(gen[bb], (b+i));
+ BITSET(kill[bb], (b+i));
+#endif
+ unionize(p->n_right, bb);
+ return;
+ }
+ ty = optype(o);
+ if (ty != LTYPE)
+ unionize(p->n_left, bb);
+ if (ty == BITYPE)
+ unionize(p->n_right, bb);
+}
+
+/*
+ * Do variable liveness analysis. Only analyze the long-lived
+ * variables, and save the live-on-exit temporaries in a bit-field
+ * at the end of each basic block. This bit-field is later used
+ * when doing short-range liveness analysis in Build().
+ */
+static void
+LivenessAnalysis(void)
+{
+ extern struct basicblock bblocks;
+ struct basicblock *bb;
+ struct interpass *ip;
+ int i, bbnum;
+
+ /*
+ * generate the gen-kill sets for all basic blocks.
+ */
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ bbnum = bb->bbnum;
+ for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
+ /* gen/kill is 'p', this node is 'n' */
+ if (ip->type == IP_NODE)
+ unionize(ip->ip_node, bbnum);
+ if (ip == bb->first)
+ break;
+ }
+ memcpy(in[bbnum], gen[bbnum], BIT2BYTE(tempmax-tempmin));
+#ifdef PCC_DEBUG
+ if (rdebug) {
+ printf("basic block %d\ngen: ", bbnum);
+ for (i = 0; i < tempmax-tempmin; i++)
+ if (TESTBIT(gen[bbnum], i))
+ printf("%d ", i+tempmin);
+ printf("\nkill: ");
+ for (i = 0; i < tempmax-tempmin; i++)
+ if (TESTBIT(kill[bbnum], i))
+ printf("%d ", i+tempmin);
+ printf("\n");
+ }
+#endif
+ }
+}
+
+#define SETCOPY(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] = f[i]
+#define SETSET(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] |= f[i]
+#define SETCLEAR(t,f,i,n) for (i = 0; i < n/NUMBITS; i++) t[i] &= ~f[i]
+#define SETCMP(v,t,f,i,n) for (i = 0; i < n/NUMBITS; i++) \
+ if (t[i] != f[i]) v = 1
+
+/*
+ * Build the set of interference edges and adjacency list.
+ */
+static void
+Build(struct interpass *ipole)
+{
+ extern struct basicblock bblocks;
+ struct basicblock bbfake;
+ struct interpass *ip;
+ struct basicblock *bb;
+ struct cfgnode *cn;
+ extern int nbblocks;
+ bittype *saved;
+ int i, j, again, nbits;
+
+ if (xtemps == 0) {
+ /*
+ * No basic block splitup is done if not optimizing,
+ * so fake one basic block to keep the liveness analysis
+ * happy.
+ */
+ nbblocks = 1;
+ bbfake.bbnum = 0;
+ bbfake.last = DLIST_PREV(ipole, qelem);
+ bbfake.first = DLIST_NEXT(ipole, qelem);
+ DLIST_INIT(&bblocks, bbelem);
+ DLIST_INSERT_AFTER(&bblocks, &bbfake, bbelem);
+ SLIST_INIT(&bbfake.children);
+ }
+
+ /* Just fetch space for the temporaries from stack */
+ nbits = xbits+(NUMBITS-1);
+ gen = alloca(nbblocks*sizeof(bittype*));
+ kill = alloca(nbblocks*sizeof(bittype*));
+ in = alloca(nbblocks*sizeof(bittype*));
+ out = alloca(nbblocks*sizeof(bittype*));
+ for (i = 0; i < nbblocks; i++) {
+ BITALLOC(gen[i],alloca,nbits);
+ BITALLOC(kill[i],alloca,nbits);
+ BITALLOC(in[i],alloca,nbits);
+ BITALLOC(out[i],alloca,nbits);
+ }
+ BITALLOC(saved,alloca,nbits);
+ LivenessAnalysis();
+
+ /* register variable temporaries are live */
+ for (i = 0; i < NPERMREG-1; i++) {
+ if (nsavregs[i])
+ continue;
+ BITSET(out[nbblocks-1], i);
+ for (j = i+1; j < NPERMREG-1; j++) {
+ if (nsavregs[j])
+ continue;
+ AddEdge(&nblock[i+tempmin], &nblock[j+tempmin]);
+ }
+ }
+
+ /* do liveness analysis on basic block level */
+ do {
+ again = 0;
+ /* XXX - loop should be in reversed execution-order */
+ DLIST_FOREACH_REVERSE(bb, &bblocks, bbelem) {
+ int i = bb->bbnum;
+ SETCOPY(saved, out[i], j, nbits);
+ SLIST_FOREACH(cn, &bb->children, cfgelem) {
+ SETSET(out[i], in[cn->bblock->bbnum],
+ j, nbits);
+ }
+ SETCMP(again, saved, out[i], j, nbits);
+ SETCOPY(saved, in[i], j, nbits);
+ SETCOPY(in[i], out[i], j, nbits);
+ SETCLEAR(in[i], kill[i], j, nbits);
+ SETSET(in[i], gen[i], j, nbits);
+ SETCMP(again, saved, in[i], j, nbits);
+ }
+ } while (again);
+
+#ifdef PCC_DEBUG
+ if (rdebug) {
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ printf("basic block %d\nin: ", bb->bbnum);
+ for (i = 0; i < tempmax-tempmin; i++)
+ if (TESTBIT(in[bb->bbnum], i))
+ printf("%d ", i+tempmin);
+ printf("\nout: ");
+ for (i = 0; i < tempmax-tempmin; i++)
+ if (TESTBIT(out[bb->bbnum], i))
+ printf("%d ", i+tempmin);
+ printf("\n");
+ }
+ }
+#endif
+
+ DLIST_FOREACH(bb, &bblocks, bbelem) {
+ RDEBUG(("liveadd bb %d\n", bb->bbnum));
+ i = bb->bbnum;
+ for (j = 0; j < (tempmax-tempmin); j += NUMBITS)
+ live[j/NUMBITS] = 0;
+ SETCOPY(live, out[i], j, nbits);
+ for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
+ if (ip->type == IP_NODE)
+ insnwalk(ip->ip_node);
+ if (ip == bb->first)
+ break;
+ }
+ }
+
+#ifdef PCC_DEBUG
+ if (rdebug) {
+ int i;
+ struct AdjSet *w;
+ ADJL *x;
+ REGW *y;
+ MOVL *m;
+
+ printf("Interference edges\n");
+ for (i = 0; i < 256; i++) {
+ if ((w = edgehash[i]) == NULL)
+ continue;
+ for (; w; w = w->next)
+ printf("%d <-> %d\n", ASGNUM(w->u), ASGNUM(w->v));
+ }
+ printf("Degrees\n");
+ DLIST_FOREACH(y, &initial, link) {
+ printf("%d (%c): trivial [%d] ", ASGNUM(y),
+ CLASS(y)+'@', trivially_colorable(y));
+ for (x = ADJLIST(y); x; x = x->r_next) {
+ if (ONLIST(x->a_temp) != &selectStack &&
+ ONLIST(x->a_temp) != &coalescedNodes)
+ printf("%d ", ASGNUM(x->a_temp));
+ else
+ printf("(%d) ", ASGNUM(x->a_temp));
+ }
+ printf("\n");
+ }
+ printf("Move nodes\n");
+ DLIST_FOREACH(y, &initial, link) {
+ if (MOVELIST(y) == NULL)
+ continue;
+ printf("%d: ", ASGNUM(y));
+ for (m = MOVELIST(y); m; m = m->next) {
+ REGW *yy = m->regm->src == y ?
+ m->regm->dst : m->regm->src;
+ printf("%d ", ASGNUM(yy));
+ }
+ printf("\n");
+ }
+ }
+#endif
+
+}
+
+static void
+EnableMoves(REGW *n)
+{
+ MOVL *l;
+ REGM *m;
+
+ for (l = MOVELIST(n); l; l = l->next) {
+ m = l->regm;
+ if (m->queue != ACTIVE)
+ continue;
+ DLIST_REMOVE(m, link);
+ PUSHMLIST(m, worklistMoves, WLIST);
+ }
+}
+
+static void
+EnableAdjMoves(REGW *nodes)
+{
+ ADJL *w;
+ REGW *n;
+
+ EnableMoves(nodes);
+ for (w = ADJLIST(nodes); w; w = w->r_next) {
+ n = w->a_temp;
+ if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
+ continue;
+ EnableMoves(w->a_temp);
+ }
+}
+
+/*
+ * Decrement the degree of node w for class c.
+ */
+static void
+DecrementDegree(REGW *w, int c)
+{
+ int wast;
+
+ RRDEBUG(("DecrementDegree: w %d, c %d\n", ASGNUM(w), c));
+
+ wast = trivially_colorable(w);
+ NCLASS(w, c)--;
+ if (wast == trivially_colorable(w))
+ return;
+
+ EnableAdjMoves(w);
+ DELWLIST(w);
+ ONLIST(w) = 0;
+ if (MoveRelated(w)) {
+ PUSHWLIST(w, freezeWorklist);
+ } else {
+ PUSHWLIST(w, simplifyWorklist);
+ }
+}
+
+static void
+Simplify(void)
+{
+ REGW *w;
+ ADJL *l;
+
+ w = POPWLIST(simplifyWorklist);
+ PUSHWLIST(w, selectStack);
+ RDEBUG(("Simplify: node %d class %d\n", ASGNUM(w), w->r_class));
+
+ l = w->r_adjList;
+ for (; l; l = l->r_next) {
+ if (ONLIST(l->a_temp) == &selectStack ||
+ ONLIST(l->a_temp) == &coalescedNodes)
+ continue;
+ DecrementDegree(l->a_temp, w->r_class);
+ }
+}
+
+static REGW *
+GetAlias(REGW *n)
+{
+ if (ONLIST(n) == &coalescedNodes)
+ return GetAlias(ALIAS(n));
+ return n;
+}
+
+static int
+OK(REGW *t, REGW *r)
+{
+ RDEBUG(("OK: t %d CLASS(t) %d adjSet(%d,%d)=%d\n",
+ ASGNUM(t), CLASS(t), ASGNUM(t), ASGNUM(r), adjSet(t, r)));
+
+#ifdef PCC_DEBUG
+ if (rdebug > 1) {
+ ADJL *w;
+ int ndeg = 0;
+ printf("OK degree: ");
+ for (w = ADJLIST(t); w; w = w->r_next) {
+ if (ONLIST(w->a_temp) != &selectStack &&
+ ONLIST(w->a_temp) != &coalescedNodes)
+ printf("%c%d ", CLASS(w->a_temp)+'@',
+ ASGNUM(w->a_temp)), ndeg++;
+ else
+ printf("(%d) ", ASGNUM(w->a_temp));
+ }
+ printf("\n");
+#if 0
+ if (ndeg != DEGREE(t) && DEGREE(t) >= 0)
+ printf("!!!ndeg %d != DEGREE(t) %d\n", ndeg, DEGREE(t));
+#endif
+ }
+#endif
+
+ if (trivially_colorable(t) || ONLIST(t) == &precolored ||
+ (adjSet(t, r) || !aliasmap(CLASS(t), COLOR(r))))/* XXX - check aliasmap */
+ return 1;
+ return 0;
+}
+
+static int
+adjok(REGW *v, REGW *u)
+{
+ ADJL *w;
+ REGW *t;
+
+ RDEBUG(("adjok\n"));
+ for (w = ADJLIST(v); w; w = w->r_next) {
+ t = w->a_temp;
+ if (ONLIST(t) == &selectStack || ONLIST(t) == &coalescedNodes)
+ continue;
+ if (OK(t, u) == 0)
+ return 0;
+ }
+ RDEBUG(("adjok returns OK\n"));
+ return 1;
+}
+
+#define oldcons /* check some more */
+/*
+ * Do a conservative estimation of whether two temporaries can
+ * be coalesced. This is "Briggs-style" check.
+ * Neither u nor v is precolored when called.
+ */
+static int
+Conservative(REGW *u, REGW *v)
+{
+ ADJL *w, *ww;
+ REGW *n;
+#ifdef oldcons
+ int i, ncl[NUMCLASS+1];
+
+ if (CLASS(u) != CLASS(v))
+ comperr("Conservative: u(%d = %d), v(%d = %d)",
+ ASGNUM(u), CLASS(u), ASGNUM(v), CLASS(v));
+
+ for (i = 0; i < NUMCLASS+1; i++)
+ ncl[i] = 0;
+
+ RDEBUG(("Conservative (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
+
+ for (w = ADJLIST(u); w; w = w->r_next) {
+ n = w->a_temp;
+ if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
+ continue;
+ for (ww = ADJLIST(v); ww; ww = ww->r_next)
+ if (ww->a_temp == n)
+ break;
+ if (ww)
+ continue;
+ if (!trivially_colorable(n))
+ ncl[CLASS(n)]++;
+ }
+ for (w = ADJLIST(v); w; w = w->r_next) {
+ n = w->a_temp;
+ if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
+ continue;
+ if (!trivially_colorable(n))
+ ncl[CLASS(n)]++;
+ }
+ i = trivially_colorable_p(CLASS(u), ncl);
+#endif
+{
+ int xncl[NUMCLASS+1], mcl = 0, j;
+ for (j = 0; j < NUMCLASS+1; j++)
+ xncl[j] = 0;
+ /*
+ * Increment xncl[class] up to K for each class.
+ * If all classes has reached K then check colorability and return.
+ */
+ for (w = ADJLIST(u); w; w = w->r_next) {
+ n = w->a_temp;
+ if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
+ continue;
+ if (xncl[CLASS(n)] == regK[CLASS(n)])
+ continue;
+ if (!trivially_colorable(n))
+ xncl[CLASS(n)]++;
+ if (xncl[CLASS(n)] < regK[CLASS(n)])
+ continue;
+ if (++mcl == NUMCLASS)
+ goto out; /* cannot get more out of it */
+ }
+ for (w = ADJLIST(v); w; w = w->r_next) {
+ n = w->a_temp;
+ if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
+ continue;
+ if (xncl[CLASS(n)] == regK[CLASS(n)])
+ continue;
+ /* ugly: have we been here already? */
+ for (ww = ADJLIST(u); ww; ww = ww->r_next)
+ if (ww->a_temp == n)
+ break;
+ if (ww)
+ continue;
+ if (!trivially_colorable(n))
+ xncl[CLASS(n)]++;
+ if (xncl[CLASS(n)] < regK[CLASS(n)])
+ continue;
+ if (++mcl == NUMCLASS)
+ break;
+ }
+out: j = trivially_colorable_p(CLASS(u), xncl);
+#ifdef oldcons
+ if (j != i)
+ comperr("Conservative: j %d i %d", j, i);
+#else
+ return j;
+#endif
+}
+#ifdef oldcons
+ RDEBUG(("Conservative i=%d\n", i));
+ return i;
+#endif
+}
+
+static void
+AddWorkList(REGW *w)
+{
+
+ if (ONLIST(w) != &precolored && !MoveRelated(w) &&
+ trivially_colorable(w)) {
+ DELWLIST(w);
+ PUSHWLIST(w, simplifyWorklist);
+ }
+}
+
+static void
+Combine(REGW *u, REGW *v)
+{
+ MOVL *m;
+ ADJL *l;
+ REGW *t;
+
+ RDEBUG(("Combine (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
+
+ if (ONLIST(v) == &freezeWorklist) {
+ DELWLIST(v);
+ } else {
+ DELWLIST(v);
+ }
+ PUSHWLIST(v, coalescedNodes);
+ ALIAS(v) = u;
+ if (rdebug) {
+ printf("adjlist(%d): ", ASGNUM(v));
+ for (l = ADJLIST(v); l; l = l->r_next)
+ printf("%d ", l->a_temp->nodnum);
+ printf("\n");
+ }
+#if 1
+{
+ MOVL *m0 = MOVELIST(v);
+
+ for (m0 = MOVELIST(v); m0; m0 = m0->next) {
+ for (m = MOVELIST(u); m; m = m->next)
+ if (m->regm == m0->regm)
+ break; /* Already on list */
+ if (m)
+ continue; /* already on list */
+ MOVELISTADD(u, m0->regm);
+ }
+}
+#else
+
+ if ((m = MOVELIST(u))) {
+ while (m->next)
+ m = m->next;
+ m->next = MOVELIST(v);
+ } else
+ MOVELIST(u) = MOVELIST(v);
+#endif
+ EnableMoves(v);
+ for (l = ADJLIST(v); l; l = l->r_next) {
+ t = l->a_temp;
+ if (ONLIST(t) == &selectStack || ONLIST(t) == &coalescedNodes)
+ continue;
+ /* Do not add edge if u cannot affect the colorability of t */
+ /* XXX - check aliasmap */
+ if (ONLIST(u) != &precolored || aliasmap(CLASS(t), COLOR(u)))
+ AddEdge(t, u);
+ DecrementDegree(t, CLASS(v));
+ }
+ if (!trivially_colorable(u) && ONLIST(u) == &freezeWorklist) {
+ DELWLIST(u);
+ PUSHWLIST(u, spillWorklist);
+ }
+if (rdebug) {
+ ADJL *w;
+ printf("Combine %d class (%d): ", ASGNUM(u), CLASS(u));
+ for (w = ADJLIST(u); w; w = w->r_next) {
+ if (ONLIST(w->a_temp) != &selectStack &&
+ ONLIST(w->a_temp) != &coalescedNodes)
+ printf("%d ", ASGNUM(w->a_temp));
+ else
+ printf("(%d) ", ASGNUM(w->a_temp));
+ }
+ printf("\n");
+}
+}
+
+static void
+Coalesce(void)
+{
+ REGM *m;
+ REGW *x, *y, *u, *v;
+
+ m = POPMLIST(worklistMoves);
+ x = GetAlias(m->src);
+ y = GetAlias(m->dst);
+
+ if (ONLIST(y) == &precolored)
+ u = y, v = x;
+ else
+ u = x, v = y;
+
+ RDEBUG(("Coalesce: src %d dst %d u %d v %d x %d y %d\n",
+ ASGNUM(m->src), ASGNUM(m->dst), ASGNUM(u), ASGNUM(v),
+ ASGNUM(x), ASGNUM(y)));
+
+ if (CLASS(m->src) != CLASS(m->dst))
+ comperr("Coalesce: src class %d, dst class %d",
+ CLASS(m->src), CLASS(m->dst));
+
+ if (u == v) {
+ RDEBUG(("Coalesce: u == v\n"));
+ PUSHMLIST(m, coalescedMoves, COAL);
+ AddWorkList(u);
+ } else if (ONLIST(v) == &precolored || adjSet(u, v)) {
+ RDEBUG(("Coalesce: constrainedMoves\n"));
+ PUSHMLIST(m, constrainedMoves, CONSTR);
+ AddWorkList(u);
+ AddWorkList(v);
+ } else if ((ONLIST(u) == &precolored && adjok(v, u)) ||
+ (ONLIST(u) != &precolored && Conservative(u, v))) {
+ RDEBUG(("Coalesce: Conservative\n"));
+ PUSHMLIST(m, coalescedMoves, COAL);
+ Combine(u, v);
+ AddWorkList(u);
+ } else {
+ RDEBUG(("Coalesce: activeMoves\n"));
+ PUSHMLIST(m, activeMoves, ACTIVE);
+ }
+}
+
+static void
+FreezeMoves(REGW *u)
+{
+ MOVL *w, *o;
+ REGM *m;
+ REGW *z;
+ REGW *x, *y, *v;
+
+ for (w = MOVELIST(u); w; w = w->next) {
+ m = w->regm;
+ if (m->queue != WLIST && m->queue != ACTIVE)
+ continue;
+ x = m->src;
+ y = m->dst;
+ if (GetAlias(y) == GetAlias(u))
+ v = GetAlias(x);
+ else
+ v = GetAlias(y);
+ RDEBUG(("FreezeMoves: u %d (%d,%d) v %d\n",
+ ASGNUM(u),ASGNUM(x),ASGNUM(y),ASGNUM(v)));
+ DLIST_REMOVE(m, link);
+ PUSHMLIST(m, frozenMoves, FROZEN);
+ if (ONLIST(v) != &freezeWorklist)
+ continue;
+ for (o = MOVELIST(v); o; o = o->next)
+ if (o->regm->queue == WLIST || o->regm->queue == ACTIVE)
+ break;
+ if (o == NULL) {
+ z = v;
+ DELWLIST(z);
+ PUSHWLIST(z, simplifyWorklist);
+ }
+ }
+}
+
+static void
+Freeze(void)
+{
+ REGW *u;
+
+ /* XXX
+ * Should check if the moves to freeze have exactly the same
+ * interference edges. If they do, coalesce them instead, it
+ * may free up other nodes that they interfere with.
+ */
+ u = POPWLIST(freezeWorklist);
+ PUSHWLIST(u, simplifyWorklist);
+ RDEBUG(("Freeze %d\n", ASGNUM(u)));
+ FreezeMoves(u);
+}
+
+static void
+SelectSpill(void)
+{
+ REGW *w;
+
+ RDEBUG(("SelectSpill\n"));
+ if (rdebug)
+ DLIST_FOREACH(w, &spillWorklist, link)
+ printf("SelectSpill: %d\n", ASGNUM(w));
+
+ /* First check if we can spill register variables */
+ DLIST_FOREACH(w, &spillWorklist, link) {
+ if (w >= &nblock[tempmin] && w < &nblock[basetemp])
+ break;
+ }
+
+ if (w == &spillWorklist) {
+ /* try to find another long-range variable */
+ DLIST_FOREACH(w, &spillWorklist, link) {
+ if (w >= &nblock[tempmin] && w < &nblock[tempmax])
+ break;
+ }
+ }
+
+ if (w == &spillWorklist) {
+ /* no heuristics, just fetch first element */
+ w = DLIST_NEXT(&spillWorklist, link);
+ }
+
+ DLIST_REMOVE(w, link);
+
+ PUSHWLIST(w, simplifyWorklist);
+ RDEBUG(("Freezing node %d\n", ASGNUM(w)));
+ FreezeMoves(w);
+}
+
+int gregn(REGW *);
+
+int
+gregn(REGW *w)
+{
+ return w->nodnum;
+}
+
+/*
+ * Set class on long-lived temporaries based on its type.
+ */
+static void
+traclass(NODE *p)
+{
+ REGW *nb;
+
+ if (p->n_op != TEMP)
+ return;
+
+ nb = &nblock[(int)p->n_lval];
+ if (CLASS(nb) == 0)
+ CLASS(nb) = gclass(p->n_type);
+}
+
+static void
+paint(NODE *p)
+{
+ struct optab *q;
+ REGW *w, *ww;
+ int i;
+
+ if (p->n_regw != NULL) {
+ /* Must color all allocated regs also */
+ ww = w = p->n_regw;
+ q = &table[TBLIDX(p->n_su)];
+ p->n_reg = COLOR(w);
+ w++;
+ if (q->needs & ALLNEEDS)
+ for (i = 0; i < ncnt(q->needs); i++) {
+ if (w->r_class == -1)
+ p->n_reg |= ENCRA(COLOR(ww), i);
+ else
+ p->n_reg |= ENCRA(COLOR(w), i);
+ w++;
+ }
+ } else
+ p->n_reg = -1;
+ if (p->n_op == TEMP) {
+ REGW *nb = &nblock[(int)p->n_lval];
+ p->n_rval = COLOR(nb);
+ if (TCLASS(p->n_su) == 0)
+ SCLASS(p->n_su, CLASS(nb));
+ p->n_op = REG;
+ p->n_lval = 0;
+ }
+}
+
+static void
+AssignColors(struct interpass *ip)
+{
+ int okColors, c;
+ REGW *o, *w;
+ ADJL *x;
+
+ RDEBUG(("AssignColors\n"));
+ while (!WLISTEMPTY(selectStack)) {
+ w = POPWLIST(selectStack);
+ okColors = classmask(CLASS(w));
+ RDEBUG(("classmask av %d, class %d: %x\n",
+ w->nodnum, CLASS(w), okColors));
+
+ for (x = ADJLIST(w); x; x = x->r_next) {
+ o = GetAlias(x->a_temp);
+ RRDEBUG(("Adj(%d): %d (%d)\n",
+ ASGNUM(w), ASGNUM(o), ASGNUM(x->a_temp)));
+
+ if (ONLIST(o) == &coloredNodes ||
+ ONLIST(o) == &precolored) {
+ c = aliasmap(CLASS(w), COLOR(o));
+ RRDEBUG(("aliasmap in class %d by color %d: "
+ "%x, okColors %x\n",
+ CLASS(w), COLOR(o), c, okColors));
+
+ okColors &= ~c;
+ }
+ }
+ if (okColors == 0) {
+ PUSHWLIST(w, spilledNodes);
+ RDEBUG(("Spilling node %d\n", ASGNUM(w)));
+ } else {
+ PUSHWLIST(w, coloredNodes);
+ c = ffs(okColors)-1;
+ COLOR(w) = color2reg(c, CLASS(w));
+ RDEBUG(("Coloring %d with %s, free %x\n",
+ ASGNUM(w), rnames[COLOR(w)], okColors));
+ }
+ }
+ DLIST_FOREACH(w, &coalescedNodes, link) {
+ REGW *ww = GetAlias(w);
+ COLOR(w) = COLOR(ww);
+ if (ONLIST(ww) == &spilledNodes) {
+ RDEBUG(("coalesced node %d spilled\n", w->nodnum));
+ ww = DLIST_PREV(w, link);
+ DLIST_REMOVE(w, link);
+ PUSHWLIST(w, spilledNodes);
+ w = ww;
+ } else
+ RDEBUG(("Giving coalesced node %d color %s\n",
+ w->nodnum, rnames[COLOR(w)]));
+ }
+
+ if (rdebug)
+ DLIST_FOREACH(w, &coloredNodes, link)
+ printf("%d: color %s\n", ASGNUM(w), rnames[COLOR(w)]);
+ if (DLIST_ISEMPTY(&spilledNodes, link)) {
+ struct interpass *ip2;
+ DLIST_FOREACH(ip2, ip, qelem)
+ if (ip2->type == IP_NODE)
+ walkf(ip2->ip_node, paint);
+ }
+}
+
+static REGW *spole;
+/*
+ * Store all spilled nodes in memory by fetching a temporary on the stack.
+ * Will never end up here if not optimizing.
+ */
+static void
+longtemp(NODE *p)
+{
+ REGW *w;
+
+ if (p->n_op != TEMP)
+ return;
+ /* XXX - should have a bitmask to find temps to convert */
+ DLIST_FOREACH(w, spole, link) {
+ if (w != &nblock[(int)p->n_lval])
+ continue;
+ if (w->r_class == 0) {
+ w->r_color = BITOOR(freetemp(szty(p->n_type)));
+ w->r_class = 1;
+ }
+ p->n_op = OREG;
+ p->n_lval = w->r_color;
+ p->n_rval = FPREG;
+ p->n_regw = NULL;
+ break;
+ }
+}
+
+static struct interpass *cip;
+/*
+ * Rewrite a tree by storing a variable in memory.
+ * XXX - must check if basic block structure is destroyed!
+ */
+static void
+shorttemp(NODE *p)
+{
+ struct interpass *nip;
+ REGW *w;
+ NODE *l, *r;
+ int off;
+
+ /* XXX - optimize this somewhat */
+ DLIST_FOREACH(w, spole, link) {
+ if (w != p->n_regw)
+ continue;
+ /* XXX - use canaddr() */
+ if (p->n_op == OREG || p->n_op == NAME) {
+ DLIST_REMOVE(w, link);
+ RDEBUG(("Node %d already in memory\n", ASGNUM(w)));
+ break;
+ }
+ RDEBUG(("rewriting node %d\n", ASGNUM(w)));
+ off = BITOOR(freetemp(szty(p->n_type)));
+ l = mklnode(OREG, off, FPREG, p->n_type);
+ r = talloc();
+ *r = *p;
+ nip = ipnode(mkbinode(ASSIGN, l, r, p->n_type));
+ *p = *l;
+ DLIST_INSERT_BEFORE(cip, nip, qelem);
+ DLIST_REMOVE(w, link);
+ break;
+ }
+}
+
+/*
+ * Change the TEMPs in the ipole list to stack variables.
+ */
+static void
+treerewrite(struct interpass *ipole, REGW *rpole)
+{
+ struct interpass *ip;
+
+ spole = rpole;
+
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ cip = ip;
+ walkf(ip->ip_node, shorttemp); /* convert temps to oregs */
+ }
+ if (!DLIST_ISEMPTY(spole, link))
+ comperr("treerewrite not empty");
+}
+
+/*
+ * Change the TEMPs in the ipole list to stack variables.
+ */
+static void
+leafrewrite(struct interpass *ipole, REGW *rpole)
+{
+ extern NODE *nodepole;
+ extern int thisline;
+ struct interpass *ip;
+
+ spole = rpole;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ nodepole = ip->ip_node;
+ thisline = ip->lineno;
+ walkf(ip->ip_node, longtemp); /* convert temps to oregs */
+ }
+ nodepole = NIL;
+}
+
+/*
+ * Avoid copying spilled argument to new position on stack.
+ */
+static int
+temparg(struct interpass *ipole, REGW *w)
+{
+ struct interpass *ip;
+ NODE *p;
+
+ ip = DLIST_NEXT(ipole, qelem); /* PROLOG */
+ ip = DLIST_NEXT(ip, qelem); /* first DEFLAB */
+ ip = DLIST_NEXT(ip, qelem); /* first NODE */
+ for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
+ if (ip->type == IP_ASM)
+ continue;
+ p = ip->ip_node;
+#ifdef PCC_DEBUG
+ if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
+ comperr("temparg");
+#endif
+ if (p->n_right->n_op != OREG)
+ continue; /* arg in register */
+ if (w != &nblock[(int)p->n_left->n_lval])
+ continue;
+ w->r_color = p->n_right->n_lval;
+ tfree(p);
+ /* Cannot DLIST_REMOVE here, would break basic blocks */
+ /* Make it a nothing instead */
+ ip->type = IP_ASM;
+ ip->ip_asm="";
+ return 1;
+ }
+ return 0;
+}
+
+#define ONLYPERM 1
+#define LEAVES 2
+#define SMALL 3
+
+/*
+ * Scan the whole function and search for temporaries to be stored
+ * on-stack.
+ *
+ * Be careful to not destroy the basic block structure in the first scan.
+ */
+static int
+RewriteProgram(struct interpass *ip)
+{
+ REGW shortregs, longregs, saveregs, *q;
+ REGW *w;
+ int rwtyp;
+
+ RDEBUG(("RewriteProgram\n"));
+ DLIST_INIT(&shortregs, link);
+ DLIST_INIT(&longregs, link);
+ DLIST_INIT(&saveregs, link);
+
+ /* sort the temporaries in three queues, short, long and perm */
+ while (!DLIST_ISEMPTY(&spilledNodes, link)) {
+ w = DLIST_NEXT(&spilledNodes, link);
+ DLIST_REMOVE(w, link);
+
+ if (w >= &nblock[tempmin] && w < &nblock[basetemp]) {
+ q = &saveregs;
+ } else if (w >= &nblock[basetemp] && w < &nblock[tempmax]) {
+ q = &longregs;
+ } else
+ q = &shortregs;
+ DLIST_INSERT_AFTER(q, w, link);
+ }
+#ifdef PCC_DEBUG
+ if (rdebug) {
+ printf("permanent: ");
+ DLIST_FOREACH(w, &saveregs, link)
+ printf("%d ", ASGNUM(w));
+ printf("\nlong-lived: ");
+ DLIST_FOREACH(w, &longregs, link)
+ printf("%d ", ASGNUM(w));
+ printf("\nshort-lived: ");
+ DLIST_FOREACH(w, &shortregs, link)
+ printf("%d ", ASGNUM(w));
+ printf("\n");
+ }
+#endif
+ rwtyp = 0;
+
+ if (!DLIST_ISEMPTY(&saveregs, link)) {
+ rwtyp = ONLYPERM;
+ DLIST_FOREACH(w, &saveregs, link) {
+ int num = w - nblock - tempmin;
+ nsavregs[num] = 1;
+ }
+ }
+ if (!DLIST_ISEMPTY(&longregs, link)) {
+ rwtyp = LEAVES;
+ DLIST_FOREACH(w, &longregs, link) {
+ w->r_class = xtemps ? temparg(ip, w) : 0;
+ }
+ }
+
+ if (rwtyp == LEAVES) {
+ leafrewrite(ip, &longregs);
+ rwtyp = ONLYPERM;
+ }
+
+ if (rwtyp == 0 && !DLIST_ISEMPTY(&shortregs, link)) {
+ /* Must rewrite the trees */
+ treerewrite(ip, &shortregs);
+// if (xtemps)
+// comperr("treerewrite");
+ rwtyp = SMALL;
+ }
+
+ RDEBUG(("savregs %x rwtyp %d\n", 0, rwtyp));
+
+ return rwtyp;
+}
+
+#ifdef notyet
+/*
+ * Assign instructions, calculate evaluation order and
+ * set temporary register numbers.
+ */
+static void
+insgen()
+{
+ geninsn(); /* instruction assignment */
+ sucomp(); /* set evaluation order */
+ slong(); /* set long temp types */
+ sshort(); /* set short temp numbers */
+}
+#endif
+
+/*
+ * Do register allocation for trees by graph-coloring.
+ */
+void
+ngenregs(struct interpass *ipole)
+{
+ extern NODE *nodepole;
+ struct interpass_prolog *ipp, *epp;
+ struct interpass *ip;
+ int i, j, nbits = 0;
+ int uu[NPERMREG] = { -1 };
+ int xnsavregs[NPERMREG];
+ int beenhere = 0;
+
+ DLIST_INIT(&lunused, link);
+ DLIST_INIT(&lused, link);
+
+ /*
+ * Do some setup before doing the real thing.
+ */
+ ipp = (struct interpass_prolog *)DLIST_NEXT(ipole, qelem);
+ epp = (struct interpass_prolog *)DLIST_PREV(ipole, qelem);
+
+ tempmin = ipp->ip_tmpnum;
+ tempmax = epp->ip_tmpnum;
+
+ /*
+ * Allocate space for the permanent registers in the
+ * same block as the long-lived temporaries.
+ * These temporaries will be handled the same way as
+ * all other variables.
+ */
+ basetemp = tempmin;
+ nsavregs = xnsavregs;
+ for (i = 0; i < NPERMREG; i++)
+ xnsavregs[i] = 0;
+ ndontregs = uu; /* currently never avoid any regs */
+
+ tempmin -= (NPERMREG-1);
+#ifdef notyet
+ if (xavoidfp)
+ dontregs |= REGBIT(FPREG);
+#endif
+
+#ifdef PCC_DEBUG
+ nodnum = tempmax;
+#endif
+ nbits = xbits = tempmax - tempmin;
+ if (nbits) {
+ nblock = tmpalloc(nbits * sizeof(REGW));
+
+ nblock -= tempmin;
+ live = tmpalloc(BIT2BYTE(nbits));
+ RDEBUG(("nblock %p num %d size %d\n",
+ nblock, nbits, (int)(nbits * sizeof(REGW))));
+ }
+
+
+ /* Block for precolored nodes */
+ ablock = tmpalloc(sizeof(REGW)*MAXREGS);
+ memset(ablock, 0, sizeof(REGW)*MAXREGS);
+ for (i = 0; i < MAXREGS; i++) {
+ ablock[i].r_onlist = &precolored;
+ ablock[i].r_class = GCLASS(i); /* XXX */
+ ablock[i].r_color = i;
+#ifdef PCC_DEBUG
+ ablock[i].nodnum = i;
+#endif
+ }
+#ifdef notyet
+ TMPMARK();
+#endif
+
+
+recalc:
+onlyperm: /* XXX - should not have to redo all */
+
+ if (nbits) {
+ memset(nblock+tempmin, 0, nbits * sizeof(REGW));
+ memset(live, 0, BIT2BYTE(nbits));
+ memset(edgehash, 0, sizeof(edgehash));
+#ifdef PCC_DEBUG
+ for (i = tempmin; i < tempmax; i++)
+ nblock[i].nodnum = i;
+#endif
+ }
+ RPRINTIP(ipole);
+ DLIST_INIT(&initial, link);
+ DLIST_FOREACH(ip, ipole, qelem) {
+ extern int thisline;
+ if (ip->type != IP_NODE)
+ continue;
+ nodepole = ip->ip_node;
+ thisline = ip->lineno;
+ geninsn(ip->ip_node, FOREFF);
+ nsucomp(ip->ip_node);
+ walkf(ip->ip_node, traclass);
+ }
+ nodepole = NIL;
+ RDEBUG(("nsucomp allocated %d temps (%d,%d)\n",
+ tempmax-tempmin, tempmin, tempmax));
+
+ RPRINTIP(ipole);
+ RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin,
+ tempmin, tempmax));
+
+ DLIST_INIT(&coalescedMoves, link);
+ DLIST_INIT(&constrainedMoves, link);
+ DLIST_INIT(&frozenMoves, link);
+ DLIST_INIT(&worklistMoves, link);
+ DLIST_INIT(&activeMoves, link);
+
+ /* Set class and move-related for perm regs */
+ for (i = 0; i < (NPERMREG-1); i++) {
+ if (nsavregs[i])
+ continue;
+ nblock[i+tempmin].r_class = GCLASS(permregs[i]);
+ DLIST_INSERT_AFTER(&initial, &nblock[i+tempmin], link);
+ moveadd(&nblock[i+tempmin], &ablock[permregs[i]]);
+ addalledges(&nblock[i+tempmin]);
+ }
+
+ Build(ipole);
+ RDEBUG(("Build done\n"));
+ MkWorklist();
+ RDEBUG(("MkWorklist done\n"));
+ do {
+ if (!WLISTEMPTY(simplifyWorklist))
+ Simplify();
+ else if (!WLISTEMPTY(worklistMoves))
+ Coalesce();
+ else if (!WLISTEMPTY(freezeWorklist))
+ Freeze();
+ else if (!WLISTEMPTY(spillWorklist))
+ SelectSpill();
+ } while (!WLISTEMPTY(simplifyWorklist) || !WLISTEMPTY(worklistMoves) ||
+ !WLISTEMPTY(freezeWorklist) || !WLISTEMPTY(spillWorklist));
+ AssignColors(ipole);
+
+ RDEBUG(("After AssignColors\n"));
+ RPRINTIP(ipole);
+
+ if (!WLISTEMPTY(spilledNodes)) {
+ switch (RewriteProgram(ipole)) {
+ case ONLYPERM:
+ goto onlyperm;
+ case SMALL:
+ optimize(ipole);
+ if (beenhere++ == MAXLOOP)
+ comperr("beenhere");
+ goto recalc;
+ }
+ }
+
+ /* fill in regs to save */
+ ipp->ipp_regs = 0;
+ for (i = 0; i < NPERMREG-1; i++) {
+ NODE *p;
+
+ if (nsavregs[i]) {
+ ipp->ipp_regs |= (1 << permregs[i]);
+ continue; /* Spilled */
+ }
+ if (nblock[i+tempmin].r_color == permregs[i])
+ continue; /* Coalesced */
+ /*
+ * If the original color of this permreg is used for
+ * coloring another register, swap them to avoid
+ * unneccessary moves.
+ */
+ for (j = i+1; j < NPERMREG-1; j++) {
+ if (nblock[j+tempmin].r_color != permregs[i])
+ continue;
+ nblock[j+tempmin].r_color = nblock[i+tempmin].r_color;
+ break;
+ }
+ if (j != NPERMREG-1)
+ continue;
+
+ /* Generate reg-reg move nodes for save */
+ p = mkbinode(ASSIGN,
+ mklnode(REG, 0, nblock[i+tempmin].r_color, INT),
+ mklnode(REG, 0, permregs[i], INT), INT);
+ p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
+ p->n_left->n_su = p->n_right->n_su = 0;
+ geninsn(p, FOREFF);
+ ip = ipnode(p);
+ DLIST_INSERT_AFTER(ipole->qelem.q_forw, ip, qelem);
+ /* XXX not int */
+ p = mkbinode(ASSIGN, mklnode(REG, 0, permregs[i], INT),
+ mklnode(REG, 0, nblock[i+tempmin].r_color, INT), INT);
+ p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
+ p->n_left->n_su = p->n_right->n_su = 0;
+ geninsn(p, FOREFF);
+ ip = ipnode(p);
+ DLIST_INSERT_BEFORE(ipole->qelem.q_back, ip, qelem);
+ }
+ epp->ipp_regs = ipp->ipp_regs;
+ /* Done! */
+}
diff --git a/usr.bin/pcc/os/dragonfly/ccconfig.h b/usr.bin/pcc/os/dragonfly/ccconfig.h
new file mode 100644
index 00000000000..08afb5fe161
--- /dev/null
+++ b/usr.bin/pcc/os/dragonfly/ccconfig.h
@@ -0,0 +1,47 @@
+/* $Id: ccconfig.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/* common cpp predefines */
+#define CPPADD { "-D__DragonFly__", "-D__ELF__", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.elf_so.2", NULL }
+#define CRT0FILE "/usr/lib/crt1.o"
+#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/crtbegin.o", NULL }
+#define ENDFILES { "/usr/lib/crtend.o", "/usr/lib/crtn.o", NULL }
+
+#if defined(mach_x86)
+#define CPPMDADD { "-D__i386__", NULL, }
+#else
+#error defines for arch missing
+#endif
+
+#define STABS
diff --git a/usr.bin/pcc/os/linux/ccconfig.h b/usr.bin/pcc/os/linux/ccconfig.h
new file mode 100644
index 00000000000..41cb8b83455
--- /dev/null
+++ b/usr.bin/pcc/os/linux/ccconfig.h
@@ -0,0 +1,49 @@
+/* $Id: ccconfig.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/* common cpp predefines */
+#define CPPADD { "-D__linux__", "-D__ELF__", "-I" INCLUDEDIR "/pcc", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/lib/ld-linux.so.2", NULL }
+#define CRT0FILE "/usr/lib/crt1.o"
+#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/gcc/i586-suse-linux/4.1.0/crtbegin.o", NULL }
+#define LIBCLIBS { "-lc", "-lgcc_s", NULL }
+#define ENDFILES { "/usr/lib/gcc/i586-suse-linux/4.1.0/crtend.o", "/usr/lib/crtn.o", NULL }
+#define STARTLABEL "_start"
+
+#if defined(mach_x86)
+#define CPPMDADD { "-D__i386__", NULL, }
+#else
+#error defines for arch missing
+#endif
+
+#define STABS
diff --git a/usr.bin/pcc/os/netbsd/ccconfig.h b/usr.bin/pcc/os/netbsd/ccconfig.h
new file mode 100644
index 00000000000..f0eecd3b704
--- /dev/null
+++ b/usr.bin/pcc/os/netbsd/ccconfig.h
@@ -0,0 +1,47 @@
+/* $Id: ccconfig.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/* common cpp predefines */
+#define CPPADD { "-D__NetBSD__", "-D__ELF__", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.elf_so", NULL }
+#define CRT0FILE "/usr/lib/crt0.o"
+#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/crtbegin.o", NULL }
+#define ENDFILES { "/usr/lib/crtend.o", "/usr/lib/crtn.o", NULL }
+
+#if defined(mach_x86)
+#define CPPMDADD { "-D__i386__", NULL, }
+#else
+#error defines for arch missing
+#endif
+
+#define STABS
diff --git a/usr.bin/pcc/os/netbsd/f77config.h b/usr.bin/pcc/os/netbsd/f77config.h
new file mode 100644
index 00000000000..6bbc447b855
--- /dev/null
+++ b/usr.bin/pcc/os/netbsd/f77config.h
@@ -0,0 +1,54 @@
+/* $Id: f77config.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the f77 compiler works.
+ */
+
+#if 0
+/* common cpp predefines */
+#define CPPADD { "-D__NetBSD__", "-D__ELF__", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.elf_so", NULL }
+#define CRT0FILE "/usr/lib/crt0.o"
+#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/crtbegin.o", NULL }
+#define ENDFILES { "/usr/lib/crtend.o", "/usr/lib/crtn.o", NULL }
+#endif
+#define PASS1NAME "/usr/lib/f77pass1"
+#define PASS2NAME "/lib/f1"
+#define PASS2OPT "/lib/c2"
+#define NOFLPASS2 "/lib/fc1"
+
+#define ASMNAME "/usr/bin/as"
+#define LDNAME "/usr/bin/ld"
+#define FOOTNAME "/usr/lib/crt0.o"
+#define PROFFOOT "/usr/lib/mcrt0.o"
+#define NOFLFOOT "/usr/lib/fcrt0.o"
+#define NOFLPROFFOOT "/usr/lib/fmcrt0.o"
+#define LIBLIST { "-lF77", "-lI77", "-lm", "-lc", "-l", NULL };
+
diff --git a/usr.bin/pcc/os/none/ccconfig.h b/usr.bin/pcc/os/none/ccconfig.h
new file mode 100644
index 00000000000..5bb3af33f42
--- /dev/null
+++ b/usr.bin/pcc/os/none/ccconfig.h
@@ -0,0 +1,50 @@
+/* $Id: ccconfig.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/*
+ * This file is for targets where there is no OS
+ */
+
+/* common cpp predefines */
+#define CPPADD { NULL, }
+#define DYNLINKER { NULL }
+#define CRT0FILE ""
+#define STARTFILES { NULL }
+#define ENDFILES { NULL }
+
+#if defined(mach_m16c)
+#define CPPMDADD { "-D__m16c__", NULL, }
+#elif defined(mach_nova)
+#define CPPMDADD { "-D__nova__", NULL, }
+#endif
+
diff --git a/usr.bin/pcc/os/openbsd/ccconfig.h b/usr.bin/pcc/os/openbsd/ccconfig.h
new file mode 100644
index 00000000000..b0962add596
--- /dev/null
+++ b/usr.bin/pcc/os/openbsd/ccconfig.h
@@ -0,0 +1,47 @@
+/* $Id: ccconfig.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/* common cpp predefines */
+#define CPPADD { "-D__OpenBSD__", "-D__ELF__", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.so", NULL }
+#define CRT0FILE "/usr/lib/crt0.o"
+#define STARTFILES { "/usr/lib/crtbegin.o", NULL }
+#define ENDFILES { "/usr/lib/crtend.o", NULL }
+
+#if defined(mach_x86)
+#define CPPMDADD { "-D__i386__", NULL, }
+#else
+#error defines for arch missing
+#endif
+
+#define STABS
diff --git a/usr.bin/pcc/os/openbsd/f77config.h b/usr.bin/pcc/os/openbsd/f77config.h
new file mode 100644
index 00000000000..8ac985d8eab
--- /dev/null
+++ b/usr.bin/pcc/os/openbsd/f77config.h
@@ -0,0 +1,46 @@
+/* $Id: f77config.h,v 1.1 2007/09/15 18:12:37 otto Exp $ */
+
+/*
+ * Copyright (c) 2004 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.
+ */
+
+/*
+ * Various settings that controls how the f77 compiler works.
+ */
+
+#define PASS1NAME "/usr/lib/f77pass1"
+#define PASS2NAME "/lib/f1"
+#define PASS2OPT "/lib/c2"
+#define NOFLPASS2 "/lib/fc1"
+
+#define ASMNAME "/usr/bin/as"
+#define LDNAME "/usr/bin/ld"
+#define FOOTNAME "/usr/lib/crt0.o"
+#define PROFFOOT "/usr/lib/mcrt0.o"
+#define NOFLFOOT "/usr/lib/fcrt0.o"
+#define NOFLPROFFOOT "/usr/lib/fmcrt0.o"
+#define LIBLIST { "-lF77", "-lI77", "-lm", "-lc", "-l", NULL };
+