summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/pcc/arm/code.c686
-rw-r--r--usr.bin/pcc/arm/local.c409
-rw-r--r--usr.bin/pcc/arm/local2.c820
-rw-r--r--usr.bin/pcc/arm/macdefs.h65
-rw-r--r--usr.bin/pcc/arm/order.c22
-rw-r--r--usr.bin/pcc/arm/table.c1389
-rw-r--r--usr.bin/pcc/cc/cc.1100
-rw-r--r--usr.bin/pcc/cc/cc.c101
-rw-r--r--usr.bin/pcc/ccconfig.h3
-rw-r--r--usr.bin/pcc/ccom/ccom.160
-rw-r--r--usr.bin/pcc/ccom/cgram.y247
-rw-r--r--usr.bin/pcc/ccom/gcc_compat.c12
-rw-r--r--usr.bin/pcc/ccom/init.c41
-rw-r--r--usr.bin/pcc/ccom/main.c14
-rw-r--r--usr.bin/pcc/ccom/optim.c4
-rw-r--r--usr.bin/pcc/ccom/pass1.h20
-rw-r--r--usr.bin/pcc/ccom/pftn.c582
-rw-r--r--usr.bin/pcc/ccom/scan.l42
-rw-r--r--usr.bin/pcc/ccom/stabs.c65
-rw-r--r--usr.bin/pcc/ccom/trees.c26
-rw-r--r--usr.bin/pcc/config.h6
-rw-r--r--usr.bin/pcc/cpp/cpp.167
-rw-r--r--usr.bin/pcc/cpp/cpp.c32
-rw-r--r--usr.bin/pcc/cpp/scanner.l48
-rw-r--r--usr.bin/pcc/hppa/code.c173
-rw-r--r--usr.bin/pcc/hppa/local.c259
-rw-r--r--usr.bin/pcc/hppa/local2.c68
-rw-r--r--usr.bin/pcc/hppa/macdefs.h2
-rw-r--r--usr.bin/pcc/hppa/order.c23
-rw-r--r--usr.bin/pcc/hppa/table.c8
-rw-r--r--usr.bin/pcc/i386/code.c9
-rw-r--r--usr.bin/pcc/i386/local.c132
-rw-r--r--usr.bin/pcc/i386/local2.c5
-rw-r--r--usr.bin/pcc/i386/macdefs.h20
-rw-r--r--usr.bin/pcc/i386/order.c13
-rw-r--r--usr.bin/pcc/i386/table.c10
-rw-r--r--usr.bin/pcc/mip/common.c22
-rw-r--r--usr.bin/pcc/mip/manifest.h6
-rw-r--r--usr.bin/pcc/mip/match.c2
-rw-r--r--usr.bin/pcc/mip/mkext.c48
-rw-r--r--usr.bin/pcc/mip/node.h11
-rw-r--r--usr.bin/pcc/mip/pass2.h4
-rw-r--r--usr.bin/pcc/mip/reader.c175
-rw-r--r--usr.bin/pcc/mip/regs.c60
-rw-r--r--usr.bin/pcc/mips/code.c69
-rw-r--r--usr.bin/pcc/mips/local.c126
-rw-r--r--usr.bin/pcc/mips/local2.c5
-rw-r--r--usr.bin/pcc/mips/macdefs.h2
-rw-r--r--usr.bin/pcc/mips/order.c2
-rw-r--r--usr.bin/pcc/mips/table.c2
-rw-r--r--usr.bin/pcc/powerpc/code.c1067
-rw-r--r--usr.bin/pcc/powerpc/local.c1130
-rw-r--r--usr.bin/pcc/powerpc/local2.c1335
-rw-r--r--usr.bin/pcc/powerpc/macdefs.h236
-rw-r--r--usr.bin/pcc/powerpc/order.c224
-rw-r--r--usr.bin/pcc/powerpc/table.c1066
-rw-r--r--usr.bin/pcc/sparc64/code.c128
-rw-r--r--usr.bin/pcc/sparc64/local.c90
-rw-r--r--usr.bin/pcc/sparc64/local2.c167
-rw-r--r--usr.bin/pcc/sparc64/macdefs.h182
-rw-r--r--usr.bin/pcc/sparc64/order.c14
-rw-r--r--usr.bin/pcc/sparc64/table.c595
62 files changed, 8673 insertions, 3678 deletions
diff --git a/usr.bin/pcc/arm/code.c b/usr.bin/pcc/arm/code.c
index 006f62d1a8e..4929b2ef0fb 100644
--- a/usr.bin/pcc/arm/code.c
+++ b/usr.bin/pcc/arm/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.2 2007/12/22 12:38:56 stefan Exp $ */
+/* $OpenBSD: code.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
@@ -36,46 +36,311 @@
#include "pass1.h"
#include "pass2.h"
+int lastloc = -1;
/*
- * Modify the alignment in the data section to become a multiple of n.
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
*/
void
-defalign(int n)
+defloc(struct symtab *sp)
{
- n /= SZCHAR;
- if (n == 1)
+ extern char *nextsect;
+ static char *loctbl[] = { "text", "data", "section .rodata" };
+ TWORD t;
+ int s;
+
+ if (sp == NULL) {
+ lastloc = -1;
return;
- printf("\t.align %d\n", n);
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? PROG : DATA;
+ if (nextsect) {
+ printf("\t.section %s\n", nextsect);
+ nextsect = NULL;
+ s = -1;
+ } else if (s != lastloc)
+ printf("\t.%s\n", loctbl[s]);
+ lastloc = s;
+ while (ISARY(t))
+ t = DECREF(t);
+ if (t > UCHAR)
+ printf("\t.align %d\n", t > USHORT ? 4 : 2);
+#ifdef USE_GAS
+ if (ISFTN(t))
+ printf("\t.type %s,%%function\n", exname(sp->soname));
+#endif
+ if (sp->sclass == EXTDEF)
+ printf("\t.global %s\n", exname(sp->soname));
+ if (ISFTN(t))
+ return;
+ if (sp->slevel == 0)
+ printf("%s:\n", exname(sp->soname));
+ else
+ printf(LABFMT ":\n", sp->soffset);
}
-/*
- * Define the current location as an internal label.
+/* Put a symbol in a temporary
+ * used by bfcode() and its helpers
*/
-void
-deflab(int label)
+static void
+putintemp(struct symtab *sym)
{
- printf(LABFMT ":\n", label);
+ NODE *p;
+
+ spname = sym;
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
+ sym->soffset = regno(p->n_left);
+ sym->sflags |= STNODE;
+ ecomp(p);
}
-/*
- * Define the current location in the data section to be the name p->sname
- */
-void
-defnam(struct symtab *p)
+/* setup a 64-bit parameter (double/ldouble/longlong)
+ * used by bfcode() */
+static void
+param_64bit(struct symtab *sym, int *argoffp, int dotemps)
{
- char *c = p->sname;
+ int argoff = *argoffp;
+ NODE *p, *q;
+ int navail;
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
+#if ALLONGLONG == 64
+ /* alignment */
+ ++argoff;
+ argoff &= ~1;
+ *argoffp = argoff;
#endif
- if (p->sclass == EXTDEF)
- printf("\t.global %s\n", exname(c));
- printf("%s:\n", exname(c));
+
+ navail = NARGREGS - argoff;
+
+ if (navail < 2) {
+ /* half in and half out of the registers */
+ if (features(FEATURE_BIGENDIAN)) {
+ cerror("movearg_64bit");
+ p = q = NULL;
+ } else {
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R0 + argoff;
+ if (dotemps) {
+ q = block(SCONV, q, NIL,
+ ULONGLONG, 0, MKSUE(ULONGLONG));
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ p->n_type = ULONGLONG;
+ p->n_df = 0;
+ p->n_sue = MKSUE(ULONGLONG);
+ p = block(LS, p, bcon(32), ULONGLONG,
+ 0, MKSUE(ULONGLONG));
+ q = block(PLUS, p, q, ULONGLONG,
+ 0, MKSUE(ULONGLONG));
+ p = tempnode(0, ULONGLONG,
+ 0, MKSUE(ULONGLONG));
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ } else {
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ regno(p) = sym->soffset;
+ p->n_type = INT;
+ p->n_df = 0;
+ p->n_sue = MKSUE(INT);
+ }
+ }
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ *argoffp = argoff + 2;
+ return;
+ }
+
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ regno(q) = R0R1 + argoff;
+ if (dotemps) {
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ } else {
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ }
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ *argoffp = argoff + 2;
+}
+
+/* setup a 32-bit param on the stack
+ * used by bfcode() */
+static void
+param_32bit(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q;
+
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ regno(q) = R0 + (*argoffp)++;
+ if (dotemps) {
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ } else {
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ }
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+}
+
+/* setup a double param on the stack
+ * used by bfcode() */
+static void
+param_double(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q, *t;
+ int tmpnr;
+
+ /*
+ * we have to dump the float from the general register
+ * into a temp, since the register allocator doesn't like
+ * floats to be in CLASSA. This may not work for -xtemps.
+ */
+
+ t = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG));
+ tmpnr = regno(t);
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ q->n_rval = R0R1 + (*argoffp)++;
+ p = buildtree(ASSIGN, t, q);
+ ecomp(p);
+
+ if (dotemps) {
+ sym->soffset = tmpnr;
+ sym->sflags |= STNODE;
+ } else {
+ q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue);
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+}
+
+/* setup a float param on the stack
+ * used by bfcode() */
+static void
+param_float(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q, *t;
+ int tmpnr;
+
+ /*
+ * we have to dump the float from the general register
+ * into a temp, since the register allocator doesn't like
+ * floats to be in CLASSA. This may not work for -xtemps.
+ */
+
+ t = tempnode(0, INT, 0, MKSUE(INT));
+ tmpnr = regno(t);
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ q->n_rval = R0 + (*argoffp)++;
+ p = buildtree(ASSIGN, t, q);
+ ecomp(p);
+
+ if (dotemps) {
+ sym->soffset = tmpnr;
+ sym->sflags |= STNODE;
+ } else {
+ q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue);
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
}
int rvnr;
/*
+ * Beginning-of-function code:
+ *
+ * 'sp' is an array of indices in symtab for the arguments
+ * 'cnt' is the number of arguments
+ */
+void
+bfcode(struct symtab **sp, int cnt)
+{
+ NODE *p, *q;
+ union arglist *usym;
+ int saveallargs = 0;
+ int i, argoff = 0;
+
+ /*
+ * Detect if this function has ellipses and save all
+ * argument registers onto stack.
+ */
+ usym = cftnsp->sdf->dfun;
+ while (usym && usym->type != TNULL) {
+ if (usym->type == TELLIPSIS) {
+ saveallargs = 1;
+ break;
+ }
+ ++usym;
+ }
+
+ /* if returning a structure, more the hidden argument into a TEMP */
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue);
+ rvnr = regno(p);
+ q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
+ q->n_rval = R0 + argoff++;
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+
+ /* recalculate the arg offset and create TEMP moves */
+ for (i = 0; i < cnt; i++) {
+
+ if ((argoff >= NARGREGS) && !xtemps) {
+ break;
+ } else if (argoff > NARGREGS) {
+ putintemp(sp[i]);
+ } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) {
+ cerror("unimplemented structure arguments");
+ } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) {
+ param_64bit(sp[i], &argoff, xtemps && !saveallargs);
+ } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) {
+ if (features(FEATURE_HARDFLOAT))
+ param_double(sp[i], &argoff,
+ xtemps && !saveallargs);
+ else
+ param_64bit(sp[i], &argoff,
+ xtemps && !saveallargs);
+ } else if (sp[i]->stype == FLOAT) {
+ if (features(FEATURE_HARDFLOAT))
+ param_float(sp[i], &argoff,
+ xtemps && !saveallargs);
+ else
+ param_32bit(sp[i], &argoff,
+ xtemps && !saveallargs);
+ } else {
+ param_32bit(sp[i], &argoff, xtemps && !saveallargs);
+ }
+ }
+
+ /* if saveallargs, save the rest of the args onto the stack */
+ while (saveallargs && argoff < NARGREGS) {
+ NODE *p, *q;
+ int off = ARGINIT/SZINT + argoff;
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R0 + argoff++;
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = FPREG;
+ p = block(PLUS, p, bcon(4*off), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+
+}
+
+/*
* End-of-Function code:
*/
void
@@ -98,7 +363,7 @@ efcode()
q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
q->n_rval = R0;
p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue);
- tempnr = p->n_lval;
+ tempnr = regno(p);
p = buildtree(ASSIGN, p, q);
ecomp(p);
@@ -116,61 +381,6 @@ efcode()
}
/*
- * Beginning-of-function code:
- *
- * 'a' is an array of indices in symtab for the arguments
- * 'n' is the number of arguments
- */
-void
-bfcode(struct symtab **sp, int cnt)
-{
- NODE *p, *q;
- int i, n, start = 0;
-
- /* if returning a structure, more the hidden argument into a TEMP */
- if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
- p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue);
- rvnr = p->n_lval;
- q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
- q->n_rval = R0 + start++;
- p = buildtree(ASSIGN, p, q);
- ecomp(p);
- }
-
- /* recalculate the arg offset and create TEMP moves */
- for (n = start, i = 0; i < cnt; i++) {
- int sz = szty(sp[i]->stype);
- if (n + sz <= 4) {
- /* put stack args in temps */
- p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
- spname = sp[i];
- q = block(REG, NIL, NIL,
- sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
- q->n_rval = (sz == 2 ? R0R1 + n : R0+n);
- p = buildtree(ASSIGN, p, q);
- sp[i]->soffset = p->n_left->n_lval;
- sp[i]->sflags |= STNODE;
- ecomp(p);
- } else {
- sp[i]->soffset -= SZINT * 4;
- if (xtemps) {
- /* put stack args in temps if optimizing */
- spname = sp[i];
- p = tempnode(0, sp[i]->stype,
- sp[i]->sdf, sp[i]->ssue);
- p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
- sp[i]->soffset = p->n_left->n_lval;
- sp[i]->sflags |= STNODE;
- ecomp(p);
- }
-
- }
- n += szty(sp[i]->stype);
- }
-}
-
-
-/*
* Beginning-of-code: finished generating function prologue
*
* by now, the automatics and register variables are allocated
@@ -189,7 +399,7 @@ ejobcode(int flag )
{
#define OSB(x) __STRING(x)
#define OS OSB(TARGOS)
- printf("\t.ident \"%s (%s)\"\n", PACKAGE_STRING, OS);
+ printf("\t.ident \"%s (%s)\"\n", VERSSTR, OS);
}
/*
@@ -203,39 +413,6 @@ bjobcode()
}
/*
- * Output ascii string: print character 't' at position 'i' until 't' == -1.
- */
-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);
- }
- }
-}
-
-/*
* Compute the alignment of object with type 't'.
*/
int
@@ -265,171 +442,183 @@ mygenswitch(int num, TWORD type, struct swents **p, int n)
return 0;
}
-static int regoff[7];
-static TWORD ftype;
/*
- * calculate stack size and offsets
+ * Straighten a chain of CM ops so that the CM nodes
+ * only appear on the left node.
+ *
+ * CM CM
+ * CM CM CM b
+ * x y a b CM a
+ * x y
*/
-static int
-offcalc(struct interpass_prolog *ipp)
+static NODE *
+straighten(NODE *p)
{
- int i, j, addto;
+ NODE *r = p->n_right;
-#ifdef PCC_DEBUG
- if (x2debug)
- printf("offcalc: p2maxautooff=%d\n", p2maxautooff);
-#endif
+ if (p->n_op != CM || r->n_op != CM)
+ return p;
- addto = p2maxautooff;
+ p->n_right = r->n_left;
+ r->n_left = p;
- // space is always allocated on the stack to save the permanents
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1) {
- addto += SZINT/SZCHAR;
- regoff[j] = addto;
- }
- }
+ return r;
+}
-#if 0
- addto += 7;
- addto &= ~7;
-#endif
-#ifdef PCC_DEBUG
- if (x2debug)
- printf("offcalc: addto=%d\n", addto);
-#endif
+/* push arg onto the stack */
+/* called by moveargs() */
+static NODE *
+pusharg(NODE *p, int *regp)
+{
+ NODE *q;
+ int sz;
- addto -= AUTOINIT / SZCHAR;
+ /* convert to register size, if smaller */
+ sz = tsize(p->n_type, p->n_df, p->n_sue);
+ if (sz < SZINT)
+ p = block(SCONV, p, NIL, INT, 0, MKSUE(INT));
- return addto;
-}
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = SP;
-void
-prologue(struct interpass_prolog *ipp)
-{
- int i, j;
- int addto;
-
-#ifdef PCC_DEBUG
- if (x2debug)
- printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n",
- ipp->ipp_ip.type,
- ipp->ipp_ip.lineno,
- ipp->ipp_name,
- ipp->ipp_vis,
- ipp->ipp_type,
- ipp->ipp_regs,
- ipp->ipp_autos,
- ipp->ip_tmpnum,
- ipp->ip_lblnum);
-#endif
+ if (szty(p->n_type) == 1) {
+ ++(*regp);
+ q = block(MINUSEQ, q, bcon(4), INT, 0, MKSUE(INT));
+ } else {
+ (*regp) += 2;
+ q = block(MINUSEQ, q, bcon(8), INT, 0, MKSUE(INT));
+ }
- ftype = ipp->ipp_type;
+ q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_sue);
- printf("\t.align 2\n");
- if (ipp->ipp_vis)
- printf("\t.global %s\n", exname(ipp->ipp_name));
- printf("\t.type %s,%%function\n", exname(ipp->ipp_name));
- printf("%s:\n", exname(ipp->ipp_name));
+ return buildtree(ASSIGN, q, p);
+}
- /*
- * We here know what register to save and how much to
- * add to the stack.
- */
- addto = offcalc(ipp);
-
- printf("\tmov %s,%s\n", rnames[IP], rnames[SP]);
- printf("\tstmfd %s!,{%s,%s,%s,%s}\n", rnames[SP], rnames[FP],
- rnames[IP], rnames[LR], rnames[PC]);
- printf("\tsub %s,%s,#4\n", rnames[FP], rnames[IP]);
- if (addto)
- printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], addto);
-
- for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) {
- if (i & 1) {
- printf("\tstr %s,[%s,#-%d]\n",
- rnames[j], rnames[FP], regoff[j]);
- }
- }
+/* setup call stack with 32-bit argument */
+/* called from moveargs() */
+static NODE *
+movearg_32bit(NODE *p, int *regp)
+{
+ int reg = *regp;
+ NODE *q;
+
+ q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
+ regno(q) = reg++;
+ q = buildtree(ASSIGN, q, p);
+ *regp = reg;
+ return q;
}
-void
-eoftn(struct interpass_prolog *ipp)
+/* setup call stack with 64-bit argument */
+/* called from moveargs() */
+static NODE *
+movearg_64bit(NODE *p, int *regp)
{
- int i, j;
+ int reg = *regp;
+ NODE *q, *r;
+
+#if ALLONGLONG == 64
+ /* alignment */
+ ++reg;
+ reg &= ~1;
+ *regp = reg;
+#endif
- if (ipp->ipp_ip.ip_lbl == 0)
- return; /* no code needs to be generated */
+ if (reg > R3) {
+ q = pusharg(p, regp);
+ } else if (reg == R3) {
+ /* half in and half out of the registers */
+ r = tcopy(p);
+ if (features(FEATURE_BIGENDIAN)) {
+ q = buildtree(RS, p, bcon(32));
+ q = block(SCONV, q, NIL, INT, 0, MKSUE(INT));
+ } else {
+ q = block(SCONV, p, NIL, INT, 0, MKSUE(INT));
+ }
+ q = movearg_32bit(q, regp);
+ if (features(FEATURE_BIGENDIAN)) {
+ r = block(SCONV, r, NIL, INT, 0, MKSUE(INT));
+ } else {
+ r = buildtree(RS, r, bcon(32));
+ r = block(SCONV, r, NIL, INT, 0, MKSUE(INT));
+ }
+ r = pusharg(r, regp);
+ q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_sue));
+ } else {
+ q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
+ regno(q) = R0R1 + (reg - R0);
+ q = buildtree(ASSIGN, q, p);
+ *regp = reg + 2;
+ }
- /* return from function code */
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1)
- printf("\tldr %s,[%s,#-%d]\n",
- rnames[j], rnames[FP], regoff[j]);
-
- }
+ return q;
+}
- /* struct return needs special treatment */
- if (ftype == STRTY || ftype == UNIONTY) {
- assert(0);
+/* setup call stack with float/double argument */
+/* called from moveargs() */
+static NODE *
+movearg_float(NODE *p, int *regp)
+{
+ NODE *r, *l;
+ int tmpnr;
+
+ /*
+ * Floats are passed in the general registers for
+ * compatibily with libraries compiled to handle soft-float.
+ */
+
+ l = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(l);
+ l = buildtree(ASSIGN, l, p);
+ ecomp(l);
+
+ if (p->n_type == FLOAT) {
+ r = tempnode(tmpnr, INT, 0, MKSUE(INT));
+ r = movearg_32bit(r, regp);
} else {
- printf("\tldmea %s,{%s,%s,%s}\n", rnames[FP], rnames[FP],
- rnames[SP], rnames[PC]);
+ r = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG));
+ r = movearg_64bit(r, regp);
}
- printf("\t.size %s,.-%s\n", exname(ipp->ipp_name),
- exname(ipp->ipp_name));
-}
-char *rnames[] = {
- "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", "r8",
- "r9", "r10", "fp", "ip", "sp", "lr", "pc",
- "r0r1", "r1r2", "r2r3", "r3r4", "r4r5", "r5r6",
- "r6r7", "r7r8", "r8r9", "r9r10",
-};
+ return r;
+}
-static void
-moveargs(NODE **n, int *regp)
+static NODE *
+moveargs(NODE *p, int *regp)
{
- NODE *r = *n;
- NODE *t;
- int sz;
- int regnum;
-
- if (r->n_op == CM) {
- moveargs(&r->n_left, regp);
- n = &r->n_right;
- r = r->n_right;
+ NODE *r, **rp;
+ int reg;
+
+ if (p->n_op == CM) {
+ p->n_left = moveargs(p->n_left, regp);
+ r = p->n_right;
+ rp = &p->n_right;
+ } else {
+ r = p;
+ rp = &p;
}
- regnum = *regp;
- sz = szty(r->n_type);
-
- if (regnum + sz <= R4) {
- t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
- switch (r->n_type) {
- case DOUBLE:
- case LDOUBLE:
-#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP)
- t->n_rval = regnum + F0;
- break;
-#endif
- case LONGLONG:
- case ULONGLONG:
- t->n_rval = regnum + R0R1;
- break;
- default:
- t->n_rval = regnum;
- }
- t = buildtree(ASSIGN, t, r);
+ reg = *regp;
+
+ if (reg > R3) {
+ *rp = pusharg(r, regp);
+ } else if (DEUNSIGN(r->n_type) == LONGLONG) {
+ *rp = movearg_64bit(r, regp);
+ } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
+ *rp = movearg_float(r, regp);
+ } else if (r->n_type == FLOAT) {
+ *rp = movearg_float(r, regp);
} else {
- t = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue);
+ *rp = movearg_32bit(r, regp);
}
- *n = t;
- *regp += sz;
+ if ((*rp)->n_op == CM && r != p)
+ p = straighten(p);
+
+ return p;
}
/*
@@ -439,13 +628,14 @@ moveargs(NODE **n, int *regp)
NODE *
funcode(NODE *p)
{
- int regnum = R0;
+ int reg = R0;
int ty;
ty = DECREF(p->n_left->n_type);
if (ty == STRTY+FTN || ty == UNIONTY+FTN)
- regnum = R1;
+ reg = R1;
+
+ p->n_right = moveargs(p->n_right, &reg);
- moveargs(&p->n_right, &regnum);
return p;
}
diff --git a/usr.bin/pcc/arm/local.c b/usr.bin/pcc/arm/local.c
index 70e9bfb4419..d11a0bdd6a8 100644
--- a/usr.bin/pcc/arm/local.c
+++ b/usr.bin/pcc/arm/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.1 2007/11/25 18:45:06 otto Exp $ */
+/* $OpenBSD: local.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
@@ -36,6 +36,8 @@
#include "pass1.h"
+extern void defalign(int);
+
/*
* clocal() is called to do local transformations on
* an expression tree before being sent to the backend.
@@ -47,6 +49,7 @@ clocal(NODE *p)
NODE *l, *r, *t;
int o;
int ty;
+ int tmpnr, isptrvoid = 0;
o = p->n_op;
switch (o) {
@@ -55,28 +58,53 @@ clocal(NODE *p)
l = p->n_left;
r = p->n_right;
- if (r->n_op == STCALL || r->n_op == USTCALL) {
- /* assign left node as first argument to function */
- nfree(p);
- t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
- l->n_rval = R0;
- l = buildtree(ADDROF, l, NIL);
- l = buildtree(ASSIGN, t, l);
- ecomp(l);
- t = tempnode(0, r->n_type, r->n_df, r->n_sue);
- r = buildtree(ASSIGN, t, r);
- ecomp(r);
- t = tempnode(t->n_lval, r->n_type, r->n_df, r->n_sue);
- return t;
+ if (r->n_op != STCALL && r->n_op != USTCALL)
+ return p;
+
+ /* assign left node as first argument to function */
+ nfree(p);
+ t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
+ l->n_rval = R0;
+ l = buildtree(ADDROF, l, NIL);
+ l = buildtree(ASSIGN, t, l);
+
+ if (r->n_right->n_op != CM) {
+ r->n_right = block(CM, l, r->n_right,
+ INT, 0, MKSUE(INT));
+ } else {
+ for (t = r->n_right; t->n_left->n_op == CM;
+ t = t->n_left)
+ ;
+ t->n_left = block(CM, l, t->n_left,
+ INT, 0, MKSUE(INT));
}
- break;
+ return r;
-#if 0
case CALL:
+ case STCALL:
+ case USTCALL:
+ if (p->n_type == VOID)
+ break;
+ /*
+ * if the function returns void*, ecode() invokes
+ * delvoid() to convert it to uchar*.
+ * We just let this happen on the ASSIGN to the temp,
+ * and cast the pointer back to void* on access
+ * from the temp.
+ */
+ if (p->n_type == PTR+VOID)
+ isptrvoid = 1;
r = tempnode(0, p->n_type, p->n_df, p->n_sue);
- ecomp(buildtree(ASSIGN, r, p));
- return r;
-#endif
+ tmpnr = regno(r);
+ r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_sue);
+
+ p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue);
+ if (isptrvoid) {
+ p = block(PCONV, p, NIL, PTR+VOID,
+ p->n_df, MKSUE(PTR+VOID));
+ }
+ p = buildtree(COMOP, r, p);
+ break;
case NAME:
if ((q = p->n_sp) == NULL)
@@ -100,12 +128,14 @@ clocal(NODE *p)
break;
case STATIC:
if (q->slevel > 0) {
- p->n_lval = 0;
- p->n_sp = q;
- }
- break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ }
+ /* FALL-THROUGH */
default:
ty = p->n_type;
+ if (strncmp(p->n_sp->soname, "__builtin", 9) == 0)
+ break;
p = block(ADDROF, p, NIL, INCREF(ty), p->n_df, p->n_sue);
p = block(UMUL, p, NIL, ty, p->n_df, p->n_sue);
break;
@@ -157,15 +187,6 @@ clocal(NODE *p)
}
}
-#if 0 // table.c will handle these okay
- 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;
- }
-#endif
-
if (l->n_op == ICON) {
CONSZ val = l->n_lval;
@@ -215,14 +236,15 @@ clocal(NODE *p)
l->n_sue = MKSUE(p->n_type);
nfree(p);
return l;
- }
-#if 0 // table.c will handle these okay
- if (DEUNSIGN(p->n_type) == SHORT &&
- DEUNSIGN(l->n_type) == SHORT) {
- nfree(p);
- p = l;
- }
-#endif
+ } else if (p->n_op == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = p->n_type;
+ l->n_sue = MKSUE(p->n_type);
+ nfree(p);
+ return clocal(l);
+ }
if ((DEUNSIGN(p->n_type) == CHAR ||
DEUNSIGN(p->n_type) == SHORT) &&
(l->n_type == FLOAT || l->n_type == DOUBLE ||
@@ -271,6 +293,29 @@ clocal(NODE *p)
void
myp2tree(NODE *p)
{
+ struct symtab *sp;
+
+ if (p->n_op != FCON)
+ return;
+
+#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
+
+ sp = IALLOC(sizeof(struct symtab));
+ sp->sclass = STATIC;
+ sp->ssue = MKSUE(p->n_type);
+ sp->slevel = 1; /* fake numeric label */
+ sp->soffset = getlab();
+ sp->sflags = 0;
+ sp->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, sp->ssue->suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
+
}
/*
@@ -349,6 +394,57 @@ spalloc(NODE *t, NODE *p, OFFSZ off)
ecomp(buildtree(ASSIGN, t, sp));
}
+/*
+ * Print out a string of characters.
+ * Assume that the assembler understands C-style escape
+ * sequences.
+ */
+void
+instring(struct symtab *sp)
+{
+ char *s, *str;
+
+ defloc(sp);
+ str = sp->sname;
+
+ /* be kind to assemblers and avoid long strings */
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; ) {
+ if (*s++ == '\\') {
+ (void)esccon(&s);
+ }
+ if (s - str > 60) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = bcon(0);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
+
+
static int inbits = 0, inval = 0;
/*
@@ -423,8 +519,18 @@ ninval(CONSZ off, int fsz, NODE *p)
if (t > BTMASK)
t = INT; /* pointer */
+ /*
+ * The target-independent code does rewrite the NAME nodes
+ * to ICONS after we prefixed the NAME nodes with ADDROF.
+ * We do it here. Maybe this is too much of a hack!
+ */
+ if (p->n_op == ADDROF && p->n_left->n_op == NAME) {
+ p = p->n_left;
+ p->n_op = ICON;
+ }
+
if (p->n_op != ICON && p->n_op != FCON)
- cerror("ninval: init node not constant");
+ cerror("ninval: init node not constant: node %p", p);
if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
uerror("element not constant");
@@ -435,17 +541,17 @@ ninval(CONSZ off, int fsz, NODE *p)
i = (p->n_lval >> 32);
j = (p->n_lval & 0xffffffff);
p->n_type = INT;
-#ifdef TARGET_BIG_ENDIAN
- p->n_lval = i;
- ninval(off+32, 32, p);
- p->n_lval = j;
- ninval(off, 32, p);
-#else
- p->n_lval = j;
- ninval(off, 32, p);
- p->n_lval = i;
- ninval(off+32, 32, p);
-#endif
+ if (features(FEATURE_BIGENDIAN)) {
+ p->n_lval = i;
+ ninval(off+32, 32, p);
+ p->n_lval = j;
+ ninval(off, 32, p);
+ } else {
+ p->n_lval = j;
+ ninval(off, 32, p);
+ p->n_lval = i;
+ ninval(off+32, 32, p);
+ }
break;
case INT:
case UNSIGNED:
@@ -455,7 +561,7 @@ ninval(CONSZ off, int fsz, NODE *p)
q->sclass == ILABEL) {
printf("+" LABFMT, q->soffset);
} else
- printf("+%s", exname(q->sname));
+ printf("+%s", exname(q->soname));
}
printf("\n");
break;
@@ -474,12 +580,16 @@ ninval(CONSZ off, int fsz, NODE *p)
case LDOUBLE:
case DOUBLE:
u.d = (double)p->n_dcon;
-#if (defined(TARGET_BIG_ENDIAN) && defined(HOST_LITTLE_ENDIAN)) || \
- (defined(TARGET_LITTLE_ENDIAN) && defined(HOST_BIG_ENDIAN))
- printf("\t.word\t0x%x\n\t.word\t0x%x\n", u.i[0], u.i[1]);
+#if defined(HOST_BIG_ENDIAN)
+ if (features(FEATURE_BIGENDIAN))
#else
- printf("\t.word\t0x%x\n\t.word\t0x%x\n", u.i[1], u.i[0]);
+ if (!features(FEATURE_BIGENDIAN))
#endif
+ printf("\t.word\t0x%x\n\t.word\t0x%x\n",
+ u.i[0], u.i[1]);
+ else
+ printf("\t.word\t0x%x\n\t.word\t0x%x\n",
+ u.i[1], u.i[0]);
break;
case FLOAT:
u.f = (float)p->n_dcon;
@@ -535,61 +645,19 @@ extdec(struct symtab *q)
{
}
-/*
- * make a common declaration for 'id', if reasonable
- */
+/* make a common declaration for id, if reasonable */
void
-commdec(struct symtab *q)
+defzero(struct symtab *sp)
{
int off;
- off = tsize(q->stype, q->sdf, q->ssue);
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
off = (off+(SZCHAR-1))/SZCHAR;
-#ifdef GCC_COMPAT
- printf("\t.comm %s,%d,%d\n", exname(gcc_findname(q)), off, 4);
-#else
- printf("\t.comm %s,%,%d\n", exname(q->sname), off, 4);
-#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("\t.lcomm %s,%d\n", exname(gcc_findname(q)), off);
-#else
- printf("\t.lcomm %s,%d\n", exname(q->sname), off);
-#endif
+ printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,0%o\n", exname(sp->soname), off);
else
- printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off);
-}
-
-/*
- * Print a (non-prog) label.
- */
-void
-deflab1(int label)
-{
- printf(LABFMT ":\n", label);
-}
-
-static char *loctbl[] = { "text", "data", "text", "section .rodata" };
-
-void
-setloc1(int locc)
-{
- if (locc == lastloc)
- return;
- lastloc = locc;
- printf("\t.%s\n", loctbl[locc]);
+ printf(LABFMT ",0%o\n", sp->soffset, off);
}
/*
@@ -603,38 +671,137 @@ setloc1(int locc)
NODE *
arm_builtin_stdarg_start(NODE *f, NODE *a)
{
- NODE *p;
- int sz = 1;
-
- /* check num args and type */
- if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
- !ISPTR(a->n_left->n_type))
- goto bad;
-
- /* must first deal with argument size; use int size */
- p = a->n_right;
- if (p->n_type < INT)
- sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue);
+ NODE *p, *q;
+ int sz = 1;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type))
+ goto bad;
+
+ /* must first deal with argument size; use int size */
+ p = a->n_right;
+ if (p->n_type < INT) {
+ /* round up to word */
+ sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue);
+ }
+
+ p = buildtree(ADDROF, p, NIL); /* address of last arg */
+ p = optim(buildtree(PLUS, p, bcon(sz)));
+ q = block(NAME, NIL, NIL, PTR+VOID, 0, 0);
+ q = buildtree(CAST, q, p);
+ p = q->n_right;
+ nfree(q->n_left);
+ nfree(q);
+ p = buildtree(ASSIGN, a->n_left, p);
+ tfree(f);
+ nfree(a);
+
+ return p;
bad:
- return bcon(0);
+ uerror("bad argument to __builtin_stdarg_start");
+ return bcon(0);
}
NODE *
arm_builtin_va_arg(NODE *f, NODE *a)
{
- return bcon(0);
+ NODE *p, *q, *r;
+ int sz, tmpnr;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
+ goto bad;
+
+ r = a->n_right;
+
+ /* get type size */
+ sz = tsize(r->n_type, r->n_df, r->n_sue) / SZCHAR;
+ if (sz < SZINT/SZCHAR) {
+ werror("%s%s promoted to int when passed through ...",
+ ISUNSIGNED(r->n_type) ? "unsigned " : "",
+ DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
+ sz = SZINT/SZCHAR;
+ }
+
+ /* alignment */
+ p = tcopy(a->n_left);
+ if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
+ p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1));
+ p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_sue);
+ }
+
+ /* create a copy to a temp node */
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(q);
+ p = buildtree(ASSIGN, q, p);
+
+ q = tempnode(tmpnr, p->n_type, p->n_df,p->n_sue);
+ q = buildtree(PLUS, q, bcon(sz));
+ q = buildtree(ASSIGN, a->n_left, q);
+
+ q = buildtree(COMOP, p, q);
+
+ nfree(a->n_right);
+ nfree(a);
+ nfree(f);
+
+ p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_sue);
+ p = buildtree(UMUL, p, NIL);
+ p = buildtree(COMOP, q, p);
+
+ return p;
+
+bad:
+ uerror("bad argument to __builtin_va_arg");
+ return bcon(0);
}
NODE *
arm_builtin_va_end(NODE *f, NODE *a)
{
+ tfree(f);
+ tfree(a);
+
return bcon(0);
}
NODE *
arm_builtin_va_copy(NODE *f, NODE *a)
{
- return bcon(0);
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
+ goto bad;
+ tfree(f);
+ f = buildtree(ASSIGN, a->n_left, a->n_right);
+ nfree(a);
+ return f;
+
+bad:
+ uerror("bad argument to __buildtin_va_copy");
+ return bcon(0);
+}
+
+char *nextsect;
+
+/*
+ * Give target the opportunity of handling pragmas.
+ */
+int
+mypragma(char **ary)
+{
+ if (strcmp(ary[1], "section") || ary[2] == NULL)
+ return 0;
+ nextsect = newstring(ary[2], strlen(ary[2]));
+ return 1;
+}
+
+/*
+ * Called when a identifier has been declared, to give target last word.
+ */
+void
+fixdef(struct symtab *sp)
+{
}
diff --git a/usr.bin/pcc/arm/local2.c b/usr.bin/pcc/arm/local2.c
index 36182094d41..8d68f59c338 100644
--- a/usr.bin/pcc/arm/local2.c
+++ b/usr.bin/pcc/arm/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.3 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: local2.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
@@ -32,9 +32,203 @@
#include <string.h>
#include <stdlib.h>
-#include "pass1.h"
#include "pass2.h"
+extern void defalign(int);
+
+#define exname(x) x
+
+char *rnames[] = {
+ "r0", "r1", "r2", "r3","r4","r5", "r6", "r7",
+ "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc",
+ "r0r1", "r1r2", "r2r3", "r3r4", "r4r5", "r5r6",
+ "r6r7", "r7r8", "r8r9", "r9r10",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+};
+
+/*
+ * Handling of integer constants. We have 8 bits + an even
+ * number of rotates available as a simple immediate.
+ * If a constant isn't trivially representable, use an ldr
+ * and a subsequent sequence of orr operations.
+ */
+
+static int
+trepresent(const unsigned int val)
+{
+ int i;
+#define rotate_left(v, n) (v << n | v >> (32 - n))
+
+ for (i = 0; i < 32; i += 2)
+ if (rotate_left(val, i) <= 0xff)
+ return 1;
+ return 0;
+}
+
+/*
+ * Return values are:
+ * 0 - output constant as is (should be covered by trepresent() above)
+ * 1 - 4 generate 1-4 instructions as needed.
+ */
+static int
+encode_constant(int constant, int *values)
+{
+ int tmp = constant;
+ int i = 0;
+ int first_bit, value;
+
+ while (tmp) {
+ first_bit = ffs(tmp);
+ first_bit -= 1; /* ffs indexes from 1, not 0 */
+ first_bit &= ~1; /* must use even bit offsets */
+
+ value = tmp & (0xff << first_bit);
+ values[i++] = value;
+ tmp &= ~value;
+ }
+ return i;
+}
+
+#if 0
+static void
+load_constant(NODE *p)
+{
+ int v = p->n_lval & 0xffffffff;
+ int reg = DECRA(p->n_reg, 1);
+
+ load_constant_into_reg(reg, v);
+}
+#endif
+
+static void
+load_constant_into_reg(int reg, int v)
+{
+ if (trepresent(v))
+ printf("\tmov %s,#%d\n", rnames[reg], v);
+ else if (trepresent(-v))
+ printf("\tmvn %s,#%d\n", rnames[reg], -v);
+ else {
+ int vals[4], nc, i;
+
+ nc = encode_constant(v, vals);
+ for (i = 0; i < nc; i++) {
+ if (i == 0) {
+ printf("\tmov %s,#%d" COM "load constant %d\n",
+ rnames[reg], vals[i], v);
+ } else {
+ printf("\torr %s,%s,#%d\n",
+ rnames[reg], rnames[reg], vals[i]);
+ }
+ }
+ }
+}
+
+static TWORD ftype;
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int addto;
+
+#ifdef PCC_DEBUG
+ if (x2debug)
+ printf("offcalc: p2maxautooff=%d\n", p2maxautooff);
+#endif
+
+ addto = p2maxautooff;
+
+#if 0
+ addto += 7;
+ addto &= ~7;
+#endif
+
+#ifdef PCC_DEBUG
+ if (x2debug)
+ printf("offcalc: addto=%d\n", addto);
+#endif
+
+ addto -= AUTOINIT / SZCHAR;
+
+ return addto;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+ int vals[4], nc, i;
+
+#ifdef PCC_DEBUG
+ if (x2debug)
+ printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n",
+ ipp->ipp_ip.type,
+ ipp->ipp_ip.lineno,
+ ipp->ipp_name,
+ ipp->ipp_vis,
+ ipp->ipp_type,
+ ipp->ipp_regs,
+ ipp->ipp_autos,
+ ipp->ip_tmpnum,
+ ipp->ip_lblnum);
+#endif
+
+ ftype = ipp->ipp_type;
+
+#if 0
+ printf("\t.align 2\n");
+ if (ipp->ipp_vis)
+ printf("\t.global %s\n", exname(ipp->ipp_name));
+ printf("\t.type %s,%%function\n", exname(ipp->ipp_name));
+#endif
+ printf("%s:\n", exname(ipp->ipp_name));
+
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+
+ printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], 16);
+ printf("\tmov %s,%s\n", rnames[IP], rnames[SP]);
+ printf("\tstmfd %s!,{%s,%s,%s,%s}\n", rnames[SP], rnames[FP],
+ rnames[IP], rnames[LR], rnames[PC]);
+ printf("\tsub %s,%s,#4\n", rnames[FP], rnames[IP]);
+
+ if (addto == 0)
+ return;
+
+ if (trepresent(addto)) {
+ printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], addto);
+ } else {
+ nc = encode_constant(addto, vals);
+ for (i = 0; i < nc; i++)
+ printf("\tsub %s,%s,#%d\n",
+ rnames[SP], rnames[SP], vals[i]);
+ }
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ assert(0);
+ } else {
+ printf("\tldmea %s,{%s,%s,%s}\n", rnames[FP], rnames[FP],
+ rnames[SP], rnames[PC]);
+ printf("\tadd %s,%s,#%d\n", rnames[SP], rnames[SP], 16);
+ }
+ printf("\t.size %s,.-%s\n", exname(ipp->ipp_name),
+ exname(ipp->ipp_name));
+}
+
+
/*
* these mnemonics match the order of the preprocessor decls
* EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT
@@ -161,18 +355,46 @@ twollcomp(NODE *p)
}
if (p->n_op >= ULE)
cb1 += 4, cb2 += 4;
- expand(p, 0, "\tcmp UR,UL\t@ compare 64-bit values (upper)\n");
+ expand(p, 0, "\tcmp UR,UL" COM "compare 64-bit values (upper)\n");
if (cb1) cbgen(cb1, s);
if (cb2) cbgen(cb2, e);
- expand(p, 0, "\tcmp AR,AL\t@ (and lower)\n");
+ expand(p, 0, "\tcmp AR,AL" COM "(and lower)\n");
cbgen(p->n_op, e);
deflab(s);
}
int
-fldexpand(NODE *P, int cookie, char **cp)
+fldexpand(NODE *p, int cookie, char **cp)
{
- return 0;
+ CONSZ val;
+ int shft;
+
+ if (p->n_op == ASSIGN)
+ p = p->n_left;
+
+ if (features(FEATURE_BIGENDIAN))
+ shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval);
+ else
+ shft = UPKFOFF(p->n_rval);
+
+ switch (**cp) {
+ case 'S':
+ printf("#%d", UPKFSZ(p->n_rval));
+ break;
+ case 'H':
+ printf("#%d", shft);
+ break;
+ case 'M':
+ case 'N':
+ val = (CONSZ)1 << UPKFSZ(p->n_rval);
+ --val;
+ val <<= shft;
+ printf("%lld", (**cp == 'M' ? val : ~val) & 0xffffffff);
+ break;
+ default:
+ comperr("fldexpand");
+ }
+ return 1;
}
#if 0
@@ -239,11 +461,19 @@ static void
stasg(NODE *p)
{
NODE *l = p->n_left;
-
- printf("\tldr %s,=%d\n", rnames[R2], p->n_stsize);
- if (l->n_rval != R0 || l->n_lval != 0)
- printf("\tadd %s,%s," CONFMT "\n", rnames[R0],
- rnames[l->n_rval], l->n_lval);
+ int val = l->n_lval;
+
+ load_constant_into_reg(R2, p->n_stsize);
+ if (l->n_rval != R0 || l->n_lval != 0) {
+ if (trepresent(val)) {
+ printf("\tadd %s,%s,#%d\n",
+ rnames[R0], rnames[regno(l)], val);
+ } else {
+ load_constant_into_reg(R0, val);
+ printf("\tadd %s,%s,%s\n", rnames[R0],
+ rnames[R0], rnames[regno(l)]);
+ }
+ }
printf("\tbl %s\n", exname("memcpy"));
}
@@ -252,23 +482,26 @@ shiftop(NODE *p)
{
NODE *r = p->n_right;
TWORD ty = p->n_type;
+ char *shifttype;
if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) {
expand(p, INBREG, "\tmov A1,AL,lsr ");
- printf(CONFMT "\t@ 64-bit left-shift\n", 32 - r->n_lval);
+ printf(CONFMT COM "64-bit left-shift\n", 32 - r->n_lval);
expand(p, INBREG, "\tmov U1,UL,asl AR\n");
expand(p, INBREG, "\torr U1,U1,A1\n");
expand(p, INBREG, "\tmov A1,AL,asl AR\n");
} else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) {
- expand(p, INBREG, "\tldr A1,=0\t@ 64-bit left-shift\n");
- expand(p, INBREG, "\tmov U1,AL,asl ");
- printf(CONFMT "\n", r->n_lval - 32);
+ expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n");
+ expand(p, INBREG, "\tmov U1,AL");
+ if (r->n_lval - 32 != 0)
+ printf(",asl " CONFMT, r->n_lval - 32);
+ printf("\n");
} else if (p->n_op == LS && r->n_op == ICON) {
- expand(p, INBREG, "\tldr A1,=0\t@ 64-bit left-shift\n");
- expand(p, INBREG, "\tldr U1,=0\n");
+ expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n");
+ expand(p, INBREG, "\tmov U1,#0\n");
} else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) {
expand(p, INBREG, "\tmov U1,UL,asl ");
- printf(CONFMT "\t@ 64-bit right-shift\n", 32 - r->n_lval);
+ printf(CONFMT COM "64-bit right-shift\n", 32 - r->n_lval);
expand(p, INBREG, "\tmov A1,AL,lsr AR\n");
expand(p, INBREG, "\torr A1,A1,U1\n");
if (ty == LONGLONG)
@@ -277,16 +510,20 @@ shiftop(NODE *p)
expand(p, INBREG, "\tmov U1,UL,lsr AR\n");
} else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) {
if (ty == LONGLONG) {
- expand(p, INBREG, "\tldr U1,=-1\t@ 64-bit right-shift\n");
- expand(p, INBREG, "\tmov A1,UL,asr ");
+ expand(p, INBREG, "\tmvn U1,#1" COM "64-bit right-shift\n");
+ expand(p, INBREG, "\tmov A1,UL");
+ shifttype = "asr";
}else {
- expand(p, INBREG, "\tldr U1,=0\t@ 64-bit right-shift\n");
- expand(p, INBREG, "\tmov A1,UL,lsr ");
+ expand(p, INBREG, "\tmov U1,#0" COM "64-bit right-shift\n");
+ expand(p, INBREG, "\tmov A1,UL");
+ shifttype = "lsr";
}
- printf(CONFMT "\n", r->n_lval - 32);
- } else if (p->n_op == LS && r->n_op == ICON) {
- expand(p, INBREG, "\tldr A1,=0\t@ 64-bit right-shift\n");
- expand(p, INBREG, "\tldr U1,=0\n");
+ if (r->n_lval - 32 != 0)
+ printf(",%s " CONFMT, shifttype, r->n_lval - 32);
+ printf("\n");
+ } else if (p->n_op == RS && r->n_op == ICON) {
+ expand(p, INBREG, "\tmov A1,#0" COM "64-bit right-shift\n");
+ expand(p, INBREG, "\tmov U1,#0\n");
}
}
@@ -301,104 +538,104 @@ fpemul(NODE *p)
if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3";
else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3";
- else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3";
+ else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "adddf3";
else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3";
else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3";
- else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3";
+ else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subdf3";
else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3";
else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3";
- else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3";
+ else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "muldf3";
else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3";
else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3";
- else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3";
+ else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divdf3";
else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2";
else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2";
- else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2";
+ else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negdf2";
else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2";
else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2";
- else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2";
+ else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqdf2";
else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2";
else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2";
- else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2";
+ else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "nedf2";
else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2";
else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2";
- else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2";
+ else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "gedf2";
else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2";
else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2";
- else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2";
+ else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "ledf2";
else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2";
else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2";
- else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2";
+ else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gtdf2";
else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2";
else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2";
- else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2";
+ else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "ltdf2";
else if (p->n_op == SCONV && p->n_type == FLOAT) {
if (l->n_type == DOUBLE) ch = "truncdfsf2";
- else if (l->n_type == LDOUBLE) ch = "trunctfsf2";
- else if (l->n_type == ULONGLONG) ch = "floatuntisf";
- else if (l->n_type == LONGLONG) ch = "floattisf";
- else if (l->n_type == LONG) ch = "floatdisf";
- else if (l->n_type == ULONG) ch = "floatundisf";
+ else if (l->n_type == LDOUBLE) ch = "truncdfsf2";
+ else if (l->n_type == ULONGLONG) ch = "floatundisf";
+ else if (l->n_type == LONGLONG) ch = "floatdisf";
+ else if (l->n_type == LONG) ch = "floatsisf";
+ else if (l->n_type == ULONG) ch = "floatunsisf";
else if (l->n_type == INT) ch = "floatsisf";
else if (l->n_type == UNSIGNED) ch = "floatunsisf";
} else if (p->n_op == SCONV && p->n_type == DOUBLE) {
if (l->n_type == FLOAT) ch = "extendsfdf2";
else if (l->n_type == LDOUBLE) ch = "trunctfdf2";
- else if (l->n_type == ULONGLONG) ch = "floatuntidf";
- else if (l->n_type == LONGLONG) ch = "floattidf";
- else if (l->n_type == LONG) ch = "floatdidf";
- else if (l->n_type == ULONG) ch = "floatundidf";
+ else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
+ else if (l->n_type == LONGLONG) ch = "floatdidf";
+ else if (l->n_type == LONG) ch = "floatsidf";
+ else if (l->n_type == ULONG) ch = "floatunsidf";
else if (l->n_type == INT) ch = "floatsidf";
else if (l->n_type == UNSIGNED) ch = "floatunsidf";
} else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
- if (l->n_type == FLOAT) ch = "extendsftf2";
- else if (l->n_type == DOUBLE) ch = "extenddftf2";
- else if (l->n_type == ULONGLONG) ch = "floatuntitf";
- else if (l->n_type == LONGLONG) ch = "floattitf";
- else if (l->n_type == LONG) ch = "floatditf";
- else if (l->n_type == ULONG) ch = "floatunsditf";
- else if (l->n_type == INT) ch = "floatsitf";
- else if (l->n_type == UNSIGNED) ch = "floatunsitf";
+ if (l->n_type == FLOAT) ch = "extendsfdf2";
+ else if (l->n_type == DOUBLE) ch = "extenddftd2";
+ else if (l->n_type == ULONGLONG) ch = "floatundidf";
+ else if (l->n_type == LONGLONG) ch = "floatdidf";
+ else if (l->n_type == LONG) ch = "floatsidf";
+ else if (l->n_type == ULONG) ch = "floatunsidf";
+ else if (l->n_type == INT) ch = "floatsidf";
+ else if (l->n_type == UNSIGNED) ch = "floatunsidf";
} else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
- if (l->n_type == FLOAT) ch = "fixunssfti";
- else if (l->n_type == DOUBLE) ch = "fixunsdfti";
- else if (l->n_type == LDOUBLE) ch = "fixunstfti";
+ if (l->n_type == FLOAT) ch = "fixunssfdi";
+ else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
} else if (p->n_op == SCONV && p->n_type == LONGLONG) {
- if (l->n_type == FLOAT) ch = "fixsfti";
- else if (l->n_type == DOUBLE) ch = "fixdfti";
- else if (l->n_type == LDOUBLE) ch = "fixtfti";
- } else if (p->n_op == SCONV && p->n_type == LONG) {
if (l->n_type == FLOAT) ch = "fixsfdi";
else if (l->n_type == DOUBLE) ch = "fixdfdi";
- else if (l->n_type == LDOUBLE) ch = "fixtfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixdfdi";
+ } else if (p->n_op == SCONV && p->n_type == LONG) {
+ if (l->n_type == FLOAT) ch = "fixsfsi";
+ else if (l->n_type == DOUBLE) ch = "fixdfsi";
+ else if (l->n_type == LDOUBLE) ch = "fixdfsi";
} else if (p->n_op == SCONV && p->n_type == ULONG) {
if (l->n_type == FLOAT) ch = "fixunssfdi";
else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
- else if (l->n_type == LDOUBLE) ch = "fixunstfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
} else if (p->n_op == SCONV && p->n_type == INT) {
if (l->n_type == FLOAT) ch = "fixsfsi";
else if (l->n_type == DOUBLE) ch = "fixdfsi";
- else if (l->n_type == LDOUBLE) ch = "fixtfsi";
+ else if (l->n_type == LDOUBLE) ch = "fixdfsi";
} else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
if (l->n_type == FLOAT) ch = "fixunssfsi";
else if (l->n_type == DOUBLE) ch = "fixunsdfsi";
- else if (l->n_type == LDOUBLE) ch = "fixunstfsi";
+ else if (l->n_type == LDOUBLE) ch = "fixunsdfsi";
}
if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op);
- printf("\tbl __%s\t@ softfloat operation\n", exname(ch));
+ printf("\tbl __%s" COM "softfloat operation\n", exname(ch));
if (p->n_op >= EQ && p->n_op <= GT)
printf("\tcmp %s,#0\n", rnames[R0]);
@@ -426,23 +663,23 @@ emul(NODE *p)
else if (p->n_op == RS && p->n_type == LONG) ch = "ashrdi3";
else if (p->n_op == RS && p->n_type == INT) ch = "ashrsi3";
- else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divti3";
+ else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3";
else if (p->n_op == DIV && p->n_type == LONG) ch = "divdi3";
else if (p->n_op == DIV && p->n_type == INT) ch = "divsi3";
- else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivti3";
+ else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3";
else if (p->n_op == DIV && p->n_type == ULONG) ch = "udivdi3";
else if (p->n_op == DIV && p->n_type == UNSIGNED) ch = "udivsi3";
- else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "modti3";
+ else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3";
else if (p->n_op == MOD && p->n_type == LONG) ch = "moddi3";
else if (p->n_op == MOD && p->n_type == INT) ch = "modsi3";
- else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umodti3";
+ else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3";
else if (p->n_op == MOD && p->n_type == ULONG) ch = "umoddi3";
else if (p->n_op == MOD && p->n_type == UNSIGNED) ch = "umodsi3";
- else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "multi3";
+ else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3";
else if (p->n_op == MUL && p->n_type == LONG) ch = "muldi3";
else if (p->n_op == MUL && p->n_type == INT) ch = "mulsi3";
@@ -450,7 +687,67 @@ emul(NODE *p)
else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negdi2";
else ch = 0, comperr("ZE");
- printf("\tbl __%s\t@ emulated operation\n", exname(ch));
+ printf("\tbl __%s" COM "emulated operation\n", exname(ch));
+}
+
+static void
+halfword(NODE *p)
+{
+ NODE *r = getlr(p, 'R');
+ NODE *l = getlr(p, 'L');
+ int idx0 = 0, idx1 = 1;
+
+ if (features(FEATURE_BIGENDIAN)) {
+ idx0 = 1;
+ idx1 = 0;
+ }
+
+ if (p->n_op == ASSIGN && r->n_op == OREG) {
+ /* load */
+ expand(p, 0, "\tldrb A1,");
+ printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx0);
+ expand(p, 0, "\tldrb AL,");
+ printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx1);
+ expand(p, 0, "\torr AL,A1,AL,asl #8\n");
+ } else if (p->n_op == ASSIGN && l->n_op == OREG) {
+ /* store */
+ expand(p, 0, "\tstrb AR,");
+ printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0);
+ expand(p, 0, "\tmov A1,AR,asr #8\n");
+ expand(p, 0, "\tstrb A1,");
+ printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1);
+ } else if (p->n_op == SCONV || p->n_op == UMUL) {
+ /* load */
+ expand(p, 0, "\tldrb A1,");
+ printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0);
+ expand(p, 0, "\tldrb A2,");
+ printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1);
+ expand(p, 0, "\torr A1,A1,A2,asl #8\n");
+ } else if (p->n_op == NAME || p->n_op == ICON || p->n_op == OREG) {
+ /* load */
+ expand(p, 0, "\tldrb A1,");
+ printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx0);
+ expand(p, 0, "\tldrb A2,");
+ printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx1);
+ expand(p, 0, "\torr A1,A1,A2,asl #8\n");
+ } else {
+ comperr("halfword");
+ }
+}
+
+static void
+bfext(NODE *p)
+{
+ int sz;
+
+ if (ISUNSIGNED(p->n_right->n_type))
+ return;
+ sz = 32 - UPKFSZ(p->n_left->n_rval);
+
+ expand(p, 0, "\tmov AD,AD,asl ");
+ printf("#%d\n", sz);
+ expand(p, 0, "\tmov AD,AD,asr ");
+ printf("#%d\n", sz);
}
static int
@@ -460,10 +757,10 @@ argsiz(NODE *p)
if (t < LONGLONG || t == FLOAT || t > BTMASK)
return 4;
- if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
+ if (t == LONGLONG || t == ULONGLONG)
+ return 8;
+ if (t == DOUBLE || t == LDOUBLE)
return 8;
- if (t == LDOUBLE)
- return 12;
if (t == STRTY || t == UNIONTY)
return p->n_stsize;
comperr("argsiz");
@@ -477,11 +774,9 @@ zzzcode(NODE *p, int c)
switch (c) {
-#if 0
- case 'B': /* Assign to bitfield */
- bfasg(p);
+ case 'B': /* bit-field sign extension */
+ bfext(p);
break;
-#endif
case 'C': /* remove from stack after subroutine call */
pr = p->n_qual;
@@ -507,18 +802,22 @@ zzzcode(NODE *p, int c)
fpemul(p);
break;
- case 'I': /* init constant */
- if (p->n_name[0] != '\0')
- comperr("named init");
- fprintf(stdout, "=%lld", p->n_lval & 0xffffffff);
- break;
+ case 'H': /* do halfword access */
+ halfword(p);
+ break;
+
+ case 'I': /* init constant */
+ if (p->n_name[0] != '\0')
+ comperr("named init");
+ load_constant_into_reg(DECRA(p->n_reg, 1),
+ p->n_lval & 0xffffffff);
+ break;
case 'J': /* init longlong constant */
- expand(p, INBREG, "\tldr A1,");
- fprintf(stdout, "=%lld\t@ load 64-bit constant\n",
+ load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1,
p->n_lval & 0xffffffff);
- expand(p, INBREG, "\tldr U1,");
- fprintf(stdout, "=%lld\n", (p->n_lval >> 32));
+ load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1 + 1,
+ (p->n_lval >> 32));
break;
case 'O': /* 64-bit left and right shift operators */
@@ -610,11 +909,16 @@ conput(FILE *fp, NODE *p)
if (p->n_sp)
printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel);
#endif
+#ifdef notdef /* ICON cannot ever use sp here */
+ /* If it does, it's a giant bug */
if (p->n_sp == NULL || (p->n_sp->sclass == ILABEL ||
(p->n_sp->sclass == STATIC && p->n_sp->slevel > 0)))
s = p->n_name;
else
s = exname(p->n_name);
+#else
+ s = p->n_name;
+#endif
if (*s != '\0') {
fprintf(fp, "%s", s);
@@ -688,7 +992,13 @@ adrput(FILE *io, NODE *p)
case OREG:
r = p->n_rval;
- fprintf(io, "[%s,#%d]", rnames[p->n_rval], (int)p->n_lval);
+ if (R2TEST(r))
+ fprintf(io, "[%s, %s, lsl #%d]",
+ rnames[R2UPK1(r)],
+ rnames[R2UPK2(r)],
+ R2UPK3(r));
+ else
+ fprintf(io, "[%s,#%d]", rnames[p->n_rval], (int)p->n_lval);
return;
case ICON:
@@ -696,13 +1006,15 @@ adrput(FILE *io, NODE *p)
conput(io, p);
return;
- case MOVE:
case REG:
switch (p->n_type) {
-#if !defined(ARM_HAS_FPA) && !defined(ARM_HAS_VFP)
case DOUBLE:
case LDOUBLE:
-#endif
+ if (features(FEATURE_HARDFLOAT)) {
+ fprintf(io, "%s", rnames[p->n_rval]);
+ break;
+ }
+ /* FALLTHROUGH */
case LONGLONG:
case ULONGLONG:
fprintf(stdout, "%s", rnames[p->n_rval-R0R1]);
@@ -725,16 +1037,73 @@ cbgen(int o, int lab)
{
if (o < EQ || o > UGT)
comperr("bad conditional branch: %s", opst[o]);
- printf("\t%s " LABFMT "\t@ conditional branch\n",
+ printf("\t%s " LABFMT COM "conditional branch\n",
ccbranches[o-EQ], lab);
}
+/*
+ * The arm can only address 4k to get a NAME, so there must be some
+ * rewriting here. Strategy:
+ * For first 1000 nodes found, print out the word directly.
+ * For the following 1000 nodes, group them together in asm statements
+ * and create a jump over.
+ * For the last <1000 statements, print out the words last.
+ */
struct addrsymb {
- DLIST_ENTRY(addrsymb) link;
- struct symtab *orig;
- struct symtab *new;
+ SLIST_ENTRY(addrsymb) link;
+ char *name; /* symbol name */
+ int num; /* symbol offset */
+ char *str; /* replace label */
};
-struct addrsymb addrsymblist;
+SLIST_HEAD(, addrsymb) aslist;
+static struct interpass *ipbase;
+static int prtnumber, nodcnt, notfirst;
+#define PRTLAB ".LY%d" /* special for here */
+
+static struct interpass *
+anode(char *p)
+{
+ extern int thisline;
+ struct interpass *ip = tmpalloc(sizeof(struct interpass));
+
+ ip->ip_asm = p;
+ ip->type = IP_ASM;
+ ip->lineno = thisline;
+ return ip;
+}
+
+static void
+flshlab(void)
+{
+ struct interpass *ip;
+ struct addrsymb *el;
+ int lab = prtnumber++;
+ char *c;
+
+ if (SLIST_FIRST(&aslist) == NULL)
+ return;
+
+ snprintf(c = tmpalloc(32), 32, "\tb " PRTLAB "\n", lab);
+ ip = anode(c);
+ DLIST_INSERT_BEFORE(ipbase, ip, qelem);
+
+ SLIST_FOREACH(el, &aslist, link) {
+ /* insert each node as asm */
+ int l = 32+strlen(el->name);
+ c = tmpalloc(l);
+ if (el->num)
+ snprintf(c, l, "%s:\n\t.word %s+%d\n",
+ el->str, el->name, el->num);
+ else
+ snprintf(c, l, "%s:\n\t.word %s\n", el->str, el->name);
+ ip = anode(c);
+ DLIST_INSERT_BEFORE(ipbase, ip, qelem);
+ }
+ /* generate asm label */
+ snprintf(c = tmpalloc(32), 32, PRTLAB ":\n", lab);
+ ip = anode(c);
+ DLIST_INSERT_BEFORE(ipbase, ip, qelem);
+}
static void
prtaddr(NODE *p)
@@ -744,39 +1113,65 @@ prtaddr(NODE *p)
int found = 0;
int lab;
+ nodcnt++;
+
+ if (p->n_op == ASSIGN && p->n_right->n_op == ICON &&
+ p->n_right->n_name[0] != '\0') {
+ /* named constant */
+ p = p->n_right;
+
+ /* Restore addrof */
+ l = mklnode(NAME, p->n_lval, 0, 0);
+ l->n_name = p->n_name;
+ p->n_left = l;
+ p->n_op = ADDROF;
+ }
+
if (p->n_op != ADDROF || l->n_op != NAME)
return;
+ /* if we passed 1k nodes printout list */
+ if (nodcnt > 1000) {
+ if (notfirst)
+ flshlab();
+ SLIST_INIT(&aslist);
+ notfirst = 1;
+ nodcnt = 0;
+ }
+
/* write address to byte stream */
- DLIST_FOREACH(el, &addrsymblist, link) {
- if (el->orig == l->n_sp) {
+ SLIST_FOREACH(el, &aslist, link) {
+ if (el->num == l->n_lval && el->name[0] == l->n_name[0] &&
+ strcmp(el->name, l->n_name) == 0) {
found = 1;
break;
}
}
if (!found) {
- setloc1(PROG);
- defalign(SZPOINT(l->n_type));
- deflab1(lab = getlab());
- printf("\t.word ");
- adrput(stdout, l);
- printf("\n");
+ /* we know that this is text segment */
+ lab = prtnumber++;
+ if (nodcnt <= 1000 && notfirst == 0) {
+ if (l->n_lval)
+ printf(PRTLAB ":\n\t.word %s+%lld\n",
+ lab, l->n_name, l->n_lval);
+ else
+ printf(PRTLAB ":\n\t.word %s\n",
+ lab, l->n_name);
+ }
el = tmpalloc(sizeof(struct addrsymb));
- el->orig = l->n_sp;
- el->new = tmpalloc(sizeof(struct symtab_hdr));
- el->new->sclass = ILABEL;
- el->new->soffset = lab;
- el->new->sflags = 0;
- DLIST_INSERT_BEFORE(&addrsymblist, el, link);
+ el->num = l->n_lval;
+ el->name = l->n_name;
+ el->str = tmpalloc(32);
+ snprintf(el->str, 32, PRTLAB, lab);
+ SLIST_INSERT_LAST(&aslist, el, link);
}
nfree(l);
p->n_op = NAME;
p->n_lval = 0;
- p->n_sp = el->new;
- p2tree(p);
+ p->n_name = el->str;
}
void
@@ -784,12 +1179,24 @@ myreader(struct interpass *ipole)
{
struct interpass *ip;
- DLIST_INIT(&addrsymblist, link);
+ SLIST_INIT(&aslist);
+ notfirst = nodcnt = 0;
DLIST_FOREACH(ip, ipole, qelem) {
- if (ip->type != IP_NODE)
- continue;
- walkf(ip->ip_node, prtaddr);
+ switch (ip->type) {
+ case IP_NODE:
+ lineno = ip->lineno;
+ ipbase = ip;
+ walkf(ip->ip_node, prtaddr);
+ break;
+ case IP_EPILOG:
+ ipbase = ip;
+ if (notfirst)
+ flshlab();
+ break;
+ default:
+ break;
+ }
}
if (x2debug)
printip(ipole);
@@ -839,30 +1246,41 @@ void
rmove(int s, int d, TWORD t)
{
switch (t) {
-#if !defined(ARM_HAS_FPU) && !defined(ARM_HAS_VFP)
case DOUBLE:
case LDOUBLE:
-#endif
+ if (features(FEATURE_HARDFLOAT)) {
+ printf("\tfmr %s,%s" COM "rmove\n",
+ rnames[d], rnames[s]);
+ break;
+ }
+ /* FALLTHROUGH */
case LONGLONG:
case ULONGLONG:
#define LONGREG(x, y) rnames[(x)-(R0R1-(y))]
if (s == d+1) {
/* dh = sl, copy low word first */
- printf("\tmov %s,%s @ rmove\n",
+ printf("\tmov %s,%s" COM "rmove\n",
LONGREG(d,0), LONGREG(s,0));
printf("\tmov %s,%s\n",
LONGREG(d,1), LONGREG(s,1));
} else {
/* copy high word first */
- printf("\tmov %s,%s @ rmove\n",
+ printf("\tmov %s,%s" COM "rmove\n",
LONGREG(d,1), LONGREG(s,1));
printf("\tmov %s,%s\n",
LONGREG(d,0), LONGREG(s,0));
}
#undef LONGREG
break;
+ case FLOAT:
+ if (features(FEATURE_HARDFLOAT)) {
+ printf("\tmr %s,%s" COM "rmove\n",
+ rnames[d], rnames[s]);
+ break;
+ }
+ /* FALLTHROUGH */
default:
- printf("\tmov %s,%s @ rmove\n", rnames[d], rnames[s]);
+ printf("\tmov %s,%s" COM "rmove\n", rnames[d], rnames[s]);
}
}
@@ -911,9 +1329,14 @@ COLORMAP(int c, int *r)
return num < 6; /* XXX see comments above */
case CLASSC:
num += r[CLASSC];
- return num < 8;
+ if (features(FEATURE_FPA))
+ return num < 8;
+ else if (features(FEATURE_VFP))
+ return num < 8;
+ else
+ cerror("colormap 1");
}
- assert(0);
+ cerror("colormap 2");
return 0; /* XXX gcc */
}
@@ -923,15 +1346,34 @@ COLORMAP(int c, int *r)
int
gclass(TWORD t)
{
-#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP)
- if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
- return CLASSC;
-#endif
- if (t == DOUBLE || t == LDOUBLE || t == LONGLONG || t == ULONGLONG)
+ if (t == DOUBLE || t == LDOUBLE) {
+ if (features(FEATURE_HARDFLOAT))
+ return CLASSC;
+ else
+ return CLASSB;
+ }
+ if (t == FLOAT) {
+ if (features(FEATURE_HARDFLOAT))
+ return CLASSC;
+ else
+ return CLASSA;
+ }
+ if (DEUNSIGN(t) == LONGLONG)
return CLASSB;
return CLASSA;
}
+int
+retreg(int t)
+{
+ int c = gclass(t);
+ if (c == CLASSB)
+ return R0R1;
+ else if (c == CLASSC)
+ return F0;
+ return R0;
+}
+
/*
* Calculate argument sizes.
*/
@@ -960,9 +1402,129 @@ special(NODE *p, int shape)
}
/*
+ * default to ARMv2
+ */
+#ifdef TARGET_BIG_ENDIAN
+#define DEFAULT_FEATURES FEATURE_BIGENDIAN | FEATURE_MUL
+#else
+#define DEFAULT_FEATURES FEATURE_MUL
+#endif
+
+static int fset = DEFAULT_FEATURES;
+
+/*
* Target-dependent command-line options.
*/
void
mflags(char *str)
{
+ if (strcasecmp(str, "little-endian") == 0) {
+ fset &= ~FEATURE_BIGENDIAN;
+ } else if (strcasecmp(str, "big-endian") == 0) {
+ fset |= FEATURE_BIGENDIAN;
+ } else if (strcasecmp(str, "fpe=fpa") == 0) {
+ fset &= ~(FEATURE_VFP | FEATURE_FPA);
+ fset |= FEATURE_FPA;
+ } else if (strcasecmp(str, "fpe=vfp") == 0) {
+ fset &= ~(FEATURE_VFP | FEATURE_FPA);
+ fset |= FEATURE_VFP;
+ } else if (strcasecmp(str, "soft-float") == 0) {
+ fset &= ~(FEATURE_VFP | FEATURE_FPA);
+ } else if (strcasecmp(str, "arch=armv1") == 0) {
+ fset &= ~FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset &= ~FEATURE_MUL;
+ fset &= ~FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv2") == 0) {
+ fset &= ~FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset &= ~FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv2a") == 0) {
+ fset &= ~FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset &= ~FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv3") == 0) {
+ fset &= ~FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset &= ~FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv4") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv4t") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv4tej") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv5") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv5te") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv5tej") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset &= ~FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv6") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset |= FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv6t2") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset |= FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv6kz") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset |= FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv6k") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset |= FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else if (strcasecmp(str, "arch=armv7") == 0) {
+ fset |= FEATURE_HALFWORDS;
+ fset |= FEATURE_EXTEND;
+ fset |= FEATURE_MUL;
+ fset |= FEATURE_MULL;
+ } else {
+ fprintf(stderr, "unknown m option '%s'\n", str);
+ exit(1);
+ }
}
+
+int
+features(int mask)
+{
+ if (mask == FEATURE_HARDFLOAT)
+ return ((fset & mask) != 0);
+ return ((fset & mask) == mask);
+}
+
+/*
+ * Define the current location as an internal label.
+ */
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
diff --git a/usr.bin/pcc/arm/macdefs.h b/usr.bin/pcc/arm/macdefs.h
index df8db2007db..a9564fd1082 100644
--- a/usr.bin/pcc/arm/macdefs.h
+++ b/usr.bin/pcc/arm/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.2 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: macdefs.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -145,8 +145,17 @@ typedef long long OFFSZ;
#define R8R9 24
#define R9R10 25
-#define NUMCLASS 2
-#define MAXREGS 26
+#define F0 26
+#define F1 27
+#define F2 28
+#define F3 29
+#define F4 30
+#define F5 31
+#define F6 32
+#define F7 33
+
+#define NUMCLASS 3
+#define MAXREGS 34
#define RSTATUS \
SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
@@ -155,6 +164,8 @@ typedef long long OFFSZ;
0, 0, 0, 0, 0, \
SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG, \
SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, \
#define ROVERLAP \
{ R0R1, -1 }, \
@@ -183,6 +194,14 @@ typedef long long OFFSZ;
{ R7, R8, R6R7, R8R9, -1 }, \
{ R8, R9, R7R8, R9R10, -1 }, \
{ R9, R10, R8R9, -1 }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
+ { -1, }, \
#define BACKTEMP /* stack grows negatively for temporaries */
#define BACKAUTO /* stack grows negatively for automatics */
@@ -190,35 +209,42 @@ typedef long long OFFSZ;
#define ARGINIT (4*8) /* # bits above fp where arguments start */
#define AUTOINIT (12*8) /* # bits above fp where automatics start */
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES 1 /* bytes are numbered right to left */
+
/* XXX - to die */
#define FPREG FP /* frame pointer */
/* Return a register class based on the type of the node */
#define PCLASS(p) (1 << gclass((p)->n_type))
-#define GCLASS(x) (x < 16 ? CLASSA : CLASSB)
+#define GCLASS(x) (x < 16 ? CLASSA : x < 26 ? CLASSB : 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 */
-
-#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP)
-#define RETREG(x) (DEUNSIGN(x) == LONGLONG ? R0R1 : \
- (x) == DOUBLE || (x) == LDOUBLE || (x) == FLOAT ? \
- F0 : R0)
-#else
-#define RETREG(x) (DEUNSIGN(x) == LONGLONG || \
- (x) == DOUBLE || (x) == LDOUBLE ? R0R1 : R0)
-#endif
+#define RETREG(x) retreg(x)
int COLORMAP(int c, int *r);
+int retreg(int ty);
+int features(int f);
+
+#define FEATURE_BIGENDIAN 0x00010000
+#define FEATURE_HALFWORDS 0x00020000 /* ldrsh/ldrh, ldrsb */
+#define FEATURE_EXTEND 0x00040000 /* sxth, sxtb, uxth, uxtb */
+#define FEATURE_MUL 0x00080000
+#define FEATURE_MULL 0x00100000
+#define FEATURE_FPA 0x10000000
+#define FEATURE_VFP 0x20000000
+#define FEATURE_HARDFLOAT (FEATURE_FPA|FEATURE_VFP)
-#define TARGET_STDARGS \
- { "__builtin_stdarg_start, arm_builtin_stdarg_start }, \
- { "__builtin_va_arg, arm_builtin_va_arg }, \
- { "__builtin_va_end, arm_builtin_va_end }, \
- { "__builtin_va_copy, arm_builtin_va_copy },
+#define TARGET_STDARGS
+#define TARGET_BUILTINS \
+ { "__builtin_stdarg_start", arm_builtin_stdarg_start }, \
+ { "__builtin_va_arg", arm_builtin_va_arg }, \
+ { "__builtin_va_end", arm_builtin_va_end }, \
+ { "__builtin_va_copy", arm_builtin_va_copy },
#define NODE struct node
struct node;
@@ -227,3 +253,6 @@ NODE *arm_builtin_va_arg(NODE *f, NODE *a);
NODE *arm_builtin_va_end(NODE *f, NODE *a);
NODE *arm_builtin_va_copy(NODE *f, NODE *a);
#undef NODE
+
+#define COM "\t@ "
+#define NARGREGS 4
diff --git a/usr.bin/pcc/arm/order.c b/usr.bin/pcc/arm/order.c
index 16798daec77..7b60b357cb6 100644
--- a/usr.bin/pcc/arm/order.c
+++ b/usr.bin/pcc/arm/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.2 2007/12/22 12:38:56 stefan Exp $ */
+/* $OpenBSD: order.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
@@ -81,11 +81,27 @@ offstar(NODE *p, int shape)
}
/*
- * It is OK to do an OREG - Modify the expression tree to be an OREG.
+ * Unable to convert to OREG (notoff() returned failure). Output
+ * suitable instructions to replace OREG.
*/
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,
+ r->n_right->n_lval);
+ tfree(p);
+ }
}
/*
@@ -298,5 +314,5 @@ livecall(NODE *p)
int
acceptable(struct optab *op)
{
- return 1;
+ return features(op->visit & 0xffff0000);
}
diff --git a/usr.bin/pcc/arm/table.c b/usr.bin/pcc/arm/table.c
index fcf715dbc09..89f6e707c35 100644
--- a/usr.bin/pcc/arm/table.c
+++ b/usr.bin/pcc/arm/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.1 2007/11/25 18:45:06 otto Exp $ */
+/* $OpenBSD: table.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*-
* Copyright (c) 2007 Gregory McGarry <g.mcgarry@ieee.org>
*
@@ -32,32 +32,6 @@
#define TSWORD TINT|TLONG
#define TWORD TUWORD|TSWORD
-#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP)
-#define INFREG INCREG
-#define NFREG NCREG
-#define SFREG SCREG
-#define NFSL NCSL
-#define NFSR NCSR
-#define INXREG INCREG
-#define NXREG NCREG
-#define SXREG SCREG
-#define NXSL NCSL
-#define NXSR NCSR
-#else
-#define INFREG INAREG
-#define NFREG NAREG
-#define SFREG SAREG
-#define NFSL NASL
-#define NFSR NASR
-#define INXREG INBREG
-#define NXREG NBREG
-#define SXREG SBREG
-#define NXSL NBSL
-#define NXSR NBSR
-#endif
-
-#define COM " @ "
-
struct optab table[] = {
/* First entry must be an empty entry */
{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
@@ -69,6 +43,7 @@ struct optab table[] = {
0, RLEFT,
COM "pointer conversion\n", },
+
/*
* Conversions of integral types
*
@@ -86,92 +61,140 @@ struct optab table[] = {
*/
{ SCONV, INAREG,
- INAREG, TCHAR,
- INAREG, TSWORD|TSHORT,
- NAREG|NASL, RESC1,
+ SAREG, TCHAR,
+ SAREG, TSWORD|TSHORT,
+ 0, RLEFT,
COM "convert char to short/int\n", },
{ SCONV, INAREG,
- INAREG, TCHAR,
- INAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
NAREG|NASL, RESC1,
" and A1,AL,#255" COM "convert char to uchar/ushort/uint\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TUCHAR,
+ SAREG, TCHAR,
+ NAREG|NASL, RESC1,
+ " sxtb A1,AL" COM "convert uchar to char\n", },
+
{ SCONV, INAREG,
- INAREG, TUCHAR,
- INAREG, TCHAR,
+ SAREG, TUCHAR,
+ SAREG, TCHAR,
NAREG|NASL, RESC1,
" mov A1,AL,asl #24" COM "convert uchar to char\n"
" mov A1,A1,asr #24\n", },
{ SCONV, INAREG,
- INAREG, TUCHAR,
- INAREG, TWORD|TSHORT|TUSHORT,
+ SAREG, TUCHAR,
+ SAREG, TWORD|TSHORT|TUSHORT,
0, RLEFT,
COM "convert uchar to (u)short/(u)int\n", },
{ SCONV, INAREG,
- INAREG, TSHORT,
- INAREG, TSWORD,
+ SAREG, TSHORT,
+ SAREG, TSWORD,
0, RLEFT,
COM "convert short to int\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TSHORT,
+ SAREG, TUWORD,
+ NAREG|NASL, RESC1,
+ " uxth A1,AL" COM "convert short to uint\n", },
+
{ SCONV, INAREG,
- INAREG, TSHORT,
- INAREG, TUWORD,
+ SAREG, TSHORT,
+ SAREG, TUWORD,
NAREG|NASL, RESC1,
" mov A1,AL,asl #16" COM "convert short to uint\n"
" mov A1,AL,lsr #16\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TUSHORT,
+ SAREG, TSHORT,
+ NAREG|NASL, RESC1,
+ " sxth A1,AL" COM "convert ushort to short\n", },
+
{ SCONV, INAREG,
- INAREG, TUSHORT,
- INAREG, TSHORT,
+ SAREG, TUSHORT,
+ SAREG, TSHORT,
NAREG|NASL, RESC1,
" mov A1,AL,asl #16" COM "convert ushort to short\n"
" mov A1,A1,asr #16\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TCHAR,
+ NAREG|NASL, RESC1,
+ " sxtb A1,AL" COM "convert (u)short to char\n", },
+
{ SCONV, INAREG,
- INAREG, TSHORT|TUSHORT,
- INAREG, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TCHAR,
NAREG|NASL, RESC1,
" mov A1,AL,asl #24" COM "convert (u)short to char\n"
" mov A1,A1,asr #24\n", },
{ SCONV, INAREG,
- INAREG, TSHORT|TUSHORT,
- INAREG, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TCHAR,
NAREG|NASL, RESC1,
- " and A1,AL,#255" COM "convert (u)short to uchar\n", },
+ " sxtb A1,AL" COM "convert (u)short to char\n", },
{ SCONV, INAREG,
- INAREG, TUSHORT,
- INAREG, TWORD,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TUCHAR,
NAREG|NASL, RESC1,
+ " and A1,AL,#255" COM "convert (u)short to uchar\n", },
+
+{ SCONV, INAREG,
+ SAREG, TUSHORT,
+ SAREG, TWORD,
+ 0, RLEFT,
COM "convert ushort to (u)int\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TWORD,
+ SAREG, TCHAR,
+ NAREG|NASL, RESC1,
+ " sxtb A1,AL" COM "convert (u)int to char\n", },
+
{ SCONV, INAREG,
- INAREG, TWORD,
- INAREG, TCHAR,
+ SAREG, TWORD,
+ SAREG, TCHAR,
NAREG|NASL, RESC1,
" mov A1,AL,asl #24" COM "convert (u)int to char\n"
" mov A1,A1,asr #24\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TWORD,
+ SAREG, TSHORT,
+ NAREG|NASL, RESC1,
+ " sxth A1,AL" COM "convert (u)int to short\n", },
+
{ SCONV, INAREG,
- INAREG, TWORD,
- INAREG, TSHORT,
+ SAREG, TWORD,
+ SAREG, TSHORT,
NAREG|NASL, RESC1,
" mov A1,AL,asl #16" COM "convert (u)int to short\n"
" mov A1,A1,asr #16\n", },
{ SCONV, INAREG,
- INAREG, TWORD,
- INAREG, TUCHAR,
+ SAREG, TWORD,
+ SAREG, TUCHAR,
NAREG|NASL, RESC1,
" and A1,AL,#255" COM "convert uchar to char\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SAREG, TWORD,
+ SAREG, TUSHORT,
+ NAREG|NASL, RESC1,
+ " uxth A1,AL" COM "convert int to ushort\n", },
+
{ SCONV, INAREG,
- INAREG, TWORD,
- INAREG, TUSHORT,
+ SAREG, TWORD,
+ SAREG, TUSHORT,
NAREG|NASL, RESC1,
" mov A1,AL,asl #16" COM "convert int to ushort\n"
" mov A1,AL,lsr #16\n", },
@@ -196,6 +219,12 @@ struct optab table[] = {
" mov A1,AL" COM "convert (u)char/(u)short/(u)int to (u)longlong\n"
" mov U1,AL,asr #31\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TCHAR,
+ NAREG, RESC1,
+ " sxtb A1,AL" COM "convert (u)longlong to char\n", },
+
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TCHAR,
@@ -203,6 +232,12 @@ struct optab table[] = {
" mov A1,AL,asl #24" COM "convert (u)longlong to char\n"
" mov A1,A1,asr #24\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TSHORT,
+ NAREG, RESC1,
+ " sxth A1,AL" COM "convert (u)longlong to short\n", },
+
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TSHORT,
@@ -222,6 +257,12 @@ struct optab table[] = {
NAREG, RESC1,
" and A1,AL,#255" COM "convert (u)longlong to uchar\n", },
+{ SCONV, INAREG | FEATURE_EXTEND,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TUSHORT,
+ NAREG, RESC1,
+ " uxth A1,AL" COM "convert (u)longlong to ushort\n", },
+
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TUSHORT,
@@ -246,287 +287,287 @@ struct optab table[] = {
" ldrb A1,AL" COM "convert uchar to int/long\n", },
/* short */
-{ SCONV, INAREG,
+{ SCONV, INAREG | FEATURE_HALFWORDS,
SOREG, TSHORT,
SAREG, TWORD,
NASL|NAREG, RESC1,
" ldrsh A1,AL" COM "convert short to int/long\n", },
/* ushort */
-{ SCONV, INAREG,
+{ SCONV, INAREG | FEATURE_HALFWORDS,
SOREG, TSHORT,
SAREG, TWORD,
NASL|NAREG, RESC1,
" ldrh A1,AL" COM "convert ushort to int/long\n", },
+/* short */
{ SCONV, INAREG,
- SFREG, TFLOAT,
- SAREG, TSWORD,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TWORD,
+ 2*NAREG|NASL, RESC1,
+ "ZH", },
+
+{ SCONV, INAREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SAREG, TWORD,
+ NAREG, RESC1,
" fix AL,AR" COM "convert float to int\n", },
-#elifdef ARM_HAS_VFP
+
+{ SCONV, INAREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SAREG, TSWORD,
+ NAREG, RESC1,
" ftosis AL,AR" COM "convert float to int\n", },
-#else
- "ZF", },
-#endif
-{ SCONV, INAREG,
- SFREG, TFLOAT,
- SAREG, TUWORD,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
- " fix AL,AR" COM "convert float to int\n", },
-#elifdef ARM_HAS_VFP
+{ SCONV, INAREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SAREG, TSWORD,
+ NAREG, RESC1,
" ftouis AL,AR" COM "convert float to int\n", },
-#else
- "ZF", },
-#endif
-{ SCONV, INBREG,
- SFREG, TFLOAT,
- SBREG, TULONGLONG,
+{ SCONV, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TWORD,
NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
"ZF", },
-#endif
+
+{ SCONV, INBREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SBREG, TULONGLONG|TLONGLONG,
+ NBREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INBREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SBREG, TULONGLONG|TLONGLONG,
+ NBREG, RESC1,
+ COM "unimplemented\n", },
{ SCONV, INBREG,
- SFREG, TFLOAT,
- SBREG, TLONGLONG,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+ SAREG, TFLOAT,
+ SBREG, TULONGLONG|TLONGLONG,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INAREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SAREG, TSWORD,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ SCONV, INAREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SAREG, TWORD,
+ NAREG, RESC1,
" fix AL,AR" COM "convert double/ldouble to int\n", },
-#elifdef ARM_HAS_VFP
+
+{ SCONV, INAREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SAREG, TSWORD,
+ NAREG, RESC1,
" ftosid AL,AR" COM "convert double/ldouble to int\n", },
-#else
- "ZF", },
-#endif
-{ SCONV, INAREG,
- SXREG, TDOUBLE|TLDOUBLE,
+{ SCONV, INAREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
SAREG, TUWORD,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
- " fix AL,AR" COM "convert double/ldouble to int\n", },
-#elifdef ARM_HAS_VFP
+ NAREG, RESC1,
" ftouid AL,AR" COM "convert double/ldouble to int\n", },
-#else
- "ZF", },
-#endif
-{ SCONV, INBREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SBREG, TULONGLONG,
+{ SCONV, INAREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SAREG, TWORD,
NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
"ZF", },
-#endif
+
+{ SCONV, INBREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SBREG, TLONGLONG|TULONGLONG,
+ NBREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INBREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SBREG, TULONGLONG|TLONGLONG,
+ NBREG, RESC1,
+ COM "unimplemented\n", },
{ SCONV, INBREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SBREG, TLONGLONG,
- NSPECIAL|NAREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TULONGLONG|TLONGLONG,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INFREG,
- SAREG, TSWORD,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ SCONV, INCREG | FEATURE_FPA,
+ SAREG, TWORD,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" flts AL,AR" COM "convert int to float\n" },
-#elifdef ARM_HAS_VFP
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SAREG, TSWORD,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fsitos AL,AR" COM "convert int to float\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INFREG,
+{ SCONV, INCREG | FEATURE_VFP,
SAREG, TUWORD,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
- " flts AL,AR" COM "convert int to float\n" },
-#elifdef ARM_HAS_VFP
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fuitos AL,AR" COM "convert int to float\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INFREG,
- SBREG, TLONGLONG,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INFREG,
- SBREG, TULONGLONG,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
- "ZF", },
-#endif
+{ SCONV, INCREG | FEATURE_FPA,
+ SBREG, TULONGLONG|TLONGLONG,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
-{ SCONV, INXREG,
- SAREG, TSWORD,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ SCONV, INCREG | FEATURE_VFP,
+ SBREG, TULONGLONG|TLONGLONG,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INAREG,
+ SBREG, TULONGLONG|TLONGLONG,
+ SAREG, TFLOAT,
+ NAREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INCREG | FEATURE_FPA,
+ SAREG, TWORD,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" fltd AL,AR" COM "convert int to double\n" },
-#elifdef ARM_HAS_VFP
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SAREG, TSWORD,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" fsitod AL,AR" COM "convert int to double\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INXREG,
+{ SCONV, INCREG | FEATURE_VFP,
SAREG, TUWORD,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
- " fltd AL,AR" COM "convert int to double\n" },
-#elifdef ARM_HAS_VFP
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" fuitod AL,AR" COM "convert int to double\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INXREG,
- SBREG, TLONGLONG,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+{ SCONV, INBREG,
+ SAREG, TWORD,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INXREG,
- SBREG, TULONGLONG,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+{ SCONV, INCREG | FEATURE_FPA,
+ SBREG, TLONGLONG|TULONGLONG,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SBREG, TLONGLONG|TULONGLONG,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INXREG,
- SAREG, TSWORD,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ SCONV, INCREG | FEATURE_FPA,
+ SAREG, TWORD,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" flte AL,AR" COM "convert int to ldouble\n" },
-#elifdef ARM_HAS_VFP
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SAREG, TSWORD,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" fsitod AL,AR" COM "convert int to ldouble\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INXREG,
+{ SCONV, INCREG | FEATURE_VFP,
SAREG, TUWORD,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
- " flte AL,AR" COM "convert int to ldouble\n" },
-#elifdef ARM_HAS_VFP
- " fuitod AL,AR" COM "convert int to ldouble\n" },
-#else
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
+ " fuitod AL,AR" COM "convert uint to ldouble\n" },
+
+{ SCONV, INBREG,
+ SAREG, TWORD,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
+{ SCONV, INCREG | FEATURE_FPA,
+ SBREG, TLONGLONG|TULONGLONG,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
-{ SCONV, INXREG,
- SBREG, TLONGLONG,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
- "ZF", },
-#endif
+{ SCONV, INCREG | FEATURE_VFP,
+ SBREG, TLONGLONG|TULONGLONG,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
-{ SCONV, INXREG,
- SBREG, TULONGLONG,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
-#else
+{ SCONV, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INFREG,
- SXREG, TDOUBLE,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
- " fcvtds AL,AR" COM "convert float to double\n" },
-#else
- "ZF", },
-#endif
+{ SCONV, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
-{ SCONV, INFREG,
- SXREG, TLDOUBLE,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
+{ SCONV, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fcvtds AL,AR" COM "convert float to double\n" },
-#else
- "ZF", },
-#endif
-{ SCONV, INXREG,
- SFREG, TFLOAT,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
- " fcvtsd AL,AR" COM "convert float to double\n" },
-#else
+{ SCONV, INAREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INXREG,
- SFREG, TFLOAT,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
-#elifdef ARM_HAS_VFP
+{ SCONV, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
+ COM "unimplemented\n", },
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
" fcvtsd AL,AR" COM "convert float to double\n" },
-#else
+
+{ SCONV, INBREG,
+ SAREG, TFLOAT,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ SCONV, INXREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SXREG, TDOUBLE|TLDOUBLE,
+{ SCONV, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ COM "convert (l)double to (l)double", },
+
+{ SCONV, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ COM "convert (l)double to (l)double", },
+
+{ SCONV, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
0, RLEFT,
COM "convert (l)double to (l)double", },
@@ -561,17 +602,31 @@ struct optab table[] = {
" bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n"
"ZC", },
-{ CALL, INFREG,
+{ CALL, INCREG | FEATURE_FPA,
SCON|SNAME, TANY,
- SFREG, TFLOAT,
- NFREG|NASL, RESC1, /* should be 0 */
+ SCREG, TFLOAT,
+ NCREG|NCSL, RESC1, /* should be 0 */
" bl CL" COM "call (args, result r0) to scon/sname (CL)\n"
"ZC", },
-{ CALL, INXREG,
+{ CALL, INCREG | FEATURE_FPA,
+ SCON|SNAME, TANY,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n"
+ "ZC", },
+
+{ CALL, INAREG,
SCON|SNAME, TANY,
- SXREG, TDOUBLE|TLDOUBLE,
- NXREG|NXSL, RESC1, /* should be 0 */
+ SAREG, TFLOAT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result r0) to scon/sname (CL)\n"
+ "ZC", },
+
+{ CALL, INBREG,
+ SCON|SNAME, TANY,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NBREG|NBSL, RESC1, /* should be 0 */
" bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n"
"ZC", },
@@ -587,16 +642,16 @@ struct optab table[] = {
NBREG|NBSL, RESC1, /* should be 0 */
" bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", },
-{ UCALL, INFREG,
+{ UCALL, INCREG | FEATURE_FPA,
SCON|SNAME, TANY,
- SFREG, TFLOAT,
- NFREG|NFSL, RESC1, /* should be 0 */
+ SCREG, TFLOAT,
+ NCREG|NCSL, RESC1, /* should be 0 */
" bl CL" COM "call (no args, result in r0) to scon/sname (CL)\n", },
-{ UCALL, INXREG,
+{ UCALL, INCREG | FEATURE_FPA,
SCON|SNAME, TANY,
- SXREG, TDOUBLE|TLDOUBLE,
- NXREG|NXSL, RESC1, /* should be 0 */
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1, /* should be 0 */
" bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", },
{ CALL, FOREFF,
@@ -614,11 +669,26 @@ struct optab table[] = {
" mov lr,pc\n"
" mov pc,AL\n", },
+{ CALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ INAREG, RESC1,
+ " mov lr,pc\n"
+ " mov pc,AL\n"
+ "ZC", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ INAREG, RESC1,
+ " mov lr,pc\n"
+ " mov pc,AL\n", },
+
/* struct return */
{ USTCALL, FOREFF,
SCON, TANY,
SANY, TANY,
- NAREG|NASL, 0,
+ 0, 0,
" bl CL\n", },
{ USTCALL, INAREG,
@@ -637,7 +707,7 @@ struct optab table[] = {
{ STCALL, FOREFF,
SCON, TANY,
SANY, TANY,
- NAREG|NASL, 0,
+ 0, 0,
" bl CL\n"
"ZC", },
@@ -686,41 +756,59 @@ struct optab table[] = {
" adds A1,AL,AR" COM "64-bit addition\n"
" adc U1,UL,UR\n", },
-{ PLUS, INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ PLUS, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" adfs A1,AL,AR" COM "float add\n", },
-#elifdef ARM_HAS_VFP
+
+{ PLUS, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fadds A1,AL,AR" COM "float add\n", },
-#else
+
+{ PLUS, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ PLUS, INXREG,
- SXREG, TDOUBLE,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ PLUS, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" adfd A1,AL,AR" COM "double add\n", },
-#elifdef ARM_HAS_VFP
+
+{ PLUS, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" faddd A1,AL,AR" COM "double add\n", },
-#else
+
+{ PLUS, INBREG,
+ SBREG, TDOUBLE,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ PLUS, INXREG,
- SXREG, TLDOUBLE,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ PLUS, INCREG | FEATURE_FPA,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" adfe A1,AL,AR" COM "ldouble add\n", },
-#elifdef ARM_HAS_VFP
+
+{ PLUS, INCREG | FEATURE_VFP,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" faddd A1,AL,AR" COM "ldouble add\n", },
-#else
+
+{ PLUS, INBREG,
+ SBREG, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
{ MINUS, INAREG,
SAREG, TWORD|TPOINT,
@@ -732,7 +820,7 @@ struct optab table[] = {
SAREG, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
NAREG|NASL, RESC1,
- " sub A1,AR,AL" COM "subtraction\n", },
+ " sub A1,AL,AR" COM "subtraction\n", },
{ MINUS, INBREG,
SBREG, TLONGLONG|TULONGLONG,
@@ -748,41 +836,59 @@ struct optab table[] = {
" subs A1,AL,AR" COM "64-bit subtraction\n"
" sbc U1,UL,AR\n", },
-{ MINUS, INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ MINUS, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" sufs A1,AL,AR" COM "float subtraction\n", },
-#elifdef ARM_HAS_VFP
+
+{ MINUS, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fsubs A1,AL,AR" COM "float subtraction\n", },
-#else
+
+{ MINUS, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ MINUS, INXREG,
- SXREG, TDOUBLE,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ MINUS, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" sufd A1,AL,AR" COM "double subtraction\n", },
-#elifdef ARM_HAS_VFP
+
+{ MINUS, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" fsubd A1,AL,AR" COM "double subtraction\n", },
-#else
+
+{ MINUS, INBREG,
+ SBREG, TDOUBLE,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ MINUS, INXREG,
- SXREG, TLDOUBLE,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ MINUS, INCREG | FEATURE_FPA,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" sufe A1,AL,AR" COM "ldouble subtraction\n", },
-#elifdef ARM_HAS_VFP
+
+{ MINUS, INCREG | FEATURE_VFP,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" fsubd A1,AL,AR" COM "double subtraction\n", },
-#else
+
+{ MINUS, INBREG,
+ SBREG, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
/*
* The next rules handle all shift operators.
@@ -790,7 +896,7 @@ struct optab table[] = {
{ LS, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TANY,
NAREG|NASL, RESC1,
" mov A1,AL,asl AR" COM "left shift\n", },
@@ -806,15 +912,21 @@ struct optab table[] = {
NBREG, RESC1,
"ZO" },
+{ LS, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TANY,
+ NSPECIAL|NBREG, RESC1,
+ "ZE" },
+
{ RS, INAREG,
SAREG, TSWORD|TSHORT|TCHAR,
- SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TANY,
NAREG|NASL, RESC1,
" mov A1,AL,asr AR" COM "right shift\n", },
{ RS, INAREG,
SAREG, TUWORD|TUSHORT|TUCHAR,
- SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TANY,
NAREG|NASL, RESC1,
" mov A1,AL,lsr AR" COM "right shift\n", },
@@ -836,6 +948,13 @@ struct optab table[] = {
NBREG, RESC1,
"ZO" },
+{ RS, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TANY,
+ NSPECIAL|NBREG, RESC1,
+ "ZE" },
+
+
/*
* The next rules takes care of assignments. "=".
*/
@@ -866,46 +985,73 @@ struct optab table[] = {
0, RDEST,
" strb AR,AL" COM "assign (u)char\n", },
-{ ASSIGN, FOREFF|INAREG,
+{ ASSIGN, FOREFF|INAREG | FEATURE_HALFWORDS,
SOREG|SNAME, TSHORT|TUSHORT,
SAREG, TSHORT|TUSHORT,
0, RDEST,
" strh AR,AL" COM "assign (u)short\n", },
-{ ASSIGN, FOREFF|INFREG,
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RDEST,
+ "ZH", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_FPA,
SOREG|SNAME, TFLOAT,
- SFREG, TFLOAT,
+ SCREG, TFLOAT,
0, RDEST,
-#ifdef ARM_HAS_FPA
" stfs AR,AL" COM "assign float\n", },
-#elifdef ARM_HAS_VFP
-#else
- " str AR,AL" COM "assign float\n", },
-#endif
-{ ASSIGN, FOREFF|INXREG,
+{ ASSIGN, FOREFF|INCREG | FEATURE_VFP,
+ SOREG|SNAME, TFLOAT,
+ SCREG, TFLOAT,
+ 0, RDEST,
+ COM "unimplemented\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TFLOAT,
+ SAREG, TFLOAT,
+ 0, RDEST,
+ " str AR,AL" COM "assign float (soft-float)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_FPA,
SOREG|SNAME, TDOUBLE,
- SXREG, TDOUBLE,
+ SCREG, TDOUBLE,
0, RDEST,
-#ifdef ARM_HAS_FPA
" stfd AR,AL" COM "assign double\n", },
-#elifdef ARM_HAS_VFP
-#else
- " str AR,AL" COM "assign double\n"
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_VFP,
+ SOREG|SNAME, TDOUBLE,
+ SCREG, TDOUBLE,
+ 0, RDEST,
+ COM "unimplemented\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG|SNAME, TDOUBLE,
+ SBREG, TDOUBLE,
+ 0, RDEST,
+ " str AR,AL" COM "assign double (soft-float)\n"
" str UR,UL\n", },
-#endif
-{ ASSIGN, FOREFF|INXREG,
+{ ASSIGN, FOREFF|INCREG | FEATURE_FPA,
SOREG|SNAME, TLDOUBLE,
- SXREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
0, RDEST,
-#ifdef ARM_HAS_FPA
" stfe AR,AL" COM "assign ldouble\n", },
-#elifdef ARM_HAS_VFP
-#else
- " str AR,AL" COM "assign ldouble\n"
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_VFP,
+ SOREG|SNAME, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ 0, RDEST,
+ COM "not implemented", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG|SNAME, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ 0, RDEST,
+ " str AR,AL" COM "assign ldouble (soft-float)\n"
" str UR,UL\n", },
-#endif
/* assign register to register */
{ ASSIGN, FOREFF|INAREG,
@@ -921,44 +1067,71 @@ struct optab table[] = {
" mov AL,AR" COM "assign UR:AR to UL:AL\n"
" mov UL,UR\n", },
-{ ASSIGN, FOREFF|INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
+{ ASSIGN, FOREFF|INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
0, RDEST,
-#ifdef ARM_HAS_FPA
" mvf AL,AR" COM "assign float reg to float reg\n", },
-#elifdef ARM_HAS_VFP
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ 0, RDEST,
" fcpys AL,AR" COM "assign float reg to float reg\n", },
-#else
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ 0, RDEST,
" mov AL,AR" COM "assign float reg to float reg\n", },
-#endif
-{ ASSIGN, FOREFF|INXREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SXREG, TDOUBLE|TLDOUBLE,
+{ ASSIGN, FOREFF|INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
0, RDEST,
-#ifdef ARM_HAS_FPA
" mvf AL,AR" COM "assign float reg to float reg\n", },
-#elifdef ARM_HAS_VFP
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
" fcpyd AL,AR" COM "assign float reg to float reg\n", },
-#else
+
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
" mov AL,AR" COM "assign (l)double reg to (l)double reg\n"
" mov UL,UR\n", },
-#endif
-#if 0
{ ASSIGN, FOREFF|INAREG,
- SFLD, TANY,
- SAREG, TANY,
- NAREG, RDEST,
- "ZE", },
+ SFLD, TANY,
+ SOREG|SNAME, TANY,
+ 3*NAREG, RDEST,
+ " ldr A1,AR" COM "bit-field assignment\n"
+ " ldr A2,AL\n"
+ " ldr A3,=M\n"
+ " mov A1,A1,asl H\n"
+ " and A1,A1,A3\n"
+ " bic A2,A2,A3\n"
+ " orr A3,A2,A1\n"
+ " str A3,AL\n"
+ "F ldr AD,AR\n"
+ "FZB", },
-{ ASSIGN, FOREFF,
+{ ASSIGN, FOREFF|INAREG,
SFLD, TANY,
SAREG, TANY,
- NAREG, 0,
- "ZE", },
-#endif
+ 3*NAREG, RDEST,
+ " ldr A2,AL" COM "bit-field assignment\n"
+ " ldr A3,=M\n"
+ " mov A1,AR,asl H\n"
+ " and A1,A1,A3\n"
+ " bic A2,A2,A3\n"
+ " orr A3,A2,A1\n"
+ " str A3,AL\n"
+ "F mov AD,AR\n"
+ "FZB", },
{ STASG, INAREG|FOREFF,
SOREG|SNAME, TANY,
@@ -982,41 +1155,59 @@ struct optab table[] = {
NSPECIAL|NBREG|NBSL, RESC1,
"ZE", },
-{ DIV, INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ DIV, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" dvfs A1,AL,AL" COM "fast (float) divide\n", },
-#elifdef ARM_HAS_VFP
+
+{ DIV, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fdivs A1,AL,AL" COM "fast (float) divide\n", },
-#else
+
+{ DIV, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ DIV, INXREG,
- SXREG, TDOUBLE,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ DIV, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" dvfd A1,AL,AL" COM "double divide\n", },
-#elifdef ARM_HAS_VFP
+
+{ DIV, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" fdivd A1,AL,AL" COM "double divide\n", },
-#else
+
+{ DIV, INBREG,
+ SBREG, TDOUBLE,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ DIV, INXREG,
- SXREG, TLDOUBLE,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
- " dvfe A1,AL,AL" COM "ldouble divide\n", },
-#elifdef ARM_HAS_VFP
+{ DIV, INCREG | FEATURE_FPA,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
+ " dvfe A1,AL,AR" COM "long double load\n", },
+
+{ DIV, INCREG | FEATURE_VFP,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" fdivd A1,AL,AL" COM "double divide\n", },
-#else
+
+{ DIV, INBREG,
+ SBREG, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
{ MOD, INAREG,
SAREG, TWORD,
@@ -1030,68 +1221,110 @@ struct optab table[] = {
NSPECIAL|NBREG, RESC1,
"ZE", },
+{ MUL, INAREG | FEATURE_MUL,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " mul A1,AL,AR\n", },
+
{ MUL, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NSPECIAL|NAREG, RESC1,
- " mul A1,AL,AR\n", },
+ "ZE", },
+
+{ MUL, INBREG | FEATURE_MULL,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ NBREG, RESC1,
+ " smull U1,A1,AL,AR\n", },
+
+{ MUL, INBREG | FEATURE_MUL,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ NBREG, RESC1,
+ " mul A1,AL,AR\n"
+ " mov U1,A1,asr #31\n", },
{ MUL, INBREG,
SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
NSPECIAL|NBREG, RESC1,
-#ifdef ARM_HAS_MULL
- " smull U1,A1,AL,AR\n", },
-#else
+ "ZE", },
+
+{ MUL, INBREG | FEATURE_MULL,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NBREG, RESC1,
+ " umull U1,A1,AL,AR\n", },
+
+{ MUL, INBREG | FEATURE_MUL,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NBREG, RESC1,
" mul A1,AL,AR\n"
- " mul U1,AL,AR\n", },
-#endif
+ " mov U1,#0\n", },
{ MUL, INBREG,
SAREG, TSWORD|TSHORT|TCHAR,
SAREG, TSWORD|TSHORT|TCHAR,
NSPECIAL|NBREG, RESC1,
-#ifdef ARM_HAS_MULL
+ "ZE", },
+
+{ MUL, INBREG | FEATURE_MULL,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TLONGLONG|TULONGLONG,
+ NBREG, RESC1,
" umull U1,A1,AL,AR\n", },
-#else
+
+{ MUL, INBREG | FEATURE_MUL,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TLONGLONG|TULONGLONG,
+ NBREG, RESC1,
" mul A1,AL,AR\n"
- " mul U1,AL,AR\n", },
-#endif
+ " mov U1,A1,asr #31\n", },
{ MUL, INBREG,
SBREG, TLONGLONG|TULONGLONG,
SBREG, TLONGLONG|TULONGLONG,
NSPECIAL|NBREG, RESC1,
-#ifdef ARM_HAS_MULL
- " umull U1,A1,AL,AR\n", },
-#else
- " mul A1,AL,AR\n"
- " mul U1,AL,AR\n", },
-#endif
+ "ZE", },
-{ MUL, INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ MUL, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fmls A1,AL,AL" COM "fast (float) multiply\n", },
-#elifdef ARM_HAS_VFP
+
+{ MUL, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" fmuls A1,AL,AL" COM "float multiply\n", },
-#else
+
+{ MUL, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ MUL, INXREG,
- SXREG, TDOUBLE|TLDOUBLE,
- SXREG, TDOUBLE|TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ MUL, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
" mufd A1,AL,AL" COM "fast (l)double multiply\n", },
-#elifdef ARM_HAS_VFP
+
+{ MUL, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
" muld A1,AL,AL" COM "(l)double multiply\n", },
-#else
+
+{ MUL, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
/*
* Indirection operators.
@@ -1115,18 +1348,24 @@ struct optab table[] = {
NAREG, RESC1,
" ldrb A1,AL" COM "uchar load\n", },
-{ UMUL, INAREG,
+{ UMUL, INAREG | FEATURE_HALFWORDS,
SANY, TANY,
SOREG|SNAME, TUSHORT,
NAREG, RESC1,
" ldrh A1,AL" COM "short load\n", },
-{ UMUL, INAREG,
+{ UMUL, INAREG | FEATURE_HALFWORDS,
SANY, TANY,
SOREG|SNAME, TSHORT,
NAREG, RESC1,
" ldrsh A1,AL" COM "short load\n", },
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TSHORT|TUSHORT,
+ 2*NAREG|NASL, RESC1,
+ "ZH", },
+
{ UMUL, INBREG,
SANY, TANY,
SOREG|SNAME, TLONGLONG|TULONGLONG,
@@ -1134,40 +1373,61 @@ struct optab table[] = {
" ldr A1,AL" COM "64-bit load\n"
" ldr U1,UL\n", },
-{ UMUL, INFREG,
+{ UMUL, INCREG | FEATURE_FPA,
SANY, TANY,
SOREG|SNAME, TFLOAT,
- NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+ NCREG, RESC1,
" ldfs A1,AL" COM "float load\n", },
-#elifdef ARM_HAS_VFP
-#else
+
+{ UMUL, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NCREG, RESC1,
+ COM "not implemented\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NAREG, RESC1,
" ldr A1,AL" COM "float load\n", },
-#endif
-{ UMUL, INXREG,
+{ UMUL, INCREG | FEATURE_FPA,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE,
+ NCREG, RESC1,
+ " ldfd A1,AL" COM "double load\n", },
+
+{ UMUL, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE,
+ NCREG, RESC1,
+ COM "not implemented\n", },
+
+{ UMUL, INBREG,
SANY, TANY,
SOREG|SNAME, TDOUBLE,
- NXREG, RESC1,
-#ifdef ARM_HAS_FPA
- " ldfd AL" COM "double load\n", },
-#elifdef ARM_HAS_VFP
-#else
+ NBREG, RESC1,
" ldr A1,AL" COM "double load\n"
" ldr U1,UL\n", },
-#endif
-{ UMUL, INXREG,
+{ UMUL, INCREG | FEATURE_FPA,
SANY, TANY,
SOREG|SNAME, TLDOUBLE,
- NXREG, RESC1,
-#ifdef ARM_HAS_FPA
- " ldfe AL" COM "long double load\n", },
-#elifdef ARM_HAS_VFP
-#else
- " ldr A1,AL" COM "long double load\n"
+ NCREG, RESC1,
+ " ldfe A1,AL" COM "long double load\n", },
+
+{ UMUL, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TLDOUBLE,
+ NCREG, RESC1,
+ COM "not implemented\n", },
+
+{ UMUL, INBREG,
+ SANY, TANY,
+ SOREG|SNAME, TLDOUBLE,
+ NBREG, RESC1,
+ " ldr A1,AL" COM "long double load (soft-float)\n"
" ldr U1,UL\n", },
-#endif
/*
* Logical/branching operators
@@ -1194,41 +1454,59 @@ struct optab table[] = {
0, RESCC,
"ZD", },
-{ OPLOG, FORCC,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
+{ OPLOG, FORCC | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
NSPECIAL, RESCC,
-#ifdef ARM_HAS_FPA
" cmfs AL,AR" COM "float compare\n", },
-#elifdef ARM_HAS_VFP
+
+{ OPLOG, FORCC | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ 0, RESCC,
" fcmps AL,AR" COM "float compare\n", },
-#else
- "ZF", },
-#endif
{ OPLOG, FORCC,
- SXREG, TDOUBLE,
- SXREG, TDOUBLE,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL, RESCC,
+ "ZF", },
+
+{ OPLOG, FORCC | FEATURE_FPA,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
NSPECIAL, RESCC,
-#ifdef ARM_HAS_FPA
" cmfd AL,AR" COM "double compare\n", },
-#elifdef ARM_HAS_VFP
+
+{ OPLOG, FORCC | FEATURE_VFP,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ 0, RESCC,
" fcmpd AL,AR" COM "double compare\n", },
-#else
- "ZF", },
-#endif
{ OPLOG, FORCC,
- SXREG, TLDOUBLE,
- SXREG, TLDOUBLE,
+ SBREG, TDOUBLE,
+ SBREG, TDOUBLE,
+ NSPECIAL, RESCC,
+ "ZF", },
+
+{ OPLOG, FORCC | FEATURE_FPA,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
NSPECIAL, RESCC,
-#ifdef ARM_HAS_FPA
" cmfe AL,AR" COM "ldouble compare\n", },
-#elifdef ARM_HAS_VFP
+
+{ OPLOG, FORCC | FEATURE_VFP,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ 0, RESCC,
" fcmpd AL,AR" COM "double compare\n", },
-#else
+
+{ OPLOG, FORCC,
+ SBREG, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ NSPECIAL, RESCC,
"ZF", },
-#endif
/* AND/OR/ER */
{ AND, INBREG,
@@ -1311,13 +1589,13 @@ struct optab table[] = {
NAREG, RESC1,
" ldrb A1,AL" COM "load uchar from memory\n", },
-{ OPLTYPE, INAREG,
+{ OPLTYPE, INAREG | FEATURE_HALFWORDS,
SANY, TANY,
SOREG|SNAME, TSHORT,
NAREG, RESC1,
" ldrsh A1,AL" COM "load short from memory\n", },
-{ OPLTYPE, INAREG,
+{ OPLTYPE, INAREG | FEATURE_HALFWORDS,
SANY, TANY,
SOREG|SNAME, TUSHORT,
NAREG, RESC1,
@@ -1325,9 +1603,23 @@ struct optab table[] = {
{ OPLTYPE, INAREG,
SANY, TANY,
+ SOREG|SNAME, TSHORT|TUSHORT,
+ 2*NAREG, RESC1,
+ "ZH", },
+
+#if 0
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SCON, TPOINT,
+ NAREG, RESC1,
+ " ldr A1,AL" COM "load integer constant\n", },
+#endif
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
SCON, TANY,
NAREG, RESC1,
- " ldr A1,ZI" COM "load integer constant\n", },
+ "ZI", },
{ OPLTYPE, INBREG,
SANY, TANY,
@@ -1348,40 +1640,61 @@ struct optab table[] = {
" mov A1,AL" COM "load UL:AL into U1:A1\n"
" mov U1,UL\n", },
-{ OPLTYPE, INFREG,
+{ OPLTYPE, INCREG | FEATURE_FPA,
SANY, TANY,
SOREG|SNAME, TFLOAT,
- NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+ NCREG, RESC1,
" ldfs A1,AL" COM "load float\n", },
-#elifdef ARM_HAS_VFP
-#else
- " ldr A1,AL" COM "load float\n", },
-#endif
-{ OPLTYPE, INXREG,
+{ OPLTYPE, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NCREG, RESC1,
+ COM "not implemented\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NAREG, RESC1,
+ " ldr A1,AL" COM "load float (soft-float)\n", },
+
+{ OPLTYPE, INCREG | FEATURE_FPA,
SANY, TANY,
SOREG|SNAME, TDOUBLE,
- NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+ NCREG, RESC1,
" ldfd A1,AL" COM "load double\n", },
-#elifdef ARM_HAS_VFP
-#else
- " ldr A1,AL" COM "load double\n"
+
+{ OPLTYPE, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE,
+ NCREG, RESC1,
+ COM "not implemented\n" },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE,
+ NBREG, RESC1,
+ " ldr A1,AL" COM "load double (soft-float)\n"
" ldr U1,UL\n", },
-#endif
-{ OPLTYPE, INXREG,
+{ OPLTYPE, INCREG | FEATURE_FPA,
SANY, TANY,
SOREG|SNAME, TLDOUBLE,
- NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+ NCREG, RESC1,
" ldfe A1,AL" COM "load ldouble\n", },
-#elifdef ARM_HAS_VFP
-#else
- " ldr A1,AL" COM "load ldouble\n"
+
+{ OPLTYPE, INCREG | FEATURE_VFP,
+ SANY, TANY,
+ SOREG|SNAME, TLDOUBLE,
+ NCREG, RESC1,
+ COM "not implemented\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SOREG|SNAME, TLDOUBLE,
+ NBREG, RESC1,
+ " ldr A1,AL" COM "load ldouble (soft-float)\n"
" ldr U1,UL\n", },
-#endif
/*
* Negate a word.
@@ -1391,7 +1704,7 @@ struct optab table[] = {
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " neg A1,AL" COM "negation\n", },
+ " rsb A1,AL,#0" COM "negation\n", },
{ UMINUS, INBREG,
SBREG, TLONGLONG|TULONGLONG,
@@ -1400,41 +1713,59 @@ struct optab table[] = {
" rsbs A1,AL,#0" COM "64-bit negation\n"
" rsc U1,UL,#0\n", },
-{ UMINUS, INFREG,
- SFREG, TFLOAT,
- SFREG, TFLOAT,
- NSPECIAL|NFREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ UMINUS, INCREG | FEATURE_FPA,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" mvfs A1,AL" COM "float negation\n", },
-#elifdef ARM_HAS_VFP
+
+{ UMINUS, INCREG | FEATURE_VFP,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
" negs A1,AL" COM "float negation\n", },
-#else
+
+{ UMINUS, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
"ZF", },
-#endif
-{ UMINUS, INXREG,
- SXREG, TDOUBLE,
- SXREG, TDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ UMINUS, INCREG | FEATURE_FPA,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" mvfd A1,AL" COM "double negation\n", },
-#elifdef ARM_HAS_VFP
+
+{ UMINUS, INCREG | FEATURE_VFP,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
" negd A1,AL" COM "double negation\n", },
-#else
+
+{ UMINUS, INBREG,
+ SBREG, TDOUBLE,
+ SBREG, TDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
-{ UMINUS, INXREG,
- SXREG, TLDOUBLE,
- SXREG, TLDOUBLE,
- NSPECIAL|NXREG, RESC1,
-#ifdef ARM_HAS_FPA
+{ UMINUS, INCREG | FEATURE_FPA,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" mvfe A1,AL" COM "ldouble negation\n", },
-#elifdef ARM_HAS_VFP
+
+{ UMINUS, INCREG | FEATURE_VFP,
+ SCREG, TLDOUBLE,
+ SCREG, TLDOUBLE,
+ NCREG, RESC1,
" negd A1,AL" COM "ldouble negation\n", },
-#else
+
+{ UMINUS, INBREG,
+ SBREG, TLDOUBLE,
+ SBREG, TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
"ZF", },
-#endif
{ COMPL, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
@@ -1466,13 +1797,13 @@ struct optab table[] = {
" stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", },
{ FUNARG, FOREFF,
- SFREG, TFLOAT,
+ SCREG, TFLOAT,
SANY, TFLOAT,
0, 0,
" stmfd sp!,{AL}" COM "save function arg to stack\n", },
{ FUNARG, FOREFF,
- SXREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
SANY, TDOUBLE|TLDOUBLE,
0, 0,
" stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", },
diff --git a/usr.bin/pcc/cc/cc.1 b/usr.bin/pcc/cc/cc.1
index 0fe730b2a10..75841c134a2 100644
--- a/usr.bin/pcc/cc/cc.1
+++ b/usr.bin/pcc/cc/cc.1
@@ -1,31 +1,32 @@
-.\" $OpenBSD: cc.1,v 1.3 2007/10/16 13:46:30 stefan Exp $
+.\" $OpenBSD: cc.1,v 1.4 2008/04/11 20:45:52 stefan Exp $
.\"
.\" 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
+.\"
+.\" 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
+.\"
+.\" 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
+.Dt CC 1
.Os
.Sh NAME
.Nm cc
.Nd front-end to the C compiler
.Sh SYNOPSIS
.Nm
-.Op Fl cEgkLMPOStvxX
+.Op Fl cEgkLMPOStvXx
.Op Fl fPIC
.Op Fl fpic
+.Op Fl m Ns Ar option
.Op Fl nostartfiles
.Op Fl nostdinc
.Op Fl nostdlib
@@ -41,12 +42,11 @@
.Op Fl o Ar outfile
.Op Fl Wl Ar flags
.Op Ar
-.Pp
.Sh DESCRIPTION
The
.Nm
utility provides a front-end to the
-.Dq portable C compiler.
+.Dq portable C compiler .
Multiple files may be given on the command line.
Unrecognized options are all sent directly to
.Xr ld 1 .
@@ -55,22 +55,22 @@ Unrecognized options are all sent directly to
Filenames that end with
.Sy \&.c
are passed via
-.Xr cpp 1 ->
-.Xr ccom 1 ->
-.Xr as 1 ->
+.Xr cpp 1 -\*[Gt]
+.Xr ccom 1 -\*[Gt]
+.Xr as 1 -\*[Gt]
.Xr ld 1 .
.Pp
Filenames that end with
.Sy \&.i
are passed via
-.Xr ccom 1 ->
-.Xr as 1 ->
+.Xr ccom 1 -\*[Gt]
+.Xr as 1 -\*[Gt]
.Xr ld 1 .
.Pp
Filenames that end with
.Sy \&.s
are passed via
-.Xr as 1 ->
+.Xr as 1 -\*[Gt]
.Xr ld 1 .
.Pp
Filenames that end with
@@ -99,7 +99,7 @@ Only compile or assemble and then stop.
Do not link.
The resulting object output is saved
as a filename with a
-.Dq .o
+.Dq \&.o
suffix unless
.Fl o
option is used.
@@ -146,7 +146,7 @@ Passed to the
preprocessor to add header search directory to override system defaults.
.It Fl include Ar file
Tells the
-.Xr cpp 1
+.Xr cpp 1
preprocessor to include the
.Ar file
during preprocessing.
@@ -162,7 +162,7 @@ See
.Fl fpic
option.
.It Fl L
-.\" TODO
+TODO
.It Fl M
Pass
.Fl M
@@ -170,12 +170,26 @@ flag to
.Xr cpp 1
to generate dependencies for
.Xr make 1 .
+.It Fl m Ns options
+Target-dependent option.
+.Bl -tag -width PowerPC
+.It ARM
+-mlittle-endian -mbig-endian -mfpe=fpa -mfpe=vpf -msoft-float -march=armv1 -march=armv2 -march=armv2a -march=armv3 -march=armv4 -march=armv4t -march=armv4tej -march=armv5 -march=armv6 -march=armv6t2 -march=armv6kz -march=armv6k -march=armv7
+.It HPPA
+.It i386
+.It MIPS
+-mlittle-endian -mbig-endian -mhard-float -msoft-float
+.It PDP-10
+.It PowerPC
+.It Sparc64
+.It VAX
+.El
.It Fl nostartfiles
-.\" TODO
+Do not link with the system startup files (crt0.c, etc.)
.It Fl nostdinc
-.\" TODO
+Do not use the system include paths (/usr/include, etc.)
.It Fl nostdlib
-.\" TODO
+Do not link with the system C library (libc).
.\" implies -nostartfiles ??
.It Fl O
Enable optimizations.
@@ -185,17 +199,18 @@ and
.Fl xtemps
to
.Xr ccom 1 .
-Note: this is unset if
+Note: this is unset if the
.Fl g
-option is set.
+option is used.
.It Fl o Ar outfile
Save result to
.Ar outfile .
.It Fl P
-TODO: what is this?
+TODO
+.\" TODO: what is this?
.\" TODO: Looks like it does cpp only, but I couldn't get it to work for me.
.It Fl pg
-Not implemented.
+Enable profiling on the generated executable.
.It Fl pthread
Defines
.Sy _PTHREADS
@@ -203,15 +218,16 @@ preprocessor directive for
.Xr cpp 1 .
Uses
.Sy -lpthread
-for
-.Xr ld 1 linker.
+for the
+.Xr ld 1
+linker.
.It Fl S
Stop after compilation by
.Xr ccom 1 .
Do not assemble and do not link.
The resulting assembler-language output is saved
as a filename with a
-.Dq .s
+.Dq \&.s
suffix unless the
.Fl o
option is used.
@@ -229,22 +245,22 @@ to
.Xr cpp 1
for traditional C preprocessor syntax.
.It Fl U Ar macro
-Passes to the
+Passes to the
.Xr cpp 1
preprocessor to remove the initial macro definition.
.It Fl v
Outputs the version of
.Nm
-and shows what commands will be ran with their command line arguments.
+and shows what commands will be run with their command line arguments.
.It Fl Wl Ar flags
-Options for the linker
+Options for the linker.
.\" what is ignored? llist?
.It Fl X
Don't remove temporary files on exit.
.It Fl x
TODO
.El
-.Sh Predefined Macros
+.Ss Predefined Macros
A few
macros are predefined by
.Nm
@@ -260,7 +276,7 @@ Set to the major version of
These macros can be used to select code based on
.Xr pcc 1
compatibility.
-See
+See the
.Fl v
option.
.It __PCC_MINOR__
@@ -287,8 +303,8 @@ and
.Sh HISTORY
The
.Nm
-command comes from the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
+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.c b/usr.bin/pcc/cc/cc.c
index 5d57d542369..23cf8beb7a8 100644
--- a/usr.bin/pcc/cc/cc.c
+++ b/usr.bin/pcc/cc/cc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cc.c,v 1.12 2007/11/22 21:47:24 stefan Exp $ */
+/* $OpenBSD: cc.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -96,6 +96,9 @@ char *llist[MAXLIB];
char alist[20];
char *xlist[100];
int xnum;
+char *mlist[100];
+char *idirafter;
+int nm;
int Cflag;
int dflag;
int pflag;
@@ -114,6 +117,7 @@ int Mflag; /* dependencies only */
int pgflag;
int exfail;
int Xflag;
+int Werror;
int nostartfiles, Bstatic;
int nostdinc, nostdlib;
int onlyas;
@@ -125,6 +129,7 @@ char *Bflag;
char *cppadd[] = CPPADD;
char *dynlinker[] = DYNLINKER;
char *crt0file = CRT0FILE;
+char *crt0file_profile = CRT0FILE_PROFILE;
char *startfiles[] = STARTFILES;
char *endfiles[] = ENDFILES;
char *mach = DEFMACH;
@@ -139,6 +144,11 @@ char *libclibs[] = LIBCLIBS;
#else
char *libclibs[] = { "-lc", NULL };
#endif
+#ifdef LIBCLIBS_PROFILE
+char *libclibs_profile[] = LIBCLIBS_PROFILE;
+#else
+char *libclibs_profile[] = { "-lc_p", NULL };
+#endif
#ifndef STARTLABEL
#define STARTLABEL "__start"
#endif
@@ -158,7 +168,12 @@ main(int argc, char *argv[])
switch (argv[i][1]) {
default:
goto passa;
-
+#ifdef notyet
+ /* must add library options first (-L/-l/...) */
+ error("unrecognized option `-%c'", argv[i][1]);
+ break;
+#endif
+
case 'B': /* other search paths for binaries */
Bflag = &argv[i][2];
break;
@@ -190,7 +205,9 @@ main(int argc, char *argv[])
Xflag++;
break;
case 'W': /* Ignore (most of) W-flags */
- if (strncmp(argv[i], "-Wl,", 4) == 0) {
+ if (strncmp(argv[i], "-Werror", 7) == 0) {
+ Werror = 1;
+ } else if (strncmp(argv[i], "-Wl,", 4) == 0) {
/* options to the linker */
t = &argv[i][4];
while ((u = strchr(t, ','))) {
@@ -199,9 +216,13 @@ main(int argc, char *argv[])
t = u;
}
llist[nl++] = t;
+ } else if (strncmp(argv[i], "-Wp,", 4) == 0) {
+ /* preprocessor */
+ if (!strncmp(argv[i], "-Wp,-C", 6))
+ Cflag++;
}
break;
-
+
case 'f': /* GCC compatibility flags */
if (strcmp(argv[i], "-fPIC") == 0)
kflag = F_PIC;
@@ -209,11 +230,11 @@ main(int argc, char *argv[])
kflag = F_pic;
/* silently ignore the rest */
break;
-
+
case 'g': /* create debug output */
gflag++;
break;
-
+
case 'i':
if (strcmp(argv[i], "-isystem") == 0) {
*pv++ = "-S";
@@ -221,14 +242,20 @@ main(int argc, char *argv[])
} else if (strcmp(argv[i], "-include") == 0) {
*pv++ = "-i";
*pv++ = argv[++i];
+ } else if (strcmp(argv[i], "-idirafter") == 0) {
+ idirafter = argv[++i];
} else
goto passa;
break;
-
+
case 'k': /* generate PIC code */
kflag = F_pic;
break;
-
+
+ case 'm': /* target-dependent options */
+ mlist[nm++] = argv[i];
+ break;
+
case 'n': /* handle -n flags */
if (strcmp(argv[i], "-nostdinc") == 0)
nostdinc++;
@@ -240,7 +267,7 @@ main(int argc, char *argv[])
else
goto passa;
break;
-
+
case 'p':
if (strcmp(argv[i], "-pg") == 0)
pgflag++;
@@ -251,9 +278,19 @@ main(int argc, char *argv[])
else
errorx(1, "unknown option %s", argv[i]);
break;
-
+
case 'x':
- xlist[xnum++] = argv[i];
+ t = &argv[i][2];
+ if (*t == 0)
+ t = argv[++i];
+ if (strcmp(t, "c") == 0)
+ ; /* default */
+#ifdef notyet
+ else if (strcmp(t, "c++"))
+ cxxflag;
+#endif
+ else
+ xlist[xnum++] = argv[i];
break;
case 't':
tflag++;
@@ -279,7 +316,7 @@ main(int argc, char *argv[])
case 'c':
cflag++;
break;
-
+
#if 0
case '2':
if(argv[i][2] == '\0')
@@ -298,17 +335,16 @@ main(int argc, char *argv[])
*pv++ = argv[i];
if (argv[i][2] == 0)
*pv++ = argv[++i];
- if (pv >= ptemp+MAXOPT)
- {
+ if (pv >= ptemp+MAXOPT) {
error("Too many DIU options");
--pv;
}
break;
-
+
case 'M':
Mflag++;
break;
-
+
case 'd':
dflag++;
strlcpy(alist, argv[i], sizeof (alist));
@@ -317,7 +353,7 @@ main(int argc, char *argv[])
printf("%s\n", VERSSTR);
vflag++;
break;
-
+
case 's':
if (strcmp(argv[i], "-static") == 0)
Bstatic = 1;
@@ -333,11 +369,10 @@ main(int argc, char *argv[])
else if((c=getsuf(t))=='c' || c=='S' || c=='i' ||
c=='s'|| Eflag) {
clist[nc++] = t;
- if (nc>=MAXFIL)
- {
+ if (nc>=MAXFIL) {
error("Too many source files");
exit(1);
- }
+ }
t = setsuf(t, 'o');
}
@@ -348,11 +383,10 @@ main(int argc, char *argv[])
}
if (j == nl) {
llist[nl++] = t;
- if (nl >= MAXLIB)
- {
+ if (nl >= MAXLIB) {
error("Too many object/library files");
exit(1);
- }
+ }
if (getsuf(t)=='o')
nxo++;
}
@@ -434,6 +468,10 @@ main(int argc, char *argv[])
av[na++] = *pv;
if (!nostdinc)
av[na++] = "-S", av[na++] = STDINC;
+ if (idirafter) {
+ av[na++] = "-I";
+ av[na++] = idirafter;
+ }
av[na++] = clist[i];
if (!Eflag && !Mflag)
av[na++] = tmp4;
@@ -457,16 +495,22 @@ main(int argc, char *argv[])
av[na++]= "ccom";
if (vflag)
av[na++] = "-v";
+ if (pgflag)
+ av[na++] = "-p";
if (gflag)
av[na++] = "-g";
if (kflag)
av[na++] = "-k";
+ if (Werror)
+ av[na++] = "-Werror";
if (Oflag) {
av[na++] = "-xtemps";
av[na++] = "-xdeljumps";
}
for (j = 0; j < xnum; j++)
av[na++] = xlist[j];
+ for (j = 0; j < nm; j++)
+ av[na++] = mlist[j];
if (getsuf(clist[i])=='i')
av[na++] = clist[i];
else
@@ -554,6 +598,7 @@ nocom:
}
if (!nostartfiles) {
av[j++] = crt0file;
+ av[j++] = pgflag ? crt0file_profile : crt0file;
for (i = 0; startfiles[i]; i++)
av[j++] = startfiles[i];
}
@@ -571,9 +616,17 @@ nocom:
#endif
if (pthreads)
av[j++] = "-lpthread";
- if (!nostdlib)
+ if (!nostdlib) {
+ if (pgflag) {
+ for (i = 0; libclibs_profile[i]; i++)
+ av[j++] = libclibs_profile[i];
+ } else {
+ for (i = 0; libclibs[i]; i++)
+ av[j++] = libclibs[i];
+ }
for (i = 0; libclibs[i]; i++)
av[j++] = libclibs[i];
+ }
if (!nostartfiles) {
for (i = 0; endfiles[i]; i++)
av[j++] = endfiles[i];
diff --git a/usr.bin/pcc/ccconfig.h b/usr.bin/pcc/ccconfig.h
index 24cbd11f762..c7fe0569ba6 100644
--- a/usr.bin/pcc/ccconfig.h
+++ b/usr.bin/pcc/ccconfig.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ccconfig.h,v 1.3 2007/10/22 13:40:08 otto Exp $ */
+/* $OpenBSD: ccconfig.h,v 1.4 2008/04/11 20:45:51 stefan Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
@@ -35,6 +35,7 @@
#define CPPADD { "-D__OpenBSD__", "-D__unix__", NULL }
#define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.so", NULL }
#define CRT0FILE "/usr/lib/crt0.o"
+#define CRT0FILE_PROFILE "/usr/lib/gcrt0.o"
#define STARTFILES { "/usr/lib/crtbegin.o", NULL }
#define ENDFILES { "/usr/lib/crtend.o", NULL }
diff --git a/usr.bin/pcc/ccom/ccom.1 b/usr.bin/pcc/ccom/ccom.1
index fee05e09a80..bc7a642b821 100644
--- a/usr.bin/pcc/ccom/ccom.1
+++ b/usr.bin/pcc/ccom/ccom.1
@@ -1,20 +1,20 @@
-.\" $OpenBSD: ccom.1,v 1.2 2007/10/20 18:23:35 otto Exp $
+.\" $OpenBSD: ccom.1,v 1.3 2008/04/11 20:45:52 stefan Exp $
."\
.\" 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
+.\" 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
+.\"
+.\" 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
+.Dt CCOM 1
.Os
.Sh NAME
.Nm ccom
@@ -28,14 +28,15 @@
.Op Fl Z 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.
+It is
+.Em not
+intended to be run directly.
.Pp
.Nm
reads the C source from
@@ -65,23 +66,28 @@ Display version.
.It Fl W Ar flags
Report warnings.
(Do some basic checks.)
-NOTE! These are subject to change RSN!
+.Em NOTE!
+.Em These are subject to change RSN!
.Ar flags
is one or more of the following:
.Bl -tag -width Ds
+.It Sy error
+Report all warnings as errors.
.It Sy implicit
Implies
.Sy implicit-function-declaration
and
.Sy implicit-int .
.It Sy implicit-function-declaration
-Report if no prototype for function.
+Report if no prototype was declared for a function.
.It Sy implicit-int
TODO
.It Sy missing-prototypes
TODO
.It Sy strict-prototypes
TODO
+.It Sy W
+Enable all warnings.
.El
.\"
.It Fl X Ar flags
@@ -92,7 +98,7 @@ is one or more of the following:
.It Sy b
Building of parse trees
.It Sy d
-Declarations (multiple
+Declarations (using multiple
.Sy d
flags gives more output)
.It Sy e
@@ -115,23 +121,27 @@ Target-specific flag, used in machine-dependent code
.\"
.It Fl x Ar optimizations
.Ar optimizations
-is one or more of the following:
+is one of the following:
.\" TODO: reword this, since multiple terms don't go with one -x switch??
.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.
+Convert statements into SSA form for optimization.
+Not yet finished.
.It Sy tailcall
Currently not implemented.
.It Sy temps
-Setting this flag allows variables to be put into registers, for further
+Setting this flag allows variables to be put into registers, for further
optimization by the register allocator.
.El
+The
+.Fl x
+flag can be passed multiple times to set different options.
.\"
.It Fl Z Ar flags
Code generator (pass2) specific debugging where
-.Ar flags
+.Ar flags
is one or more of the following:
.Bl -tag -width Ds
.It Sy b
@@ -155,7 +165,7 @@ Type matching in instruction generator
.It Sy u
Sethi-Ullman computations
.It Sy x
-Target-specific flag, used in machine-dependent code
+Target-specific flag, used in machine-dependent code
.El
.El
.Sh SEE ALSO
@@ -165,8 +175,8 @@ Target-specific flag, used in machine-dependent code
.Sh HISTORY
The
.Nm
-compiler is based on the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
+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
@@ -174,7 +184,7 @@ 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
+part of a project by undergraduate students at Lulea University of
Technology.
.Pp
This product includes software developed or owned by Caldera
diff --git a/usr.bin/pcc/ccom/cgram.y b/usr.bin/pcc/ccom/cgram.y
index 79c1a3963e7..2af2844b3aa 100644
--- a/usr.bin/pcc/ccom/cgram.y
+++ b/usr.bin/pcc/ccom/cgram.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: cgram.y,v 1.8 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: cgram.y,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
@@ -147,7 +147,9 @@ static int fun_inline; /* Reading an inline function */
int oldstyle; /* Current function being defined */
int noretype;
static struct symtab *xnf;
-extern int enummer;
+extern int enummer, tvaloff;
+extern struct rstack *rpole;
+static int ctval;
static NODE *bdty(int op, ...);
static void fend(void);
@@ -161,9 +163,14 @@ static void adddef(void);
static void savebc(void);
static void swstart(int, TWORD);
static void genswitch(int, TWORD, struct swents **, int);
-static NODE * structref(NODE *p, int f, char *name);
+static NODE *structref(NODE *p, int f, char *name);
static char *mkpstr(char *str);
static struct symtab *clbrace(NODE *);
+static NODE *cmop(NODE *l, NODE *r);
+static NODE *xcmop(NODE *out, NODE *in, NODE *str);
+static void mkxasm(char *str, NODE *p);
+static NODE *xasmop(char *str, NODE *p);
+
/*
* State for saving current switch state (when nested switches).
@@ -198,7 +205,7 @@ struct savbc {
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
+ designator_list designator xasm oplist oper cnstr
%type <strp> string wstring C_STRING C_WSTRING
%type <rp> str_head
%type <symp> xnfdeclarator clbrace enum_head
@@ -328,6 +335,9 @@ type_qualifier_list:
direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
| '(' declarator ')' { $$ = $2; }
| direct_declarator '[' nocon_e ']' {
+ $3 = optim($3);
+ if (blevel == 0 && !nncon($3))
+ uerror("array size not constant");
if (!ISINTEGER($3->n_type))
werror("array size is not an integer");
else if ($3->n_op == ICON && $3->n_lval < 0) {
@@ -337,32 +347,43 @@ direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
$$ = block(LB, $1, $3, INT, 0, MKSUE(INT));
}
| direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
- | direct_declarator '(' notype parameter_type_list ')' {
+ | direct_declarator '(' fundcl parameter_type_list ')' {
+ if (blevel-- > 1)
+ symclear(blevel);
$$ = bdty(CALL, $1, $4);
}
- | direct_declarator '(' notype identifier_list ')' {
+ | direct_declarator '(' fundcl identifier_list ')' {
+ if (blevel-- > 1)
+ symclear(blevel);
$$ = bdty(CALL, $1, $4);
if (blevel != 0)
uerror("function declaration in bad context");
oldstyle = 1;
}
- | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); }
+ | direct_declarator '(' ')' {
+ ctval = tvaloff;
+ $$ = bdty(UCALL, $1);
+ }
;
-notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ }
+fundcl: { if (++blevel == 1) argoff = ARGINIT; ctval = tvaloff; }
;
-identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; }
+identifier_list: C_NAME {
+ $$ = mkty(FARG, NULL, MKSUE(INT));
+ $$->n_sp = lookup($1, 0);
+ defid($$, PARAM);
+ }
| identifier_list ',' C_NAME {
- $$ = bdty(NAME, $3);
- $$->n_type = FARG;
+ $$ = mkty(FARG, NULL, MKSUE(INT));
+ $$->n_sp = lookup($3, 0);
+ defid($$, PARAM);
$$ = 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; }
@@ -388,8 +409,18 @@ parameter_list: parameter_declaration { $$ = $1; }
*/
parameter_declaration:
declaration_specifiers declarator {
+ if ($1->n_lval == AUTO || $1->n_lval == TYPEDEF ||
+ $1->n_lval == EXTERN || $1->n_lval == STATIC)
+ uerror("illegal parameter class");
$$ = tymerge($1, $2);
+ if (blevel == 1) {
+ $$->n_sp = lookup((char *)$$->n_sp, 0);/* XXX */
+ if (ISFTN($$->n_type))
+ $$->n_type = INCREF($$->n_type);
+ defid($$, PARAM);
+ }
nfree($1);
+
}
| declaration_specifiers abstract_declarator {
$$ = tymerge($1, $2);
@@ -418,14 +449,14 @@ direct_abstract_declarator:
$$ = bdty(LB, $1, $3);
}
| '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
- | '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, bdty(NAME, NULL), $3);
+ | '(' parameter_type_list ')' {
+ $$ = bdty(CALL, bdty(NAME, NULL), $2);
}
| direct_abstract_declarator '(' ')' {
$$ = bdty(UCALL, $1);
}
- | direct_abstract_declarator '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, $1, $4);
+ | direct_abstract_declarator '(' parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $3);
}
;
@@ -496,14 +527,15 @@ moe_list: moe
;
moe: C_NAME { moedef($1); }
+ | C_TYPENAME { moedef($1); }
| C_NAME '=' con_e { enummer = $3; moedef($1); }
+ | C_TYPENAME '=' con_e { enummer = $3; moedef($1); }
;
struct_dcl: str_head '{' struct_dcl_list '}' empty {
$$ = dclstruct($1);
}
| C_STRUCT C_NAME { $$ = rstruct($2,$1); }
- | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); }
| str_head '{' '}' {
#ifndef GCC_COMPAT
werror("gcc extension");
@@ -518,7 +550,6 @@ empty: { /* Get yacc read the next token before reducing */ }
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
@@ -549,30 +580,21 @@ struct_declarator_list:
struct_declarator: declarator {
tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */
- defid($1, $<nodep>0->n_lval);
+ soumemb($1, (char *)$1->n_sp,
+ $<nodep>0->n_lval); /* XXX */
nfree($1);
}
| ':' con_e {
- if (!(instruct&INSTRUCT))
- uerror( "field outside of structure" );
- if ($2 < 0 || $2 >= FIELD) {
- uerror("illegal field size");
+ if (fldchk($2))
$2 = 1;
- }
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" );
+ if (fldchk($3))
$3 = 1;
- }
if ($1->n_op == NAME) {
tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME);
- defid($1, FIELD|$3);
+ soumemb($1, (char *)$1->n_sp, FIELD | $3);
nfree($1);
} else
uerror("illegal declarator");
@@ -632,7 +654,11 @@ designator: '[' con_e ']' {
}
$$ = bdty(LB, NULL, $2);
}
- | C_STROP C_NAME { $$ = bdty(NAME, $2); }
+ | C_STROP C_NAME {
+ if ($1 != DOT)
+ uerror("invalid designator");
+ $$ = bdty(NAME, $2);
+ }
;
optcomma : /* VOID */
@@ -696,7 +722,7 @@ begin: '{' {
}
;
-statement: e ';' { ecomp( $1 ); }
+statement: e ';' { ecomp( $1 ); symclear(blevel); }
| compoundstmt
| ifprefix statement { plabel($1); reached = 1; }
| ifelprefix statement {
@@ -799,8 +825,26 @@ statement: e ';' { ecomp( $1 ); }
;
asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); }
+ | C_ASM '(' string xasm ')' { mkxasm($3, $4); }
+ ;
+
+xasm: ':' oplist { $$ = xcmop($2, NIL, NIL); }
+ | ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); }
+ | ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); }
+ ;
+
+oplist: /* nothing */ { $$ = NIL; }
+ | oper { $$ = $1; }
;
+oper: string '(' e ')' { $$ = xasmop($1, $3); }
+ | oper ',' string '(' e ')' { $$ = cmop($1, xasmop($3, $5)); }
+ ;
+
+cnstr: string { $$ = xasmop($1, bcon(0)); }
+ | cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); }
+ ;
+
label: C_NAME ':' { deflabel($1); reached = 1; }
| C_CASE e ':' { addcase($2); reached = 1; }
| C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
@@ -861,7 +905,23 @@ forprefix: C_FOR '(' .e ';' .e ';' {
else
flostat |= FLOOP;
}
+ | C_FOR '(' incblev declaration .e ';' {
+ blevel--;
+ savebc();
+ contlab = getlab();
+ brklab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ if ($5)
+ cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
+ else
+ flostat |= FLOOP;
+ }
;
+
+incblev: { blevel++; }
+ ;
+
switchpart: C_SWITCH '(' e ')' {
NODE *p;
int num;
@@ -887,14 +947,14 @@ switchpart: C_SWITCH '(' e ')' {
}
;
/* EXPRESSIONS */
-con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- $$ = icons( $2 );
- instruct=$<intval>1;
+con_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' {
+ $$ = icons($2);
+ rpole = $<rp>1;
}
;
-nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- instruct=$<intval>1;
+nocon_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' {
+ rpole = $<rp>1;
$$ = $2;
}
;
@@ -979,7 +1039,7 @@ term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); }
| C_SIZEOF '(' cast_type ')' %prec C_SIZEOF {
$$ = doszof($3);
}
- | '(' cast_type ')' clbrace init_list '}' {
+ | '(' cast_type ')' clbrace init_list optcomma '}' {
endinit();
spname = $4;
$$ = buildtree(NAME, NIL, NIL);
@@ -1294,6 +1354,8 @@ init_declarator(NODE *tn, NODE *p, int assign)
if (assign) {
defid(typ, class);
typ->n_sp->sflags |= SASG;
+ if (typ->n_sp->sflags & SDYNARRAY)
+ uerror("can't initialize dynamic arrays");
lcommdel(typ->n_sp);
} else {
nidcl(typ, class);
@@ -1315,10 +1377,18 @@ fundef(NODE *tp, NODE *p)
{
extern int prolab;
struct symtab *s;
+ NODE *q = p;
int class = tp->n_lval, oclass;
char *c;
- /* Enter function args before they are clobbered in tymerge() */
+ while (q->n_op == UMUL)
+ q = q->n_left;
+ if (q->n_op != CALL && q->n_op != UCALL) {
+ uerror("invalid function definition");
+ p = bdty(UCALL, p);
+ }
+
+ /* Save function args before they are clobbered in tymerge() */
/* Typecheck against prototype will be done in defid(). */
ftnarg(p);
@@ -1344,8 +1414,8 @@ fundef(NODE *tp, NODE *p)
prolab = getlab();
c = cftnsp->soname;
send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
- cftnsp->sclass == EXTDEF, prolab);
- blevel = 1;
+ cftnsp->sclass == EXTDEF, prolab, ctval);
+ blevel++;
#ifdef STABS
if (gflag)
stabs_func(s);
@@ -1409,9 +1479,10 @@ static char *
mkpstr(char *str)
{
char *s, *os;
- int v, l = strlen(str)+1;
+ int v, l = strlen(str)+3; /* \t + \n + \0 */
os = s = isinlining ? permalloc(l) : tmpalloc(l);
+ *s++ = '\t';
for (; *str; ) {
if (*str++ == '\\')
v = esccon(&str);
@@ -1419,6 +1490,7 @@ mkpstr(char *str)
v = str[-1];
*s++ = v;
}
+ *s++ = '\n';
*s = 0;
return os;
}
@@ -1445,3 +1517,90 @@ clbrace(NODE *p)
beginit(sp);
return sp;
}
+
+/* Support for extended assembler a' la' gcc style follows below */
+
+static NODE *
+cmop(NODE *l, NODE *r)
+{
+ return block(CM, l, r, INT, 0, MKSUE(INT));
+}
+
+static NODE *
+voidcon(void)
+{
+ return block(ICON, NIL, NIL, STRTY, 0, MKSUE(VOID));
+}
+
+static NODE *
+xmrg(NODE *out, NODE *in)
+{
+ NODE *p = in;
+
+ if (p->n_op == XARG) {
+ in = cmop(out, p);
+ } else {
+ while (p->n_left->n_op == CM)
+ p = p->n_left;
+ p->n_left = cmop(out, p->n_left);
+ }
+ return in;
+}
+
+/*
+ * Put together in and out node lists in one list, and balance it with
+ * the constraints on the right side of a CM node.
+ */
+static NODE *
+xcmop(NODE *out, NODE *in, NODE *str)
+{
+ NODE *p, *q;
+
+ if (out) {
+ /* D out-list sanity check */
+ for (p = out; p->n_op == CM; p = p->n_left) {
+ q = p->n_right;
+ if (q->n_name[0] != '=')
+ uerror("output missing =");
+ }
+ if (p->n_name[0] != '=')
+ uerror("output missing =");
+ if (in == NIL)
+ p = out;
+ else
+ p = xmrg(out, in);
+ } else if (in) {
+ p = in;
+ } else
+ p = voidcon();
+
+ if (str == NIL)
+ str = voidcon();
+ return cmop(p, str);
+}
+
+/*
+ * Generate a XARG node based on a string and an expression.
+ */
+static NODE *
+xasmop(char *str, NODE *p)
+{
+
+ p = block(XARG, p, NIL, INT, 0, MKSUE(INT));
+ p->n_name = str;
+ return p;
+}
+
+/*
+ * Generate a XASM node based on a string and an expression.
+ */
+static void
+mkxasm(char *str, NODE *p)
+{
+ NODE *q;
+
+ q = block(XASM, p->n_left, p->n_right, INT, 0, MKSUE(INT));
+ q->n_name = str;
+ nfree(p);
+ ecomp(q);
+}
diff --git a/usr.bin/pcc/ccom/gcc_compat.c b/usr.bin/pcc/ccom/gcc_compat.c
index 4148cd4ead4..1f8920623e6 100644
--- a/usr.bin/pcc/ccom/gcc_compat.c
+++ b/usr.bin/pcc/ccom/gcc_compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gcc_compat.c,v 1.4 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: gcc_compat.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -50,6 +50,7 @@ static struct kw {
{ "__const", NULL, 0 },
{ "__asm__", NULL, C_ASM },
{ "__inline__", NULL, C_FUNSPEC },
+ { "__thread", NULL, 0 },
{ NULL, NULL, 0 },
};
@@ -63,12 +64,15 @@ gcc_init()
}
+#define TS "\n#pragma tls\n# %d\n"
+#define TLLEN sizeof(TS)+10
/*
* See if a string matches a gcc keyword.
*/
int
gcc_keyword(char *str, NODE **n)
{
+ char tlbuf[TLLEN], *tw;
struct kw *kwp;
int i;
@@ -86,6 +90,12 @@ gcc_keyword(char *str, NODE **n)
case 3: /* __const */
*n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
return C_QUALIFIER;
+ case 6: /* __thread */
+ snprintf(tlbuf, TLLEN, TS, lineno);
+ tw = &tlbuf[strlen(tlbuf)];
+ while (tw > tlbuf)
+ cunput(*--tw);
+ return -1;
}
cerror("gcc_keyword");
return 0;
diff --git a/usr.bin/pcc/ccom/init.c b/usr.bin/pcc/ccom/init.c
index 8e800c84cb9..f4ced795f23 100644
--- a/usr.bin/pcc/ccom/init.c
+++ b/usr.bin/pcc/ccom/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.6 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: init.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
@@ -118,8 +118,8 @@ int idebug;
*/
static struct instk {
struct instk *in_prev; /* linked list */
- struct symtab **in_xp; /* member in structure initializations */
- struct symtab *in_sym; /* stab index */
+ struct symtab *in_lnk; /* member in structure initializations */
+ struct symtab *in_sym; /* symtab index */
union dimfun *in_df; /* dimenston of array */
TWORD in_t; /* type for this level */
int in_n; /* number of arrays seen so far */
@@ -231,7 +231,7 @@ beginit(struct symtab *sp)
curll = ll = getll(); /* at least first entry in list */
/* first element */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_n = 0;
is->in_t = sp->stype;
is->in_sym = sp;
@@ -279,22 +279,22 @@ stkpush(void)
is->in_n = 0;
if (pstk == NULL) {
/* stack empty */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_t = sp->stype;
is->in_sym = sp;
is->in_df = sp->sdf;
} else if (ISSOU(t)) {
- sq = *pstk->in_xp;
+ sq = pstk->in_lnk;
if (sq == NULL) {
uerror("excess of initializing elements");
} else {
- is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0;
+ is->in_lnk = ISSOU(sq->stype) ? sq->ssue->sylnk : 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_lnk = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->sylnk : 0;
is->in_t = DECREF(t);
is->in_sym = sp;
if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) {
@@ -329,9 +329,9 @@ stkpop(void)
printf("stkpop\n");
#endif
for (; pstk; pstk = pstk->in_prev) {
- if (pstk->in_t == STRTY && pstk->in_xp[0] != NULL) {
- pstk->in_xp++;
- if (*pstk->in_xp != NULL)
+ if (pstk->in_t == STRTY && pstk->in_lnk != NULL) {
+ pstk->in_lnk = pstk->in_lnk->snext;
+ if (pstk->in_lnk != NULL)
break;
}
if (ISSOU(pstk->in_t) && pstk->in_fl)
@@ -716,8 +716,9 @@ irbrace()
if (ISARY(pstk->in_t))
pstk->in_n = pstk->in_df->ddim;
else if (pstk->in_t == STRTY) {
- while (pstk->in_xp[0] != NULL && pstk->in_xp[1] != NULL)
- pstk->in_xp++;
+ while (pstk->in_lnk != NULL &&
+ pstk->in_lnk->snext != NULL)
+ pstk->in_lnk = pstk->in_lnk->snext;
}
stkpop();
return;
@@ -751,11 +752,11 @@ mkstack(NODE *p)
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)
+ if (pstk->in_lnk) {
+ for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext)
+ if (pstk->in_lnk->sname == (char *)p->n_sp)
break;
- if (pstk->in_xp[0] == NULL)
+ if (pstk->in_lnk == NULL)
uerror("member missing");
} else {
uerror("not a struct/union");
@@ -783,7 +784,7 @@ desinit(NODE *p)
pstk = pstk->in_prev; /* Empty stack */
if (ISSOU(pstk->in_t))
- pstk->in_xp = pstk->in_sym->ssue->suelem;
+ pstk->in_lnk = pstk->in_sym->ssue->sylnk;
mkstack(p); /* Setup for assignment */
@@ -889,8 +890,8 @@ prtstk(struct instk *in)
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);
+ if (in->in_lnk)
+ printf("curel %s ", in->in_lnk->sname);
else
printf("END struct");
}
diff --git a/usr.bin/pcc/ccom/main.c b/usr.bin/pcc/ccom/main.c
index cd3604cc12c..de88379c9e8 100644
--- a/usr.bin/pcc/ccom/main.c
+++ b/usr.bin/pcc/ccom/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.4 2007/12/09 18:50:01 ragge Exp $ */
+/* $OpenBSD: main.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2002 Anders Magnusson. All rights reserved.
@@ -34,7 +34,7 @@
#include "pass1.h"
#include "pass2.h"
-int sflag, nflag, oflag, kflag;
+int sflag, nflag, oflag, kflag, pflag;
int lflag, odebug, rdebug, s2debug, udebug, x2debug;
#if !defined(MULTIPASS) || defined(PASST)
int iTflag, oTflag;
@@ -92,6 +92,10 @@ Wflags(char *str)
Wimplicit_int = Wimplicit_function_declaration = 1;
return;
}
+ if (strcmp(str, "error") == 0) {
+ warniserr = 1;
+ return;
+ }
all = strcmp(str, "W") == 0;
for (i = 0; flagstr[i].n; i++)
if (all || strcmp(flagstr[i].n, str) == 0) {
@@ -112,7 +116,7 @@ main(int argc, char *argv[])
prgname = argv[0];
- while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:kvm:")) != -1)
+ while ((ch = getopt(argc, argv, "OT:VW:X:Z:gklm:psvwx:")) != -1)
switch (ch) {
#if !defined(MULTIPASS) || defined(PASS1)
case 'X':
@@ -202,6 +206,10 @@ main(int argc, char *argv[])
gflag = 1;
break;
+ case 'p': /* Profiling */
+ pflag = 1;
+ break;
+
case 's': /* Statistics */
++sflag;
break;
diff --git a/usr.bin/pcc/ccom/optim.c b/usr.bin/pcc/ccom/optim.c
index e4b48144cd5..6ae9991a6c4 100644
--- a/usr.bin/pcc/ccom/optim.c
+++ b/usr.bin/pcc/ccom/optim.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: optim.c,v 1.2 2007/11/18 17:39:55 ragge Exp $ */
+/* $OpenBSD: optim.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -43,8 +43,6 @@
# 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 */
diff --git a/usr.bin/pcc/ccom/pass1.h b/usr.bin/pcc/ccom/pass1.h
index aa9bb3758b9..960e0f40de1 100644
--- a/usr.bin/pcc/ccom/pass1.h
+++ b/usr.bin/pcc/ccom/pass1.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass1.h,v 1.8 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: pass1.h,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -90,6 +90,9 @@ extern char *scnames(int);
#define SINLINE 00400
#define STNODE 01000
#define SASG 04000
+#define SLOCAL1 010000
+#define SLOCAL2 020000
+#define SLOCAL3 040000
/* alignment of initialized quantities */
#ifndef AL_INIT
@@ -116,7 +119,7 @@ union dimfun {
*/
struct suedef {
int suesize; /* Size of the struct */
- struct symtab **suelem;/* points to the list of elements */
+ struct symtab *sylnk; /* the list of elements */
int suealign; /* Alignment of this struct */
};
@@ -206,12 +209,6 @@ extern int pragma_packed, pragma_aligned;
extern char *pragma_renamed;
/*
- * Flags used in structures/unions
- */
-#define INSTRUCT 02
-#define INUNION 04
-
-/*
* Flags used in the (elementary) flow analysis ...
*/
#define FBRK 02
@@ -256,6 +253,7 @@ OFFSZ tsize(TWORD, union dimfun *, struct suedef *),
NODE * typenode(NODE *new);
void spalloc(NODE *, NODE *, OFFSZ);
char *exname(char *);
+extern struct rstack *rpole;
int oalloc(struct symtab *p, int *poff);
void deflabel(char *);
@@ -278,6 +276,7 @@ char *addname(char *);
char *newstring(char *, int len);
void symclear(int level);
struct symtab *hide(struct symtab *p);
+void soumemb(NODE *, char *, int);
int talign(unsigned int, struct suedef *);
void bfcode(struct symtab **, int);
int chkftn(union arglist *, union arglist *);
@@ -305,7 +304,6 @@ 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);
@@ -321,6 +319,10 @@ int mypragma(char **);
void fixdef(struct symtab *);
int cqual(TWORD t, TWORD q);
void defloc(struct symtab *);
+int fldchk(int sz);
+int nncon(NODE *);
+void cunput(char c);
+
#ifdef GCC_COMPAT
void gcc_init(void);
diff --git a/usr.bin/pcc/ccom/pftn.c b/usr.bin/pcc/ccom/pftn.c
index f70636f73d7..55d2925688e 100644
--- a/usr.bin/pcc/ccom/pftn.c
+++ b/usr.bin/pcc/ccom/pftn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pftn.c,v 1.12 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: pftn.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -73,18 +73,16 @@
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 */
+ argoff; /* the next unused argument offset */
int retlab = NOLAB; /* return label for subroutine */
int brklab;
int contlab;
int flostat;
-int instruct, blevel;
+int blevel;
int reached, prolab;
struct params;
@@ -99,12 +97,11 @@ struct params;
*/
struct rstack {
struct rstack *rnext;
- int rinstruct;
- int rclass;
- int rstrucoff;
- struct params *rlparam;
+ int rsou;
+ int rstr;
struct symtab *rsym;
-};
+ struct symtab *rb;
+} *rpole;
/*
* Linked list for parameter (and struct elements) declaration.
@@ -120,6 +117,7 @@ static int nparams;
static NODE *arrstk[10];
static int arrstkp;
static int intcompare;
+static NODE *parlink;
void fixtype(NODE *p, int class);
int fixclass(int class, TWORD type);
@@ -187,14 +185,13 @@ defid(NODE *q, int class)
if (blevel == 1) {
switch (class) {
default:
- if (!(class&FIELD))
+ if (!(class&FIELD) && !ISFTN(type))
uerror("declared argument %s missing",
p->sname );
case MOS:
- case STNAME:
case MOU:
- case UNAME:
case TYPEDEF:
+ case PARAM:
;
}
}
@@ -242,9 +239,7 @@ defid(NODE *q, int class)
#endif
/* check that redeclarations are to the same structure */
- if ((temp == STRTY || temp == UNIONTY) &&
- p->ssue != q->n_sue &&
- class != STNAME && class != UNAME) {
+ if ((temp == STRTY || temp == UNIONTY) && p->ssue != q->n_sue) {
goto mismatch;
}
@@ -255,15 +250,9 @@ defid(NODE *q, int class)
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) {
+ if (class & FIELD)
+ return;
+ switch(class) {
case EXTERN:
switch( scl ){
@@ -312,15 +301,7 @@ defid(NODE *q, int class)
case MOU:
case MOS:
- if (scl == class) {
- if (oalloc(p, &strucoff))
- break;
- if (class == MOU)
- strucoff = 0;
- ssave(p);
- return;
- }
- break;
+ return;
case EXTDEF:
switch (scl) {
@@ -333,16 +314,10 @@ defid(NODE *q, int class)
}
break;
- case STNAME:
- case UNAME:
- if (scl != class)
- break;
- if (p->ssue->suesize == 0)
- return; /* previous entry just a mention */
- break;
-
case AUTO:
case REGISTER:
+ if (blevel == slev)
+ goto redec;
; /* mismatch.. */
}
@@ -354,12 +329,12 @@ defid(NODE *q, int class)
if (blevel == slev || class == EXTERN || class == FORTRAN ||
class == UFORTRAN) {
if (ISSTR(class) && !ISSTR(p->sclass)) {
- uerror("redeclaration of %s", p->sname);
+redec: uerror("redeclaration of %s", p->sname);
return;
}
}
if (blevel == 0)
- uerror("redeclaration of %s", p->sname);
+ goto redec;
q->n_sp = p = hide(p);
enter: /* make a new entry */
@@ -373,27 +348,9 @@ defid(NODE *q, int class)
p->sclass = class;
p->slevel = blevel;
p->soffset = NOOFFSET;
- if (class == STNAME || class == UNAME) {
- p->ssue = permalloc(sizeof(struct suedef));
- suedefcnt++;
- p->ssue->suesize = 0;
- p->ssue->suelem = NULL;
- p->ssue->suealign = ALSTRUCT;
- } else {
- if (q->n_sue == NULL)
- cerror("q->n_sue == NULL");
- p->ssue = q->n_sue;
-#if 0
- switch (BTYPE(type)) {
- case STRTY:
- case UNIONTY:
- p->ssue = q->n_sue;
- break;
- default:
- p->ssue = MKSUE(BTYPE(type));
- }
-#endif
- }
+ if (q->n_sue == NULL)
+ cerror("q->n_sue == NULL");
+ p->ssue = q->n_sue;
/* copy dimensions */
p->sdf = q->n_df;
@@ -404,7 +361,6 @@ defid(NODE *q, int class)
/* allocate offsets */
if (class&FIELD) {
(void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */
- ssave(p);
} else switch (class) {
case REGISTER:
@@ -416,6 +372,18 @@ defid(NODE *q, int class)
else
oalloc(p, &autooff);
break;
+ case PARAM:
+ if (ISARY(p->stype)) {
+ /* remove array type on parameters before oalloc */
+ p->stype += (PTR-ARY);
+ p->sdf++;
+ }
+ if (arrstkp)
+ dynalloc(p, &argoff);
+ else
+ oalloc(p, &argoff);
+ break;
+
case STATIC:
case EXTDEF:
case EXTERN:
@@ -429,10 +397,9 @@ defid(NODE *q, int class)
case MOU:
case MOS:
- oalloc(p, &strucoff);
+ oalloc(p, &rpole->rstr);
if (class == MOU)
- strucoff = 0;
- ssave(p);
+ rpole->rstr = 0;
break;
}
@@ -458,13 +425,10 @@ ssave(struct symtab *sym)
p->next = NULL;
p->sym = sym;
- if (lparam == NULL) {
- p->prev = (struct params *)&lpole;
+ if ((p->prev = lparam) == NULL)
lpole = p;
- } else {
+ else
lparam->next = p;
- p->prev = lparam;
- }
lparam = p;
}
@@ -476,6 +440,7 @@ ftnend()
{
extern struct savbc *savbc;
extern struct swdef *swpole;
+ extern int tvaloff;
char *c;
if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
@@ -484,7 +449,7 @@ ftnend()
c = cftnsp->soname;
SETOFF(maxautooff, ALCHAR);
send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c,
- cftnsp->stype, cftnsp->sclass == EXTDEF, retlab);
+ cftnsp->stype, cftnsp->sclass == EXTDEF, retlab, tvaloff);
}
tcheck();
@@ -510,6 +475,10 @@ ftnend()
tmpfree(); /* Release memory resources */
}
+static struct symtab nulsym = {
+ { NULL, 0, 0, 0, 0 }, "null", "null", INT, 0, NULL, NULL
+};
+
void
dclargs()
{
@@ -517,15 +486,12 @@ dclargs()
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)
+ if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
goto done;
/*
@@ -536,11 +502,13 @@ dclargs()
parr = tmpalloc(sizeof(struct symtab *) * nparams);
if (nparams)
- for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole;
- a = a->prev) {
-
+ for (a = lparam, i = 0; a != NULL; a = a->prev) {
p = a->sym;
parr[i++] = p;
+ if (p == NULL) {
+ uerror("parameter %d name missing", i);
+ p = &nulsym; /* empty symtab */
+ }
if (p->stype == FARG) {
p->stype = INT;
p->ssue = MKSUE(INT);
@@ -552,8 +520,6 @@ dclargs()
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);
@@ -579,59 +545,47 @@ dclargs()
if (chkftn(al, alb))
uerror("function doesn't match prototype");
intcompare = 0;
+
+ }
+
+ if (oldstyle && nparams) {
+ /* Must recalculate offset for oldstyle args here */
+ argoff = ARGINIT;
+ for (i = 0; i < nparams; i++) {
+ parr[i]->soffset = NOOFFSET;
+ oalloc(parr[i], &argoff);
+ }
}
+
done: cendarg();
- c = cftnsp->soname;
-#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);
plabel(getlab()); /* used when spilling */
+ if (parlink)
+ ecomp(parlink);
+ parlink = NIL;
lparam = NULL;
nparams = 0;
+ symclear(1); /* In case of function pointer args */
}
/*
- * reference to a structure or union, with no definition
+ * Struct/union/enum symtab construction.
*/
-NODE *
-rstruct(char *tag, int soru)
+static void
+defstr(struct symtab *sp, int class)
{
- 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 : 0);
- defid(q, (soru&INSTRUCT) ? STNAME :
- ((soru&INUNION) ? UNAME : 0));
- nfree(q);
- break;
-
- case STRTY:
- if (soru & INSTRUCT)
- break;
- goto def;
-
- case UNIONTY:
- if (soru & INUNION)
- break;
- goto def;
-
- }
- q = mkty(p->stype, 0, p->ssue);
- q->n_sue = p->ssue;
- return q;
+ sp->ssue = permalloc(sizeof(struct suedef));
+ sp->ssue->suesize = 0;
+ sp->ssue->sylnk = NULL;
+ sp->ssue->suealign = 0;
+ sp->sclass = class;
+ if (class == STNAME)
+ sp->stype = STRTY;
+ else if (class == UNAME)
+ sp->stype = UNIONTY;
}
/*
@@ -643,23 +597,26 @@ deftag(char *name, int class)
{
struct symtab *sp;
- sp = lookup(name, STAGNAME);
- if (sp->ssue == NULL)
- sp->ssue = permalloc(sizeof(struct suedef));
- if (sp->sclass == SNULL) {
+ if ((sp = lookup(name, STAGNAME))->ssue == NULL) {
/* New tag */
- sp->sclass = class;
- } else if (sp->slevel < blevel) {
- /* declared at different block level, hide it */
- sp = hide(sp);
- sp->sclass = class;
- } else if (sp->sclass != class) {
- /* redeclaration of tag */
+ defstr(sp, class);
+ } else if (sp->sclass != class)
uerror("tag %s redeclared", name);
- }
return sp;
}
+/*
+ * reference to a structure or union, with no definition
+ */
+NODE *
+rstruct(char *tag, int soru)
+{
+ struct symtab *sp;
+
+ sp = deftag(tag, soru);
+ return mkty(sp->stype, 0, sp->ssue);
+}
+
static int enumlow, enumhigh;
int enummer;
@@ -701,8 +658,12 @@ enumhd(char *name)
return NULL;
sp = deftag(name, ENAME);
- if (sp->stype != UNDEF) /* enum type already declared */
- uerror("%s redeclared", name);
+ if (sp->stype != UNDEF) {
+ if (sp->slevel == blevel)
+ uerror("%s redeclared", name);
+ sp = hide(sp);
+ defstr(sp, ENAME);
+ }
return sp;
}
@@ -759,39 +720,28 @@ struct rstack *
bstruct(char *name, int soru)
{
struct rstack *r;
- struct symtab *s;
- NODE *q;
+ struct symtab *sp;
- if (name != NULL)
- s = lookup(name, STAGNAME);
- else
- s = NULL;
+ if (name != NULL) {
+ sp = deftag(name, soru);
+ if (sp->ssue->suealign != 0) {
+ if (sp->slevel < blevel) {
+ sp = hide(sp);
+ defstr(sp, soru);
+ } else
+ uerror("%s redeclared", name);
+ }
+ sp->ssue->suealign = ALSTRUCT;
+ } else
+ sp = 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 {
- cerror("bstruct");
- }
- r->rsym = q->n_sp;
- r->rlparam = lparam;
- nfree(q);
+ r->rsou = soru;
+ r->rstr = 0;
+ r->rsym = sp;
+ r->rb = NULL;
+ r->rnext = rpole;
+ rpole = r;
return r;
}
@@ -803,12 +753,10 @@ NODE *
dclstruct(struct rstack *r)
{
NODE *n;
- struct params *l, *m;
struct suedef *sue;
- struct symtab *p;
+ struct symtab *sp;
int al, sa, sz, coff;
TWORD temp;
- int i, high, low;
if (r->rsym == NULL) {
sue = permalloc(sizeof(struct suedef));
@@ -817,65 +765,49 @@ dclstruct(struct rstack *r)
sue->suealign = ALSTRUCT;
} else
sue = r->rsym->ssue;
+ if (sue->suealign == 0) /* suealign == 0 is undeclared struct */
+ sue->suealign = ALSTRUCT;
#ifdef PCC_DEBUG
if (ddebug)
printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??");
#endif
- temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:0);
- instruct = r->rinstruct;
- strunem = r->rclass;
+ temp = r->rsou == STNAME ? STRTY : UNIONTY;
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);
-
coff = 0;
if (pragma_packed || pragma_aligned)
- strucoff = 0; /* must recount it */
-
- for (i = 0; l != NULL; l = l->next) {
- sue->suelem[i++] = p = l->sym;
+ rpole->rstr = 0; /* must recount it */
- if (p == NULL)
- cerror("gummy structure member");
- sa = talign(p->stype, p->ssue);
- if (p->sclass & FIELD)
- sz = p->sclass&FLDSIZ;
+ sue->sylnk = r->rb;
+ for (sp = r->rb; sp; sp = sp->snext) {
+ sa = talign(sp->stype, sp->ssue);
+ if (sp->sclass & FIELD)
+ sz = sp->sclass&FLDSIZ;
else
- sz = tsize(p->stype, p->sdf, p->ssue);
+ sz = tsize(sp->stype, sp->sdf, sp->ssue);
if (pragma_packed || pragma_aligned) {
/* XXX check pack/align sizes */
- p->soffset = coff;
+ sp->soffset = coff;
if (pragma_aligned)
coff += ALLDOUBLE;
else
coff += sz;
- strucoff = coff;
+ rpole->rstr = coff;
}
- if (sz > strucoff)
- strucoff = sz; /* for use with unions */
+ if (sz > rpole->rstr)
+ rpole->rstr = 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);
+ SETOFF(rpole->rstr, al);
- sue->suesize = strucoff;
+ sue->suesize = rpole->rstr;
sue->suealign = al;
pragma_packed = pragma_aligned = 0;
@@ -887,25 +819,47 @@ dclstruct(struct rstack *r)
#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]);
+ printf("\tsize %d align %d link %p\n",
+ sue->suesize, sue->suealign, sue->sylnk);
+ for (sp = sue->sylnk; sp != NULL; sp = sp->snext) {
+ printf("\tmember %s(%p)\n", sp->sname, sp);
}
}
#endif
- strucoff = r->rstrucoff;
- if ((lparam = r->rlparam) != NULL)
- lparam->next = NULL;
+ rpole = r->rnext;
n = mkty(temp, 0, sue);
return n;
}
/*
+ * Add a new member to the current struct or union being declared.
+ */
+void
+soumemb(NODE *n, char *name, int class)
+{
+ struct symtab *sp, *lsp;
+
+ if (rpole == NULL)
+ cerror("soumemb");
+
+ lsp = NULL;
+ for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext)
+ if (sp->sname == name)
+ uerror("redeclaration of %s", name);
+
+ sp = getsymtab(name, SMOSNAME);
+ if (rpole->rb == NULL)
+ rpole->rb = sp;
+ else
+ lsp->snext = sp;
+ n->n_sp = sp;
+ defid(n, class);
+}
+
+
+
+/*
* error printing routine in parser
*/
void yyerror(char *s);
@@ -930,74 +884,44 @@ 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.
+ * Push argument symtab entries onto 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)
+ 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);
+ ssave(q->n_sp);
nparams++;
#ifdef PCC_DEBUG
if (ddebug > 2)
printf(" saving sym %s (%p) from (%p)\n",
- s->sname, s, q);
+ q->n_sp->sname, q->n_sp, 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);
+ ssave(p->n_sp);
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);
+ nparams ? p->n_sp->sname : "<noname>", p->n_sp, p);
#endif
}
@@ -1103,7 +1027,7 @@ tsize(TWORD ty, union dimfun *d, struct suedef *sue)
return(SZINT);
}
} else {
- if (sue->suelem == NULL)
+ if (sue->suealign == 0)
uerror("unknown structure/union/enum");
}
@@ -1221,7 +1145,7 @@ oalloc(struct symtab *p, int *poff )
} else
#endif
if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
- p->stype == SHORT || p->stype == USHORT)) {
+ p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) {
off = upoff(SZINT, ALINT, &noff);
#ifndef RTOLBYTES
off = noff - tsz;
@@ -1243,7 +1167,24 @@ oalloc(struct symtab *p, int *poff )
}
/*
- * Allocate space on the stack for dynamic arrays.
+ * Delay emission of code generated in argument headers.
+ */
+static void
+edelay(NODE *p)
+{
+ if (blevel == 1) {
+ /* Delay until after declarations */
+ if (parlink == NULL)
+ parlink = p;
+ else
+ parlink = block(COMOP, parlink, p, 0, 0, 0);
+ } else
+ ecomp(p);
+}
+
+/*
+ * Allocate space on the stack for dynamic arrays (or at least keep track
+ * of the index).
* 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.
@@ -1258,41 +1199,66 @@ dynalloc(struct symtab *p, int *poff)
union dimfun *df;
NODE *n, *nn, *tn, *pol;
TWORD t;
- int i, no;
+ int astkp, no;
/*
- * The pointer to the array is stored in a TEMP node, which number
- * is in the soffset field;
+ * The pointer to the array is not necessarily stored in a
+ * TEMP node, but if it is, its 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 = regno(tn);
+ astkp = 0;
+ if (ISARY(t) && blevel == 1) {
+ /* must take care of side effects of dynamic arg arrays */
+ if (p->sdf->ddim < 0) {
+ /* first-level array will be indexed correct */
+ edelay(arrstk[astkp++]);
+ }
+ p->sdf++;
+ p->stype += (PTR-ARY);
+ t = p->stype;
+ }
+ if (ISARY(t)) {
+ 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 = regno(tn);
+ } else {
+ oalloc(p, poff);
+ tn = NIL;
+ }
df = p->sdf;
pol = NIL;
- for (i = 0; ISARY(t); t = DECREF(t), df++) {
- if (df->ddim >= 0)
+ for (; t > BTMASK; t = DECREF(t)) {
+ if (!ISARY(t))
continue;
- n = arrstk[i++];
- nn = tempnode(0, INT, 0, MKSUE(INT));
- no = regno(nn);
- ecomp(buildtree(ASSIGN, nn, n)); /* Save size */
+ if (df->ddim < 0) {
+ n = arrstk[astkp++];
+ nn = tempnode(0, INT, 0, MKSUE(INT));
+ no = regno(nn);
+ edelay(buildtree(ASSIGN, nn, n));
+
+ df->ddim = -no;
+ n = tempnode(no, INT, 0, MKSUE(INT));
+ } else
+ n = bcon(df->ddim);
- df->ddim = -no;
- n = tempnode(no, INT, 0, MKSUE(INT));
- if (pol == NIL)
- pol = n;
- else
- pol = buildtree(MUL, pol, n);
+ pol = (pol == NIL ? n : buildtree(MUL, pol, n));
+ df++;
}
/* Create stack gap */
- if (pol == NIL)
- uerror("aggregate dynamic array not allowed");
- else
- spalloc(tn, pol, tsize(t, 0, p->ssue));
+ if (blevel == 1) {
+ if (tn)
+ tfree(tn);
+ if (pol)
+ tfree(pol);
+ } else {
+ if (pol == NIL)
+ uerror("aggregate dynamic array not allowed");
+ if (tn)
+ spalloc(tn, pol, tsize(t, 0, p->ssue));
+ }
arrstkp = 0;
}
@@ -1343,24 +1309,24 @@ falloc(struct symtab *p, int w, int new, NODE *pty)
}
if( w == 0 ){ /* align only */
- SETOFF( strucoff, al );
+ SETOFF( rpole->rstr, al );
if( new >= 0 ) uerror( "zero size field");
return(0);
}
- if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+ if( rpole->rstr%al + w > sz ) SETOFF( rpole->rstr, al );
if( new < 0 ) {
- strucoff += w; /* we know it will fit */
+ rpole->rstr += 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);
+ if( p->soffset != rpole->rstr || p->sclass != (FIELD|w) ) return(1);
}
- p->soffset = strucoff;
- strucoff += w;
+ p->soffset = rpole->rstr;
+ rpole->rstr += w;
p->stype = type;
fldty( p );
return(0);
@@ -1382,7 +1348,7 @@ nidcl(NODE *p, int class)
if (class == SNULL) {
if (blevel > 1)
class = AUTO;
- else if (blevel != 0 || instruct)
+ else if (blevel != 0 || rpole)
cerror( "nidcl error" );
else /* blevel = 0 */
commflag = 1, class = EXTERN;
@@ -1498,8 +1464,8 @@ typenode(NODE *p)
type = class = qual = sig = uns = 0;
saved = NIL;
- if (strunem != 0)
- class = strunem;
+ if (rpole != NULL)
+ class = rpole->rsou == STNAME ? MOS : MOU;
for (q = p; p; p = p->n_left) {
switch (p->n_op) {
@@ -2376,7 +2342,7 @@ fixtype(NODE *p, int class)
}
/* detect function arguments, watching out for structure declarations */
- if (instruct && ISFTN(type)) {
+ if (rpole && ISFTN(type)) {
uerror("function illegal in structure or union");
type = INCREF(type);
}
@@ -2404,10 +2370,8 @@ fixclass(int class, TWORD type)
{
/* first, fix null class */
if (class == SNULL) {
- if (instruct&INSTRUCT)
- class = MOS;
- else if (instruct&INUNION)
- class = MOU;
+ if (rpole)
+ class = rpole->rsou == STNAME ? MOS : MOU;
else if (blevel == 0)
class = EXTDEF;
else
@@ -2433,24 +2397,23 @@ fixclass(int class, TWORD type)
}
}
- if( class&FIELD ){
- if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
- return( class );
- }
-
- switch( class ){
+ if (class & FIELD) {
+ if (rpole && rpole->rsou != STNAME)
+ uerror("illegal use of field");
+ return(class);
+ }
- case MOU:
- if( !(instruct&INUNION) ) uerror( "illegal MOU class" );
- return( class );
+ switch (class) {
case MOS:
- if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" );
- return( class );
+ case MOU:
+ if (rpole == NULL)
+ uerror("illegal member class");
+ return(class);
case REGISTER:
if (blevel == 0)
- uerror( "illegal register declaration" );
+ uerror("illegal register declaration");
if (blevel == 1)
return(PARAM);
else
@@ -2472,13 +2435,12 @@ fixclass(int class, TWORD type)
uerror( "fortran function has wrong type" );
}
}
- case STNAME:
- case UNAME:
case EXTERN:
case STATIC:
case EXTDEF:
case TYPEDEF:
case USTATIC:
+ case PARAM:
return( class );
default:
@@ -2543,6 +2505,18 @@ getsymtab(char *name, int flags)
return s;
}
+int
+fldchk(int sz)
+{
+ if (rpole->rsou != STNAME)
+ uerror("field outside of structure");
+ if (sz < 0 || sz >= FIELD) {
+ uerror("illegal field size");
+ return 1;
+ }
+ return 0;
+}
+
#ifdef PCC_DEBUG
static char *
ccnames[] = { /* names of storage classes */
diff --git a/usr.bin/pcc/ccom/scan.l b/usr.bin/pcc/ccom/scan.l
index 4e349815a0f..32dd7857a7e 100644
--- a/usr.bin/pcc/ccom/scan.l
+++ b/usr.bin/pcc/ccom/scan.l
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: scan.l,v 1.4 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: scan.l,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2002 Anders Magnusson. All rights reserved.
@@ -58,7 +58,7 @@ int notype, parbal;
#define CPP_HASH 4
#ifdef STABS
-#define STABS_LINE(x) if (gflag && blevel) stabs_line(x)
+#define STABS_LINE(x) if (gflag && blevel > 1) stabs_line(x)
#else
#define STABS_LINE(x)
#endif
@@ -125,10 +125,10 @@ extern void yyset_lineno (int);
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); }
+"struct" { yylval.intval = STNAME; 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); }
+"union" { yylval.intval = UNAME; 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));
@@ -138,22 +138,22 @@ extern void yyset_lineno (int);
return(C_QUALIFIER); }
"while" { return(C_WHILE); }
-{L}({L}|{D})* { struct symtab *s;
- int i;
+{L}({L}|{D})* { struct symtab *s;
+ int i = 0;
- yylval.strp = addname(yytext);
+ yylval.strp = addname(yytext);
#ifdef GCC_COMPAT
- if ((i = gcc_keyword(yylval.strp,
- &yylval.nodep)) != 0)
- return i;
+ if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0)
+ return i;
#endif
- if (!notype) {
- s = lookup(yylval.strp, SNOCREAT);
- if (s && s->sclass == TYPEDEF)
- return notype=1, C_TYPENAME;
- }
- return(C_NAME);
+ if (i == 0) {
+ if (notype)
+ return(C_NAME);
+ s = lookup(yylval.strp, SNOCREAT);
+ return s && s->sclass == TYPEDEF ?
+ notype=1, C_TYPENAME : C_NAME;
}
+ }
0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
@@ -204,7 +204,7 @@ L?\"(\\.|[^\\"])*\" {
"!=" { yylval.intval = NE; return(C_EQUOP); }
";" { notype = 0; return(';'); }
("{"|"<%") { notype = 0; return('{'); }
-("}"|"%>") { return('}'); }
+("}"|"%>") { if (rpole) notype = 1; return('}'); }
"," { if (parbal) notype = 0; return(','); }
":" { return(':'); }
"=" { return('='); }
@@ -446,6 +446,8 @@ control(int t)
lineno = val - 1;
while (*wr && *wr != '\"')
wr++;
+ if (*wr == 0)
+ return;
if (*wr++ != '\"')
goto bad;
eptr = wr;
@@ -510,3 +512,9 @@ pragma()
else
bad: werror("unknown pragma");
}
+
+void
+cunput(char c)
+{
+ unput(c);
+}
diff --git a/usr.bin/pcc/ccom/stabs.c b/usr.bin/pcc/ccom/stabs.c
index 8fe84a5b035..78765545eff 100644
--- a/usr.bin/pcc/ccom/stabs.c
+++ b/usr.bin/pcc/ccom/stabs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: stabs.c,v 1.6 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: stabs.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
@@ -121,7 +121,7 @@ stabs_init()
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",
+ cprint(savestabs, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n",
st->num, st->num, N_LSYM);
}
@@ -132,7 +132,7 @@ stabs_init()
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",
+ cprint(savestabs, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n",
name, num, inhnum, min, max, N_LSYM);
}
@@ -196,11 +196,11 @@ void
stabs_line(int line)
{
#ifdef STAB_LINE_ABSOLUTE
- cprint(savestabs, ".stabn %d,0,%d," STABLBL, N_SLINE, line, stablbl);
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n", N_SLINE, line, stablbl);
#else
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, exname(curfun));
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n", N_SLINE, line, stablbl, exname(curfun));
#endif
- cprint(1, STABLBL ":", stablbl++);
+ cprint(1, STABLBL ":\n", stablbl++);
}
/*
@@ -210,12 +210,12 @@ void
stabs_lbrac(int blklvl)
{
#ifdef STAB_LINE_ABSOLUTE
- cprint(savestabs, ".stabn %d,0,%d," STABLBL, N_LBRAC, blklvl, stablbl);
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n", N_LBRAC, blklvl, stablbl);
#else
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s",
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n",
N_LBRAC, blklvl, stablbl, exname(curfun));
#endif
- cprint(1, STABLBL ":", stablbl++);
+ cprint(1, STABLBL ":\n", stablbl++);
}
/*
@@ -225,13 +225,13 @@ void
stabs_rbrac(int blklvl)
{
#ifdef STAB_LINE_ABSOLUTE
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "\n",
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n",
N_RBRAC, blklvl, stablbl);
#else
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n",
+ cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n",
N_RBRAC, blklvl, stablbl, exname(curfun));
#endif
- cprint(1, STABLBL ":", stablbl++);
+ cprint(1, STABLBL ":\n", stablbl++);
}
/*
@@ -244,9 +244,9 @@ stabs_file(char *fname)
if (mainfile == NULL)
mainfile = fname; /* first call */
- cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL,
+ cprint(savestabs, "\t.stabs \"%s\",%d,0,0," STABLBL "\n",
fname, fname == mainfile ? N_SO : N_SOL, stablbl);
- cprint(savestabs, STABLBL ":", stablbl++);
+ cprint(savestabs, STABLBL ":\n", stablbl++);
}
/*
@@ -259,7 +259,7 @@ stabs_func(struct symtab *s)
curfun = s->soname;
printtype(s, str, sizeof(str));
- cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s",
+ cprint(savestabs, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n",
curfun, s->sclass == STATIC ? 'f' : 'F', str,
N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun));
}
@@ -330,32 +330,32 @@ stabs_newsym(struct symtab *s)
printtype(s, ostr, sizeof(ostr));
switch (s->sclass) {
case PARAM:
- cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:p%s\",%d,0,%d,%d\n", sname, ostr,
N_PSYM, suesize, BIT2BYTE(s->soffset));
break;
case AUTO:
- cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:%s\",%d,0,%d,%d\n", sname, ostr,
N_LSYM, suesize, BIT2BYTE(s->soffset));
break;
case STATIC:
if (blevel)
- cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:V%s\",%d,0,%d," LABFMT "\n", sname, ostr,
N_LCSYM, suesize, s->soffset);
else
- cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:S%s\",%d,0,%d,%s\n", sname, ostr,
N_LCSYM, suesize, exname(sname));
break;
case EXTERN:
case EXTDEF:
- cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:G%s\",%d,0,%d,0\n", sname, ostr,
N_GSYM, suesize);
break;
case REGISTER:
- cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr,
+ cprint(savestabs, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", sname, ostr,
N_RSYM, 1, s->soffset);
break;
@@ -377,9 +377,15 @@ stabs_struct(struct symtab *p, struct suedef *sue)
{
}
+static struct foo {
+ struct foo *next;
+ char *str;
+} *foopole;
+
void
cprint(int p2, char *fmt, ...)
{
+ extern int inftn;
va_list ap;
char *str;
@@ -387,12 +393,19 @@ cprint(int p2, char *fmt, ...)
if (p2) {
str = tmpvsprintf(fmt, ap);
str = newstring(str, strlen(str)); /* XXX - for inlines */
- send_passt(IP_ASM, str);
- } else {
- putchar('\t');
+ if (inftn == 0) {
+ struct foo *w = tmpalloc(sizeof(struct foo));
+ w->str = str;
+ w->next = foopole;
+ foopole = w;
+ } else {
+ while (foopole)
+ send_passt(IP_ASM, foopole->str),
+ foopole = foopole->next;
+ send_passt(IP_ASM, str);
+ }
+ } else
vprintf(fmt, ap);
- putchar('\n');
- }
va_end(ap);
}
diff --git a/usr.bin/pcc/ccom/trees.c b/usr.bin/pcc/ccom/trees.c
index 70fa2caefe6..e7bd9a87f8a 100644
--- a/usr.bin/pcc/ccom/trees.c
+++ b/usr.bin/pcc/ccom/trees.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trees.c,v 1.13 2008/01/12 17:26:16 ragge Exp $ */
+/* $OpenBSD: trees.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -76,6 +76,7 @@ static int opact(NODE *p);
static int moditype(TWORD);
static NODE *strargs(NODE *);
static void rmcops(NODE *p);
+int inftn; /* currently between epilog/prolog */
/* some special actions, used in finding the type of nodes */
# define NCVT 01
@@ -115,7 +116,6 @@ buildtree(int o, NODE *l, NODE *r)
struct symtab *sp = NULL; /* XXX gcc */
NODE *lr, *ll;
char *name;
- struct symtab **elem;
#ifdef PCC_DEBUG
if (bdebug) {
@@ -245,6 +245,8 @@ runtime:
if (actions & LVAL) { /* check left descendent */
if (notlval(p->n_left)) {
uerror("lvalue required");
+ nfree(p);
+ return l;
#ifdef notyet
} else {
if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
@@ -350,16 +352,15 @@ runtime:
break;
}
- if ((elem = l->n_sue->suelem) == NULL)
+ if ((sp = l->n_sue->sylnk) == NULL)
uerror("undefined struct or union");
name = r->n_name;
- for (; *elem != NULL; elem++) {
- sp = *elem;
+ for (; sp != NULL; sp = sp->snext) {
if (sp->sname == name)
break;
}
- if (*elem == NULL)
+ if (sp == NULL)
uerror("member '%s' not declared", name);
r->n_sp = sp;
@@ -1591,6 +1592,8 @@ eprint(NODE *p, int down, int *a, int *b)
ty = coptype( p->n_op );
printf("%p) %s, ", p, copst(p->n_op));
+ if (p->n_op == XARG || p->n_op == XASM)
+ printf("id '%s', ", p->n_name);
if (ty == LTYPE) {
printf(CONFMT, p->n_lval);
printf(", %d, ", (p->n_op != NAME && p->n_op != ICON) ?
@@ -2058,6 +2061,10 @@ p2tree(NODE *p)
printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue));
break;
+ case XARG:
+ case XASM:
+ break;
+
default:
printf( "\n" );
}
@@ -2125,6 +2132,10 @@ p2tree(NODE *p)
p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR;
break;
+ case XARG:
+ case XASM:
+ break;
+
default:
p->n_name = "";
}
@@ -2220,6 +2231,7 @@ send_passt(int type, ...)
defloc(cftnsp);
/* FALLTHROUGH */
case IP_PROLOG:
+ inftn = type == IP_PROLOG ? 1 : 0;
ipp = (struct interpass_prolog *)ip;
ipp->ipp_regs = va_arg(ap, int);
ipp->ipp_autos = va_arg(ap, int);
@@ -2227,7 +2239,7 @@ send_passt(int type, ...)
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_tmpnum = va_arg(ap, int);
ipp->ip_lblnum = crslab;
if (type == IP_PROLOG)
ipp->ip_lblnum--;
diff --git a/usr.bin/pcc/config.h b/usr.bin/pcc/config.h
index 11eb06e5e4f..47f4ced9ead 100644
--- a/usr.bin/pcc/config.h
+++ b/usr.bin/pcc/config.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: config.h,v 1.4 2007/10/07 19:26:26 otto Exp $ */
+/* $OpenBSD: config.h,v 1.5 2008/04/11 20:45:51 stefan Exp $ */
#define PCC_MAJOR 0
#define PCC_MINOR 9
-#define PCC_MINORMINOR 8
-#define VERSSTR "pcc 0.9.8"
+#define PCC_MINORMINOR 9
+#define VERSSTR "pcc 0.9.9"
#define YYTEXT_POINTER 1
diff --git a/usr.bin/pcc/cpp/cpp.1 b/usr.bin/pcc/cpp/cpp.1
index 2f4606ee011..50a7a9bc81c 100644
--- a/usr.bin/pcc/cpp/cpp.1
+++ b/usr.bin/pcc/cpp/cpp.1
@@ -1,24 +1,24 @@
-.\" $Id: cpp.1,v 1.3 2008/01/12 17:58:29 ragge Exp $
+.\" $Id: cpp.1,v 1.4 2008/04/11 20:45:52 stefan Exp $
.\" $NetBSD$
-.\" $OpenBSD: cpp.1,v 1.3 2008/01/12 17:58:29 ragge Exp $
+.\" $OpenBSD: cpp.1,v 1.4 2008/04/11 20:45:52 stefan Exp $
."\
.\" 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
+.\"
+.\" 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
+.\"
+.\" 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 17, 2007
-.Dt cpp 1
+.Dt CPP 1
.Os
.Sh NAME
.Nm cpp
@@ -34,7 +34,6 @@
.Op Fl U Ar macro
.Op Ar infile | -
.Op Ar outfile
-.Pp
.Sh DESCRIPTION
The
.Nm
@@ -45,7 +44,7 @@ It is used to include header files,
expand macro definitions,
and perform conditional compilation.
.Pp
-The
+The
.Ar infile
input file is optional.
If not provided or the file name is
@@ -65,6 +64,9 @@ It writes by default to standard output.
.\"
The options are as follows:
.Bl -tag -width Ds
+.It Fl ?
+Show command line usage for
+.Nm .
.It Fl C
Do not discard comments.
.It Fl D Ar macro[=value]
@@ -73,14 +75,14 @@ Fake a definition at the beginning by using
.Ar macro=value Dc .
If
.Ar value
-is not set on command-line, then defines as 1.
+is not set on command-line, then define it as 1.
.\" TODO: show example
.It Fl dM
Print list of
.Dq #define
statements to standard output for all defined macros other than
builtin macros (see below).
-The normal results of preprocessing are not outputted.
+The normal results of preprocessing are not output.
.\" TODO this doesn't show predefined macros
.\" other -d options are ignored
.It Fl I Ar path
@@ -106,8 +108,9 @@ Generate dependencies for
Add
.Ar path
to the list of system directories containing needed header files.
+The
.Fl S
-may be specified multiple times.
+option may be specified multiple times.
Note:
.Nm
does not have a default include directory defined.
@@ -120,25 +123,22 @@ Do not define the
.Dv __DATE__ ,
.Dv __STDC__ ,
and
-.Dv __STDC_VERSION__ ,
+.Dv __STDC_VERSION__
macros.
.\"
.It Fl U Ar macro
Undefine a macro at the beginning by using
.Do #undef
.Ar macro Dc .
-.It Fl v
-Display version.
.It Fl V
Verbose debugging output.
.Fl V
can be repeated for further details.
.\" -V only available if cpp source built with CPP_DEBUG, which is the default.
-.It Fl ?
-Show command line usage for
-.Nm .
+.It Fl v
+Display version.
.El
-.Sh Builtin Macros
+.Ss Builtin Macros
A few macros are interpreted inside the
.Nm cpp
program:
@@ -151,19 +151,22 @@ in quotes.
.It __FILE__
Expands to the name of the current input file in quotes.
When read from standard input, it expands to
-.Qq Ao stdin Ac .
+.Qq Aq stdin .
.It __LINE__
Expands to the line number of the current line containing the macro.
.It __STDC__
Expands to the constant 1.
-This means the compiler conforms to ISO Standard C,
-ISO/IEC 9899:1990
+This means the compiler conforms to
+.St -isoC
.Po also known as
.Do C90 Dc Pc .
.It __STDC_VERSION__
Expands to
.Dq 199901L
-which indicates it supports ISO/IEC 9899:1999 standard
+which indicates that
+.Nm
+supports
+.St -isoC-99
.Po commonly referred to as
.Do C99 Dc Pc .
.It __TIME__
@@ -193,8 +196,8 @@ An error occurred.
.Sh HISTORY
The
.Nm
-command comes from the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
+command comes from the original Portable C Compiler by S. C. Johnson,
+written in the late 70's.
The code originates from the V6 preprocessor with some additions
from V7 cpp and ansi/c99 support.
.Pp
diff --git a/usr.bin/pcc/cpp/cpp.c b/usr.bin/pcc/cpp/cpp.c
index b2f9702f35a..095b75da475 100644
--- a/usr.bin/pcc/cpp/cpp.c
+++ b/usr.bin/pcc/cpp/cpp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpp.c,v 1.8 2008/01/12 17:58:29 ragge Exp $ */
+/* $OpenBSD: cpp.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
@@ -101,7 +101,7 @@ int dflag; /* debug printouts */
int ofd;
usch outbuf[CPPBUF];
-int obufp, istty;
+int obufp, istty, inmac;
int Cflag, Mflag, dMflag;
usch *Mfile;
struct initar *initar;
@@ -983,7 +983,8 @@ expmac(struct recur *rp)
else
orgexp++;
- DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp));
+ DDPRINT(("id1: typ %d noexp %d orgexp %d\n",
+ c, noexp, orgexp));
if (c == IDENT) { /* XXX numbers? */
DDPRINT(("id2: str %s\n", yytext));
/* OK to always expand here? */
@@ -1118,12 +1119,19 @@ expdef(vp, rp, gotwarn)
* read arguments and store them on heap.
* will be removed just before return from this function.
*/
+ inmac = 1;
sptr = stringbuf;
+ instr = 0;
for (i = 0; i < narg && c != ')'; i++) {
args[i] = stringbuf;
plev = 0;
while ((c = yylex()) == WSPACE || c == '\n')
;
+ DDPRINT((":AAA (%d)", c));
+ if (instr == -1)
+ savch(NOEXP), instr = 1;
+ if (c == NOEXP)
+ instr = 1;
for (;;) {
if (plev == 0 && (c == ')' || c == ','))
break;
@@ -1134,10 +1142,14 @@ expdef(vp, rp, gotwarn)
savstr((usch *)yytext);
while ((c = yylex()) == '\n')
savch('\n');
+ if (c == EXPAND)
+ instr = 0;
}
while (args[i] < stringbuf &&
(stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
stringbuf--;
+ if (instr == 1)
+ savch(EXPAND), instr = -1;
savch('\0');
}
if (ellips)
@@ -1145,8 +1157,12 @@ expdef(vp, rp, gotwarn)
if (ellips && c != ')') {
args[i] = stringbuf;
plev = 0;
+ instr = 0;
while ((c = yylex()) == WSPACE)
;
+ if (c == NOEXP)
+ instr++;
+ DDPRINT((":AAY (%d)", c));
for (;;) {
if (plev == 0 && c == ')')
break;
@@ -1154,9 +1170,16 @@ expdef(vp, rp, gotwarn)
plev++;
if (c == ')')
plev--;
- savstr((usch *)yytext);
+ if (plev == 0 && c == ',' && instr) {
+ savch(EXPAND);
+ savch(',');
+ savch(NOEXP);
+ } else
+ savstr((usch *)yytext);
while ((c = yylex()) == '\n')
savch('\n');
+ if (c == EXPAND)
+ instr--;
}
while (args[i] < stringbuf &&
(stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
@@ -1171,6 +1194,7 @@ expdef(vp, rp, gotwarn)
if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
error("wrong arg count");
+ inmac = 0;
while (gotwarn--)
cunput(WARN);
diff --git a/usr.bin/pcc/cpp/scanner.l b/usr.bin/pcc/cpp/scanner.l
index 5e155d30d52..e5dca5e9f26 100644
--- a/usr.bin/pcc/cpp/scanner.l
+++ b/usr.bin/pcc/cpp/scanner.l
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: scanner.l,v 1.8 2008/01/12 17:58:29 ragge Exp $ */
+/* $OpenBSD: scanner.l,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson. All rights reserved.
@@ -32,6 +32,7 @@
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
#include "cpp.h"
#include "y.tab.h"
@@ -198,7 +199,14 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) {
{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
-^{WS}*#{WS}* { contr = 1; BEGIN CONTR; }
+^{WS}*#{WS}* { extern int inmac;
+
+ if (inmac)
+ error("preprocessor directive found "
+ "while expanding macro");
+ contr = 1;
+ BEGIN CONTR;
+ }
{WS}+ { PRTOUT(WSPACE); }
<CONTR>"ifndef" { contr = 0; ifndefstmt(); }
@@ -217,13 +225,13 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) {
"//".*$ { /* if (tflag) yyless(..) */
- if (Cflag)
+ if (Cflag && !flslvl)
putstr((usch *)yytext);
else if (!flslvl)
putch(' ');
}
"/*" { int c, wrn;
- if (Cflag)
+ if (Cflag && !flslvl)
putstr((usch *)yytext);
wrn = 0;
more: while ((c = input()) && c != '*') {
@@ -231,20 +239,20 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) {
putch(c), ifiles->lineno++;
else if (c == 1) /* WARN */
wrn = 1;
- else if (Cflag)
+ else if (Cflag && !flslvl)
putch(c);
}
if (c == 0)
return 0;
- if (Cflag)
+ if (Cflag && !flslvl)
putch(c);
if ((c = input()) && c != '/') {
- if (Cflag)
+ if (Cflag && !flslvl)
putch('*');
unput(c);
goto more;
}
- if (Cflag)
+ if (Cflag && !flslvl)
putch(c);
if (c == 0)
return 0;
@@ -580,15 +588,23 @@ charcon(void)
}
static void
-chknl(void)
+chknl(int ignore)
{
int t;
slow = 1;
while ((t = yylex()) == WSPACE)
;
- if (t != '\n')
- error("newline expected, got \"%s\"", yytext);
+ if (t != '\n') {
+ if (ignore) {
+ warning("newline expected, got \"%s\"", yytext);
+ /* ignore rest of line */
+ while ((t = yylex()) && t != '\n')
+ ;
+ }
+ else
+ error("newline expected, got \"%s\"", yytext);
+ }
slow = 0;
}
@@ -612,7 +628,7 @@ elsestmt(void)
if (elslvl==trulvl+flslvl)
error("Too many else");
elslvl=trulvl+flslvl;
- chknl();
+ chknl(1);
}
static void
@@ -640,7 +656,7 @@ ifdefstmt(void)
trulvl++;
else
flslvl++;
- chknl();
+ chknl(0);
}
static void
@@ -659,7 +675,7 @@ ifndefstmt(void)
trulvl++;
else
flslvl++;
- chknl();
+ chknl(0);
}
static void
@@ -676,7 +692,7 @@ endifstmt(void)
if (flslvl == 0)
elflvl = 0;
elslvl = 0;
- chknl();
+ chknl(1);
}
/*
@@ -832,7 +848,7 @@ undefstmt(void)
if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
np->value = 0;
slow = 0;
- chknl();
+ chknl(0);
}
static void
diff --git a/usr.bin/pcc/hppa/code.c b/usr.bin/pcc/hppa/code.c
index f00c7639bf5..ebc523f57dd 100644
--- a/usr.bin/pcc/hppa/code.c
+++ b/usr.bin/pcc/hppa/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.3 2007/12/19 20:19:54 otto Exp $ */
+/* $OpenBSD: code.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
@@ -32,38 +32,46 @@
# include "pass1.h"
NODE *funarg(NODE *, int *);
+int argreg(TWORD, int *);
/*
- * cause the alignment to become a multiple of n
- * never called for text segment.
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
*/
void
-defalign(int n)
+defloc(struct symtab *sp)
{
- n /= SZCHAR;
- if (n == 1)
- return;
- printf("\t.align %d\n", n);
-}
+ extern char *nextsect;
+ static char *loctbl[] = { "text", "data", "section .rodata" };
+ static int lastloc = -1;
+ TWORD t;
+ int s;
-/*
- * define the current location as the name p->sname
- * never called for text segment.
- */
-void
-defnam(struct symtab *p)
-{
- char *c = p->sname;
-
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
-#endif
- if (p->sclass == EXTDEF)
- printf("\t.export %s, data\n", c);
- printf("\t.label %s\n", c);
+ if (sp == NULL) {
+ lastloc = -1;
+ return;
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+ if (nextsect) {
+ printf("\t.section %s\n", nextsect);
+ nextsect = NULL;
+ s = -1;
+ } else if (s != lastloc)
+ printf("\t.%s\n", loctbl[s]);
+ lastloc = s;
+ while (ISARY(t))
+ t = DECREF(t);
+ if (t > UCHAR)
+ printf("\t.align\t%d\n", ISFTN(t)? 4 : talign(t, sp->ssue));
+ if (sp->sclass == EXTDEF)
+ printf("\t.export %s, data\n", sp->soname);
+ if (sp->slevel == 0)
+ printf("\t.label %s\n", sp->soname);
+ else
+ printf("\t.label\t" LABFMT "\n", sp->soffset);
}
-
/*
* code for the end of a function
* deals with struct return here
@@ -94,20 +102,71 @@ efcode()
send_passt(IP_NODE, p);
}
+int
+argreg(TWORD t, int *n)
+{
+ switch (t) {
+ case FLOAT:
+ return FR7L - 2 * (*n)++;
+ case DOUBLE:
+ case LDOUBLE:
+ *n += 2;
+ return FR6 - *n - 2;
+ case LONGLONG:
+ case ULONGLONG:
+ *n += 2;
+ return AD1 - (*n - 2) / 2;
+ default:
+ return ARG0 - (*n)++;
+ }
+}
+
/*
* 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)
+bfcode(struct symtab **a, int cnt)
{
- int i;
+ struct symtab *sp;
+ NODE *p, *q;
+ int i, n, sz;
- if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
- return;
+ 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);
+ }
+
+ /* recalculate the arg offset and create TEMP moves */
+ for (n = 0, i = 0; i < cnt; i++) {
+ sp = a[i];
+
+ sz = szty(sp->stype);
+ if (n % sz)
+ n++; /* XXX LDOUBLE */
+
+ if (n < 4) {
+ p = tempnode(0, sp->stype, sp->sdf, sp->ssue);
+ /* TODO p->n_left->n_lval = -(32 + n * 4); */
+ q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue);
+ q->n_rval = argreg(sp->stype, &n);
+ p = buildtree(ASSIGN, p, q);
+ sp->soffset = regno(p->n_left);
+ sp->sflags |= STNODE;
+ ecomp(p);
+ } else {
+ sp->soffset += SZINT * n;
+ if (xtemps) {
+ /* put stack args in temps if optimizing */
+ p = tempnode(0, sp->stype, sp->sdf, sp->ssue);
+ p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
+ sp->soffset = regno(p->n_left);
+ sp->sflags |= STNODE;
+ ecomp(p);
+ }
+ }
+ }
}
@@ -138,40 +197,6 @@ bjobcode(void)
}
/*
- * 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\t\"");
- 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\t\"%c", t);
- } else {
- lastoctal = 0;
- putchar(t);
- }
- }
-}
-
-/*
* return the alignment of field of type t
*/
int
@@ -210,7 +235,7 @@ funarg(NODE *p, int *n)
sz = szty(p->n_type);
if (*n % sz)
- (*n)++; /* XXX */
+ (*n)++; /* XXX LDOUBLE */
if (*n >= 4) {
*n += sz;
@@ -221,25 +246,7 @@ funarg(NODE *p, int *n)
} else {
r = block(REG, NIL, NIL, p->n_type, 0, 0);
r->n_lval = 0;
- switch (p->n_type) {
- case FLOAT:
- r->n_rval = FR7L - 2 * (*n)++;
- break;
- case DOUBLE:
- case LDOUBLE:
- *n = (*n + 1) & ~1;
- r->n_rval = FR6 - *n;
- *n += 2;
- break;
- case LONGLONG:
- case ULONGLONG:
- *n = (*n + 1) & ~1;
- r->n_rval = AD1 - *n / 2;
- *n += 2;
- break;
- default:
- r->n_rval = ARG0 - (*n)++;
- }
+ r->n_rval = argreg(p->n_type, n);
}
p = block(ASSIGN, r, p, p->n_type, 0, 0);
clocal(p);
diff --git a/usr.bin/pcc/hppa/local.c b/usr.bin/pcc/hppa/local.c
index 2c9fd3fa4a1..58ace34370c 100644
--- a/usr.bin/pcc/hppa/local.c
+++ b/usr.bin/pcc/hppa/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.3 2007/12/19 20:19:54 otto Exp $ */
+/* $OpenBSD: local.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
@@ -34,6 +34,8 @@
/* this file contains code which is dependent on the target machine */
+struct symtab *makememcpy(void);
+
/* clocal() is called to do local transformations on
* an expression tree preparitory to its being
* written out in intermediate code.
@@ -48,7 +50,7 @@
NODE *
clocal(NODE *p)
{
- register struct symtab *q;
+ register struct symtab *q, *sp;
register NODE *r, *l, *s;
register int o, m, rn;
char *ch, name[16];
@@ -113,13 +115,14 @@ clocal(NODE *p)
case STATIC:
case EXTERN:
+ if (strncmp(p->n_sp->soname, "__builtin", 9) == 0)
+ break;
+
l = block(REG, NIL, NIL, INT, 0, 0);
l->n_lval = 0;
l->n_rval = R1;
l = block(ASSIGN, l, p, INT, 0, 0);
- r = block(ICON, NIL, NIL, INT, 0, 0);
- r->n_sp = p->n_sp;
- r->n_lval = 0;
+ r = xbcon(0, p->n_sp, INT);
p = block(UMUL,
block(PLUS, l, r, INT, 0, 0),
NIL, p->n_type, p->n_df, p->n_sue);
@@ -135,9 +138,7 @@ clocal(NODE *p)
l->n_lval = 0;
l->n_rval = R1;
l = block(ASSIGN, l, p->n_left, INT, 0, 0);
- r = block(ICON, NIL, NIL, INT, 0, 0);
- r->n_sp = p->n_left->n_sp;
- r->n_lval = 0;
+ r = xbcon(0, p->n_left->n_sp, INT);
l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue);
nfree(p);
p = l;
@@ -285,7 +286,16 @@ clocal(NODE *p)
l->n_sue = MKSUE(m);
nfree(p);
return l;
+ } else if (l->n_op == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return clocal(l);
}
+
if (DEUNSIGN(p->n_type) == SHORT &&
DEUNSIGN(l->n_type) == SHORT) {
nfree(p);
@@ -384,6 +394,77 @@ clocal(NODE *p)
p->n_type, p->n_df, p->n_sue);
l->n_left = tcopy(r);
break;
+
+ case STASG:
+ /* memcpy(left, right, size) */
+ sp = makememcpy();
+ l = p->n_left;
+ /* guess struct return */
+ if (l->n_op == NAME && ISFTN(l->n_sp->stype)) {
+ l = block(REG, NIL, NIL, VOID|PTR, 0, MKSUE(LONG));
+ l->n_lval = 0;
+ l->n_rval = RET0;
+ } else if (l->n_op == UMUL)
+ l = tcopy(l->n_left);
+ else if (l->n_op == NAME)
+ l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,MKSUE(LONG));
+ l = block(CALL, block(ADDROF,
+ (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),
+ NIL, PTR|FTN, 0, MKSUE(LONG)),
+ block(CM, block(CM, l, tcopy(p->n_right),
+ STRTY|PTR, 0, MKSUE(LONG)),
+ (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0),
+ INT, 0, MKSUE(LONG));
+ r->n_lval = p->n_sue->suesize/SZCHAR;
+ s->n_sp = sp;
+ s->n_df = s->n_sp->sdf;
+ defid(s, EXTERN);
+ tfree(p);
+ p = l;
+ p->n_left = clocal(p->n_left);
+ p->n_right = clocal(p->n_right);
+ calldec(p->n_left, p->n_right);
+ funcode(p);
+ break;
+
+ case STARG:
+ /* arg = memcpy(argN-size, src, size) */
+ sp = makememcpy();
+ l = block(CALL, block(ADDROF,
+ (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),NIL,0,0,0),
+ block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0),
+ (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0),
+ INT, 0, MKSUE(LONG));
+ r->n_lval = p->n_sue->suesize/SZCHAR;
+ s->n_sp = sp;
+ s->n_df = s->n_sp->sdf;
+ defid(s, EXTERN);
+ tfree(p);
+ p = l;
+ p->n_left = clocal(p->n_left);
+ calldec(p->n_left, p->n_right);
+ funcode(p);
+ break;
+
+ case STCALL:
+ case CALL:
+ for (r = p->n_right; r->n_op == CM; r = r->n_left) {
+ if (r->n_right->n_op == ASSIGN &&
+ r->n_right->n_right->n_op == CALL) {
+ s = r->n_right->n_right;
+ l = tempnode(0, s->n_type, s->n_df, s->n_sue);
+ ecode(buildtree(ASSIGN, l, s));
+ r->n_right->n_right = tcopy(l);
+ }
+ if (r->n_left->n_op == ASSIGN &&
+ r->n_left->n_right->n_op == CALL) {
+ s = r->n_left->n_right;
+ l = tempnode(0, s->n_type, s->n_df, s->n_sue);
+ ecode(buildtree(ASSIGN, l, s));
+ r->n_left->n_right = tcopy(l);
+ }
+ }
+ break;
}
/* second pass - rewrite long ops */
@@ -414,6 +495,7 @@ clocal(NODE *p)
p->n_left->n_left->n_sp = lookup(addname(name), 0);
defid(p->n_left->n_left, EXTERN);
p->n_left = clocal(p->n_left);
+ calldec(p->n_left, p->n_right);
p->n_op = CALL;
funcode(p);
break;
@@ -428,9 +510,60 @@ clocal(NODE *p)
return(p);
}
+struct symtab *
+makememcpy()
+{
+ NODE *memcpy, *args, *t, *u;
+ struct symtab *sp;
+
+ /* TODO check that it's a func proto */
+ if ((sp = lookup(addname("memcpy"), SNORMAL)))
+ return sp;
+
+ memcpy = block(NAME, NIL, NIL, 0, 0, MKSUE(LONG));
+ memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL);
+ defid(memcpy, EXTERN);
+
+ args = block(CM, block(CM,
+ block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)),
+ block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 0, 0, 0),
+ block(NAME, NIL, NIL, LONG, 0, MKSUE(LONG)), 0, 0, 0);
+
+ tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0),
+ (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0),
+ NIL, LONG, 0, 0)));
+ tfree(t);
+ tfree(u);
+
+ return sp;
+}
+
void
myp2tree(NODE *p)
{
+ int o = p->n_op;
+
+ if (o != FCON)
+ return;
+
+ /* Write float constants to memory */
+ /* Should be volontary per architecture */
+
+#if 0
+ setloc1(RDATA);
+ defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
+ ALDOUBLE : ALLDOUBLE );
+ deflab1(i = getlab());
+#endif
+
+ 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 = getlab();
+ p->n_sp->sflags = 0;
+
}
/*ARGSUSED*/
@@ -540,9 +673,12 @@ indata(CONSZ val, int size)
* sequences. Location is already set.
*/
void
-instring(char *str)
+instring(struct symtab *sp)
{
- char *s;
+ char *s, *str;
+
+ defloc(sp);
+ str = sp->sname;
/* be kind to assemblers and avoid long strings */
printf("\t.ascii\t\"");
@@ -560,6 +696,27 @@ instring(char *str)
printf("\\0\"\n");
}
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = bcon(0);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
+
static int inbits, inval;
/*
@@ -660,7 +817,7 @@ ninval(CONSZ off, int fsz, NODE *p)
q->sclass == ILABEL) {
printf("+" LABFMT, q->soffset);
} else
- printf("+%s", exname(q->sname));
+ printf("+%s", exname(q->soname));
}
printf("\n");
break;
@@ -719,71 +876,65 @@ ctype(TWORD type)
}
void
-calldec(NODE *p, NODE *q)
+calldec(NODE *f, NODE *a)
{
- printf("\t.call\n");
+ struct symtab *q;
+ if (f->n_op == UMUL && f->n_left->n_op == PLUS &&
+ f->n_left->n_right->n_op == ICON)
+ q = f->n_left->n_right->n_sp;
+ else if (f->n_op == PLUS && f->n_right->n_op == ICON)
+ q = f->n_right->n_sp;
+ else {
+ fwalk(f, eprint, 0);
+ cerror("unknown function");
+ return;
+ }
+
+ printf("\t.import\t%s,code\n", exname(q->soname));
}
void
extdec(struct symtab *q)
{
-#ifdef GCC_COMPAT
- printf("\t.import\t%s,data\n", gcc_findname(q));
-#else
- printf("\t.import\t%s,data\n", exname(q->sname));
-#endif
+ printf("\t.import\t%s,data\n", exname(q->soname));
}
/* make a common declaration for id, if reasonable */
void
-commdec(struct symtab *q)
+defzero(struct symtab *sp)
{
int off;
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
-#ifdef GCC_COMPAT
- printf("\t.label\t%s\n", gcc_findname(q));
-#else
- printf("\t.label\t%s\n", exname(q->sname));
-#endif
- printf("\t.comm\t%d\n", off);
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
+ off = (off + (SZCHAR - 1)) / SZCHAR;
+ printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,0%o\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",0%o\n", sp->soffset, off);
}
-/* make a local common declaration for id, if reasonable */
-void
-lcommdec(struct symtab *q)
-{
- int off;
+char *nextsect;
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
- if (q->slevel == 0)
-#ifdef GCC_COMPAT
- printf("\t.lcomm %s,0%o\n", gcc_findname(q), off);
-#else
- printf("\t.lcomm %s,0%o\n", exname(q->sname), off);
-#endif
- else
- printf("\t.lcomm " LABFMT ",0%o\n", q->soffset, off);
-}
+#define SSECTION 010000
/*
- * print a (non-prog) label.
+ * Give target the opportunity of handling pragmas.
*/
-void
-deflab1(int label)
+int
+mypragma(char **ary)
{
- printf("\t.label\t" LABFMT "\n", label);
+ if (strcmp(ary[1], "section") || ary[2] == NULL)
+ return 0;
+ nextsect = newstring(ary[2], strlen(ary[2]));
+ return 1;
}
-static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
-
+/*
+ * Called when a identifier has been declared, to give target last word.
+ */
void
-setloc1(int locc)
+fixdef(struct symtab *sp)
{
- if (locc == lastloc)
- return;
- lastloc = locc;
- printf("\t.%s\n", loctbl[locc]);
}
+
diff --git a/usr.bin/pcc/hppa/local2.c b/usr.bin/pcc/hppa/local2.c
index feec2e85ccc..4bd2cd97093 100644
--- a/usr.bin/pcc/hppa/local2.c
+++ b/usr.bin/pcc/hppa/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.3 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: local2.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
@@ -86,18 +86,18 @@ prtprolog(struct interpass_prolog *ipp, int addto)
for (i = 0; i < MAXREGS; i++)
if (TESTBIT(ipp->ipp_regs, i)) {
if (i <= R31)
- printf("\tstw\t%s,%d(%%sp)\n",
+ printf("\tstw\t%s,%d(%%r3)\n",
rnames[i], regoff[i]);
else if (i <= RETD0)
- printf("\tstw\t%s,%d(%%sp)\n"
- "\tstw\t%s,%d(%%sp)\n",
+ printf("\tstw\t%s,%d(%%r3)\n"
+ "\tstw\t%s,%d(%%r3)\n",
rnames[rl[i - RD0]], regoff[i] + 0,
rnames[rh[i - RD0]], regoff[i] + 4);
else if (i <= FR31)
- printf("\tfstws\t%s,%d(%%sp)\n",
+ printf("\tfstws\t%s,%d(%%r3)\n",
rnames[i], regoff[i]);
else
- printf("\tfstds\t%s,%d(%%sp)\n",
+ printf("\tfstds\t%s,%d(%%r3)\n",
rnames[i], regoff[i]);
}
}
@@ -108,7 +108,7 @@ prtprolog(struct interpass_prolog *ipp, int addto)
static int
offcalc(struct interpass_prolog *ipp)
{
- int i, addto;
+ int i, addto, off;
addto = 32;
if (p2calls) {
@@ -119,12 +119,12 @@ offcalc(struct interpass_prolog *ipp)
addto += i * 4;
}
- for (i = 0; i < MAXREGS; i++)
+ for (off = 4, i = 0; i < MAXREGS; i++)
if (TESTBIT(ipp->ipp_regs, i)) {
- regoff[i] = addto;
- addto += SZINT/SZCHAR;
+ regoff[i] = off;
+ off += szty(PERMTYPE(i)) * SZINT/SZCHAR;
}
- addto += 4 + p2maxautooff;
+ addto += off + p2maxautooff;
return (addto + 63) & ~63;
}
@@ -160,18 +160,18 @@ eoftn(struct interpass_prolog *ipp)
for (i = 0; i < MAXREGS; i++)
if (TESTBIT(ipp->ipp_regs, i)) {
if (i <= R31)
- printf("\tldw\t%d(%%sp),%s\n",
+ printf("\tldw\t%d(%%r3),%s\n",
regoff[i], rnames[i]);
else if (i <= RETD0)
- printf("\tldw\t%d(%%sp),%s\n"
- "\tldw\t%d(%%sp),%s\n",
+ printf("\tldw\t%d(%%r3),%s\n"
+ "\tldw\t%d(%%r3),%s\n",
regoff[i] + 0, rnames[rl[i - RD0]],
regoff[i] + 4, rnames[rh[i - RD0]]);
else if (i <= FR31)
- printf("\tfldws\t%d(%%sp),%s\n",
+ printf("\tfldws\t%d(%%r3),%s\n",
regoff[i], rnames[i]);
else
- printf("\tfldds\t%d(%%sp),%s\n",
+ printf("\tfldds\t%d(%%r3),%s\n",
regoff[i], rnames[i]);
}
@@ -285,7 +285,7 @@ tlen(p) NODE *p;
default:
if (!ISPTR(p->n_type))
- comperr("tlen type %d not pointer");
+ comperr("tlen type %d not pointer", p->n_type);
return SZPOINT(p->n_type)/SZCHAR;
}
}
@@ -293,6 +293,7 @@ tlen(p) NODE *p;
static int
argsiz(NODE *p)
{
+ NODE *q;
TWORD t = p->n_type;
if (t < LONGLONG || t == FLOAT || t > BTMASK)
@@ -300,10 +301,16 @@ argsiz(NODE *p)
if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
return 8;
if (t == LDOUBLE)
- return 8; /* quad is 16 */
- if (t == STRTY || t == UNIONTY)
- return p->n_stsize;
- comperr("argsiz");
+ return 8; /* LDOUBLE is 16 */
+ if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == STARG)
+ return 4 + p->n_right->n_stsize;
+ /* perhaps it's down there somewhere -- let me take another look! */
+ if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == CALL) {
+ q = p->n_right->n_right->n_left->n_left->n_right;
+ if (q->n_op == STARG)
+ return 4 + q->n_stsize;
+ }
+ comperr("argsiz %p", p);
return 0;
}
@@ -345,11 +352,19 @@ twollcomp(NODE *p)
}
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);
+ if (cb1) {
+ p->n_op = cb1;
+ p->n_label = s;
+ expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
+ p->n_label = e;
+ p->n_op = o;
+ }
+ if (cb2) {
+ p->n_op = cb2;
+ expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n");
+ p->n_op = o;
+ }
+ expand(p, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n");
deflab(s);
}
@@ -554,7 +569,6 @@ adrput(FILE *io, NODE *p)
} else
fprintf(io, "(%s)", rnames[p->n_rval]);
return;
- case MOVE:
case REG:
if (RD0 <= p->n_rval && p->n_rval <= RETD0)
fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]);
diff --git a/usr.bin/pcc/hppa/macdefs.h b/usr.bin/pcc/hppa/macdefs.h
index 65eedbd59ee..86aaccf741d 100644
--- a/usr.bin/pcc/hppa/macdefs.h
+++ b/usr.bin/pcc/hppa/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.2 2007/12/19 20:19:54 otto Exp $ */
+/* $OpenBSD: macdefs.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
diff --git a/usr.bin/pcc/hppa/order.c b/usr.bin/pcc/hppa/order.c
index 68513151ba1..e9dac7f575e 100644
--- a/usr.bin/pcc/hppa/order.c
+++ b/usr.bin/pcc/hppa/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.2 2007/12/19 20:19:54 otto Exp $ */
+/* $OpenBSD: order.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
@@ -177,6 +177,7 @@ setorder(NODE *p)
{
return 0; /* nothing differs on hppa */
}
+
/*
* Set registers "live" at function calls (like arguments in registers).
* This is for liveness analysis of registers.
@@ -184,9 +185,23 @@ setorder(NODE *p)
int *
livecall(NODE *p)
{
- static int r[1] = { -1 }; /* Terminate with -1 */
-
- return &r[0];
+ static int r[5], *s = &r[4];
+
+ *s = -1;
+ if (p->n_op == UCALL || p->n_op == UFORTCALL || p->n_op == USTCALL ||
+ p->n_op == FORTCALL)
+ return s;
+
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ if (p->n_right->n_op == ASSIGN &&
+ p->n_right->n_left->n_op == REG)
+ *--s = p->n_right->n_left->n_rval;
+
+ if (p->n_op == ASSIGN &&
+ p->n_left->n_op == REG)
+ *--s = p->n_left->n_rval;
+
+ return s;
}
/*
diff --git a/usr.bin/pcc/hppa/table.c b/usr.bin/pcc/hppa/table.c
index 71149fc9fae..5e53ef9736c 100644
--- a/usr.bin/pcc/hppa/table.c
+++ b/usr.bin/pcc/hppa/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.2 2007/12/19 20:19:54 otto Exp $ */
+/* $OpenBSD: table.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2007 Michael Shalayeff
@@ -583,13 +583,13 @@ struct optab table[] = {
{ ASSIGN, FOREFF|INAREG,
SOREG, TBYTE,
- SHINT, TBYTE,
+ SHINT, TBYTE,
0, RDEST,
"\tstb\tAR,AL\n", },
{ ASSIGN, FOREFF|INAREG,
SOREG, THWORD,
- SHINT, THWORD,
+ SHINT, THWORD,
0, RDEST,
"\tsth\tAR,AL\n", },
@@ -601,7 +601,7 @@ struct optab table[] = {
{ ASSIGN, FOREFF|INLL,
SOREG, TLL,
- SHLL, TLL,
+ SHLL, TLL,
0, RDEST,
"\tstw\tAR,AL\n"
"\tstw\tUR,UL\n", },
diff --git a/usr.bin/pcc/i386/code.c b/usr.bin/pcc/i386/code.c
index 0e0a6bb7cbc..11f951ff1f2 100644
--- a/usr.bin/pcc/i386/code.c
+++ b/usr.bin/pcc/i386/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.7 2008/01/12 17:29:09 ragge Exp $ */
+/* $OpenBSD: code.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -48,6 +48,13 @@ defloc(struct symtab *sp)
}
t = sp->stype;
s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (s != DATA)
+ cerror("non-data symbol in tls section");
+ nextsect = ".tdata";
+ }
+#endif
if (nextsect) {
printf(" .section %s\n", nextsect);
nextsect = NULL;
diff --git a/usr.bin/pcc/i386/local.c b/usr.bin/pcc/i386/local.c
index 4643c7adbe1..9f3fe41cdd5 100644
--- a/usr.bin/pcc/i386/local.c
+++ b/usr.bin/pcc/i386/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.6 2008/01/12 17:29:09 ragge Exp $ */
+/* $OpenBSD: local.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -123,6 +123,83 @@ picstatic(NODE *p)
return q;
}
+#ifdef TLS
+/*
+ * Create a reference for a TLS variable.
+ */
+static NODE *
+tlspic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp;
+
+ /*
+ * creates:
+ * leal var@TLSGD(%ebx),%eax
+ * call ___tls_get_addr@PLT
+ */
+
+ /* calc address of var@TLSGD */
+ q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID));
+ sp = picsymtab(p->n_sp->soname, "@TLSGD");
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+
+ /* assign to %eax */
+ r = block(REG, NIL, NIL, PTR|VOID, 0, MKSUE(VOID));
+ r->n_rval = EAX;
+ q = buildtree(ASSIGN, r, q);
+
+ /* call ___tls_get_addr */
+ spname = lookup("___tls_get_addr@PLT", 0);
+ spname->stype = EXTERN|INT|FTN;
+ r = buildtree(NAME, NIL, NIL);
+ r = buildtree(ADDROF, r, NIL);
+ r = block(UCALL, r, NIL, INT, 0, MKSUE(INT));
+
+ /* fusion both parts together */
+ q = buildtree(COMOP, q, r);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsnonpic(NODE *p)
+{
+ NODE *q, *r;
+ struct symtab *sp;
+ int ext = p->n_sp->sclass;
+
+ sp = picsymtab(p->n_sp->soname, ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
+ q = xbcon(0, sp, INT);
+ if (ext == EXTERN)
+ q = block(UMUL, q, NIL, PTR|VOID, 0, MKSUE(VOID));
+
+ spname = lookup("%gs:0", 0);
+ spname->stype = EXTERN|INT;
+ r = buildtree(NAME, NIL, NIL);
+
+ q = buildtree(PLUS, q, r);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+
+ nfree(p);
+ return q;
+}
+
+static NODE *
+tlsref(NODE *p)
+{
+ if (kflag)
+ return (tlspic(p));
+ else
+ return (tlsnonpic(p));
+}
+#endif
+
/* clocal() is called to do local transformations on
* an expression tree preparitory to its being
* written out in intermediate code.
@@ -172,6 +249,12 @@ clocal(NODE *p)
break;
/* FALLTHROUGH */
case STATIC:
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
+ break;
+ }
+#endif
if (kflag == 0) {
if (q->slevel == 0)
break;
@@ -188,6 +271,12 @@ clocal(NODE *p)
case EXTERN:
case EXTDEF:
+#ifdef TLS
+ if (q->sflags & STLS) {
+ p = tlsref(p);
+ break;
+ }
+#endif
if (kflag == 0)
break;
if (blevel > 0)
@@ -374,6 +463,14 @@ clocal(NODE *p)
l->n_sue = MKSUE(m);
nfree(p);
return l;
+ } else if (l->n_op == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return clocal(l);
}
if (DEUNSIGN(p->n_type) == SHORT &&
DEUNSIGN(l->n_type) == SHORT) {
@@ -405,9 +502,10 @@ clocal(NODE *p)
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));
+ r = p;
+ p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right);
+ nfree(r);
+ break;
case FORCE:
/* put return value in return reg */
@@ -846,6 +944,15 @@ defzero(struct symtab *sp)
{
int off;
+#ifdef TLS
+ if (sp->sflags & STLS) {
+ if (sp->sclass == EXTERN)
+ sp->sclass = EXTDEF;
+ simpleinit(sp, bcon(0));
+ return;
+ }
+#endif
+
off = tsize(sp->stype, sp->sdf, sp->ssue);
off = (off+(SZCHAR-1))/SZCHAR;
printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
@@ -856,14 +963,21 @@ defzero(struct symtab *sp)
}
char *nextsect;
-
-#define SSECTION 010000
+#ifdef TLS
+static int gottls;
+#endif
/* * Give target the opportunity of handling pragmas.
*/
int
mypragma(char **ary)
{
+#ifdef TLS
+ if (strcmp(ary[1], "tls") == 0 && ary[2] == NULL) {
+ gottls = 1;
+ return 1;
+ }
+#endif
if (strcmp(ary[1], "section") || ary[2] == NULL)
return 0;
nextsect = newstring(ary[2], strlen(ary[2]));
@@ -876,4 +990,10 @@ mypragma(char **ary)
void
fixdef(struct symtab *sp)
{
+#ifdef TLS
+ /* may have sanity checks here */
+ if (gottls)
+ sp->sflags |= STLS;
+ gottls = 0;
+#endif
}
diff --git a/usr.bin/pcc/i386/local2.c b/usr.bin/pcc/i386/local2.c
index a2e02a69ec6..70015de2b29 100644
--- a/usr.bin/pcc/i386/local2.c
+++ b/usr.bin/pcc/i386/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.7 2008/01/12 17:29:09 ragge Exp $ */
+/* $OpenBSD: local2.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -119,7 +119,7 @@ prologue(struct interpass_prolog *ipp)
int addto;
ftype = ipp->ipp_type;
-#if 0
+#ifdef LANG_F77
if (ipp->ipp_vis)
printf(" .globl %s\n", ipp->ipp_name);
printf(" .align 4\n");
@@ -775,7 +775,6 @@ adrput(FILE *io, NODE *p)
conput(io, p);
return;
- case MOVE:
case REG:
switch (p->n_type) {
case LONGLONG:
diff --git a/usr.bin/pcc/i386/macdefs.h b/usr.bin/pcc/i386/macdefs.h
index 436b511152e..0343b1ffabc 100644
--- a/usr.bin/pcc/i386/macdefs.h
+++ b/usr.bin/pcc/i386/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.3 2007/11/17 12:00:37 ragge Exp $ */
+/* $OpenBSD: macdefs.h,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -106,22 +106,14 @@ 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 */
+#ifdef LANG_F77
#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
+#define ARGOFFSET 8
#endif
#define BACKAUTO /* stack grows negatively for automatics */
@@ -304,3 +296,9 @@ int COLORMAP(int c, int *r);
#define SMIXOR (MAXSPECIAL+4)
#define SMILWXOR (MAXSPECIAL+5)
#define SMIHWXOR (MAXSPECIAL+6)
+
+/*
+ * i386-specific symbol table flags.
+ */
+#define SSECTION SLOCAL1
+#define STLS SLOCAL2
diff --git a/usr.bin/pcc/i386/order.c b/usr.bin/pcc/i386/order.c
index 95be8ab4461..f88ef1a4c67 100644
--- a/usr.bin/pcc/i386/order.c
+++ b/usr.bin/pcc/i386/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.4 2007/12/09 18:53:02 ragge Exp $ */
+/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -280,9 +280,16 @@ setorder(NODE *p)
int *
livecall(NODE *p)
{
- static int r[2] = { EBX, -1 };
+ static int r[] = { EAX, EBX, -1 };
+ int off = 1;
- return kflag ? &r[0] : &r[1];
+#ifdef TLS
+ if (p->n_left->n_op == ICON &&
+ strcmp(p->n_left->n_name, "___tls_get_addr@PLT") == 0)
+ off--;
+#endif
+
+ return kflag ? &r[off] : &r[2];
}
/*
diff --git a/usr.bin/pcc/i386/table.c b/usr.bin/pcc/i386/table.c
index 81c4ccb47af..8370d128171 100644
--- a/usr.bin/pcc/i386/table.c
+++ b/usr.bin/pcc/i386/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: table.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -133,7 +133,7 @@ struct optab table[] = {
{ SCONV, INLL,
SHCH|SOREG|SNAME, TCHAR,
SANY, TLL,
- NSPECIAL|NAREG|NASL, RESC1,
+ NSPECIAL|NCREG|NCSL, RESC1,
" movsbl AL,%eax\n cltd\n", },
/* convert unsigned char to (u)long long */
@@ -275,14 +275,14 @@ struct optab table[] = {
{ SCONV, INCH,
SOREG|SNAME, TLL,
SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
+ NBREG|NBSL, 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,
+ NBREG|NBSL, RESC1,
"ZS", },
/* convert (u)long long to (u)short (mem->reg) */
@@ -1162,7 +1162,7 @@ struct optab table[] = {
{ UMUL, INLL,
SANY, TANY,
SOREG, TLL,
- NCREG|NCSL, RESC1,
+ NCREG, RESC1,
" movl UL,U1\n movl AL,A1\n", },
{ UMUL, INAREG,
diff --git a/usr.bin/pcc/mip/common.c b/usr.bin/pcc/mip/common.c
index 399c8cb39ba..95ee5358394 100644
--- a/usr.bin/pcc/mip/common.c
+++ b/usr.bin/pcc/mip/common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common.c,v 1.8 2007/11/17 12:00:37 ragge Exp $ */
+/* $OpenBSD: common.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -75,10 +75,19 @@ int nerrors = 0; /* number of errors */
char *ftitle;
int lineno;
+int warniserr = 0;
+
#ifndef WHERE
#define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
#endif
+static void
+incerr(void)
+{
+ if (++nerrors > 30)
+ cerror("too many errors");
+}
+
/*
* nonfatal error message
* the routine where is different for pass 1 and pass 2;
@@ -90,13 +99,11 @@ 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);
+ incerr();
}
/*
@@ -137,6 +144,8 @@ werror(char *s, ...)
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
va_end(ap);
+ if (warniserr)
+ incerr();
}
#ifndef MKEXT
@@ -191,7 +200,6 @@ tcopy(NODE *p)
return(q);
}
-
/*
* ensure that all nodes have been freed
*/
@@ -317,7 +325,6 @@ struct dopest {
{ REG, "REG", LTYPE, },
{ OREG, "OREG", LTYPE, },
{ TEMP, "TEMP", LTYPE, },
- { MOVE, "MOVE", UTYPE, },
{ ICON, "ICON", LTYPE, },
{ FCON, "FCON", LTYPE, },
{ CCODES, "CCODES", LTYPE, },
@@ -328,7 +335,8 @@ struct dopest {
{ UFORTCALL, "UFCALL", UTYPE|CALLFLG, },
{ COMPL, "~", UTYPE, },
{ FORCE, "FORCE", UTYPE, },
-/* { INIT, "INIT", UTYPE, }, */
+ { XARG, "XARG", UTYPE, },
+ { XASM, "XASM", BITYPE, },
{ SCONV, "SCONV", UTYPE, },
{ PCONV, "PCONV", UTYPE, },
{ PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, },
diff --git a/usr.bin/pcc/mip/manifest.h b/usr.bin/pcc/mip/manifest.h
index b569f844366..a41278c8f0e 100644
--- a/usr.bin/pcc/mip/manifest.h
+++ b/usr.bin/pcc/mip/manifest.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: manifest.h,v 1.9 2008/01/12 17:17:28 ragge Exp $ */
+/* $OpenBSD: manifest.h,v 1.10 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -167,6 +167,7 @@
#define DATA 1 /* (rw) data segment */
#define RDATA 2 /* (ro) data segment */
#define STRNG 3 /* (ro) string segment */
+#define UDATA 4 /* (rw) uninitialized data */
#define regno(p) ((p)->n_rval) /* register number */
@@ -177,7 +178,7 @@
extern int bdebug, tdebug, edebug;
extern int ddebug, xdebug, f2debug;
extern int iTflag, oTflag, kflag;
-extern int sflag, nflag, gflag;
+extern int sflag, nflag, gflag, pflag;
extern int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
Wimplicit_function_declaration;
extern int xssaflag, xtailcallflag, xtemps, xdeljumps;
@@ -319,4 +320,5 @@ NODE *tcopy(NODE *);
void fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down);
extern int nerrors; /* number of errors seen so far */
+extern int warniserr; /* treat warnings as errors */
#endif
diff --git a/usr.bin/pcc/mip/match.c b/usr.bin/pcc/mip/match.c
index e03b06ddb28..3204f429835 100644
--- a/usr.bin/pcc/mip/match.c
+++ b/usr.bin/pcc/mip/match.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.c,v 1.8 2008/01/12 17:17:28 ragge Exp $ */
+/* $OpenBSD: match.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
diff --git a/usr.bin/pcc/mip/mkext.c b/usr.bin/pcc/mip/mkext.c
index 609aae81cb6..f0fcdbde8fc 100644
--- a/usr.bin/pcc/mip/mkext.c
+++ b/usr.bin/pcc/mip/mkext.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mkext.c,v 1.7 2008/01/12 17:17:28 ragge Exp $ */
+
/*
* Generate defines for the needed hardops.
*/
@@ -67,7 +67,30 @@ 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 op = q->op;
+ char *s;
+
+ if (op < OPSIMP) {
+ s = opst[op];
+ } else
+ s = "Special op";
+ printf("table entry %td, op %s: %s\n", q - table, s, str);
+}
+
+static int
+getrcl(struct optab *q)
+{
+ int v = q->needs & (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT);
+ int r = q->rewrite & RESC1 ? 1 : q->rewrite & RESC2 ? 2 : 3;
+ int i = 0;
+
+#define INCK(c) while (v & c##COUNT) { \
+ v -= c##REG, i++; if (i == r) return I##c##REG; }
+ INCK(NA)
+ INCK(NB)
+ INCK(NC)
+ INCK(ND)
+ return 0;
}
int
@@ -147,6 +170,14 @@ main(int argc, char *argv[])
rval++;
}
}
+ /* check that reclaim is not the wrong class */
+ if ((q->rewrite & (RESC1|RESC2|RESC3)) &&
+ !(q->needs & REWRITE)) {
+ if ((q->visit & getrcl(q)) == 0) {
+ compl(q, "rwong RESCx class");
+ rval++;
+ }
+ }
if (q->rewrite & (RESC1|RESC2|RESC3) && q->visit & FOREFF)
compl(q, "FOREFF may cause reclaim of wrong class");
}
@@ -166,6 +197,19 @@ main(int argc, char *argv[])
fprintf(fc, "%d, ", i), j++;
fprintf(fc, "-1 };\n");
fprintf(fh, "#define NPERMREG %d\n", j+1);
+ fprintf(fc, "bittype validregs[] = {\n");
+ for (j = 0; j < MAXREGS; j += bitsz) {
+ int cbit = 0;
+ for (i = 0; i < bitsz; i++) {
+ if (i+j == MAXREGS)
+ break;
+ if (rstatus[i+j] & INREGS)
+ cbit |= (1 << i);
+ }
+ fprintf(fc, "\t0x%08x,\n", cbit);
+ }
+ fprintf(fc, "};\n");
+ fprintf(fh, "extern bittype validregs[];\n");
/*
* The register allocator uses bitmasks of registers for each class.
diff --git a/usr.bin/pcc/mip/node.h b/usr.bin/pcc/mip/node.h
index c21905bb422..ba7ce53be37 100644
--- a/usr.bin/pcc/mip/node.h
+++ b/usr.bin/pcc/mip/node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: node.h,v 1.2 2007/09/15 22:04:39 ray Exp $ */
+/* $OpenBSD: node.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -26,6 +26,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef NODE_H
+#define NODE_H
+
/*
* The node structure is the basic element in the compiler.
* Depending on the operator, it may be one of several types.
@@ -113,7 +116,7 @@ typedef struct node {
#define REG 6
#define OREG 7
#define TEMP 8
-#define MOVE 9 /* Special reg-reg move node */
+#define XARG 9
/*
* Arithmetic nodes.
@@ -184,7 +187,7 @@ typedef struct node {
#define STASG 50
#define STARG 51
#define FORCE 52
-/* #define INIT 53 */
+#define XASM 53
#define GOTO 54
#define RETURN 55
#define STREF 56
@@ -192,3 +195,5 @@ typedef struct node {
#define ADDROF 58
#define MAXOP 58
+
+#endif
diff --git a/usr.bin/pcc/mip/pass2.h b/usr.bin/pcc/mip/pass2.h
index c1c922bd6f5..4b0c3b23b6a 100644
--- a/usr.bin/pcc/mip/pass2.h
+++ b/usr.bin/pcc/mip/pass2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass2.h,v 1.7 2007/12/09 18:38:49 ragge Exp $ */
+/* $OpenBSD: pass2.h,v 1.8 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
@@ -265,7 +265,7 @@ void myreader(struct interpass *pole);
int oregok(NODE *p, int sharp);
void myormake(NODE *);
int *livecall(NODE *);
-
+void prtreg(FILE *, NODE *);
char *prcook(int);
void conput(FILE *, NODE *);
diff --git a/usr.bin/pcc/mip/reader.c b/usr.bin/pcc/mip/reader.c
index fd6a6339752..67292997d02 100644
--- a/usr.bin/pcc/mip/reader.c
+++ b/usr.bin/pcc/mip/reader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: reader.c,v 1.13 2008/01/12 17:17:28 ragge Exp $ */
+/* $OpenBSD: reader.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -89,18 +89,13 @@ FILE *prfil;
static struct interpass prepole;
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 fixxasm(struct interpass *ip);
static void gencode(NODE *p, int cookie);
+static void genxasm(NODE *p);
char *ltyp[] = { "", "LREG", "LOREG", "LTEMP" };
char *rtyp[] = { "", "RREG", "ROREG", "RTEMP" };
@@ -117,13 +112,13 @@ static void
cktree(NODE *p)
{
if (p->n_op > MAXOP)
- cerror("op %d slipped through", p->n_op);
+ cerror("%p) op %d slipped through", p, p->n_op);
if (BTYPE(p->n_type) > MAXTYPES)
- cerror("type %x slipped through", p->n_type);
+ cerror("%p) type %x slipped through", p, p->n_type);
if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
- cerror("not logop branch");
+ cerror("%p) not logop branch", p);
if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
- cerror("asgop %d slipped through", p->n_op);
+ cerror("%p) asgop %d slipped through", p, p->n_op);
}
#endif
@@ -134,11 +129,11 @@ static int
isuseless(NODE *n)
{
switch (n->n_op) {
+ case XASM:
case FUNARG:
case UCALL:
case UFORTCALL:
case FORCE:
-/* case INIT: */
case ASSIGN:
case CALL:
case FORTCALL:
@@ -245,6 +240,8 @@ pass2_compile(struct interpass *ip)
}
}
+ fixxasm(&ipole); /* setup for extended asm */
+
optimize(&ipole);
ngenregs(&ipole);
@@ -290,6 +287,9 @@ emit(struct interpass *ip)
case FORCE:
gencode(p->n_left, INREGS);
break;
+ case XASM:
+ genxasm(p);
+ break;
default:
if (p->n_op != REG || p->n_type != VOID) /* XXX */
gencode(p, FOREFF); /* Emit instructions */
@@ -309,10 +309,10 @@ emit(struct interpass *ip)
deflab(ip->ip_lbl);
break;
case IP_ASM:
- printf("\t%s\n", ip->ip_asm);
+ printf("%s", ip->ip_asm);
break;
default:
- cerror("compile4 %d", ip->type);
+ cerror("emit %d", ip->type);
}
}
@@ -476,6 +476,17 @@ again: switch (o = p->n_op) {
p->n_su = 0; /* su calculations traverse left */
break;
+ case XASM:
+ for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left)
+ geninsn(p1->n_right, FOREFF);
+ geninsn(p1, FOREFF);
+ break; /* all stuff already done? */
+
+ case XARG:
+ /* generate code for correct class here */
+ geninsn(p->n_left, 1 << p->n_label);
+ break;
+
default:
comperr("geninsn: bad op %s, node %p", opst[o], p);
}
@@ -576,6 +587,43 @@ rewrite(NODE *p, int rewrite, int cookie)
p->n_rval = DECRA(p->n_reg, 0);
}
+/*
+ * printout extended assembler.
+ */
+void
+genxasm(NODE *p)
+{
+ NODE *q, **nary;
+ int n = 1, o = 0;
+ char *w;
+
+ for (q = p->n_left; q->n_op == CM; q = q->n_left)
+ n++;
+ nary = tmpalloc(sizeof(NODE *)*n);
+ o = n;
+ for (q = p->n_left; q->n_op == CM; q = q->n_left) {
+ gencode(q->n_right->n_left, INREGS);
+ nary[--o] = q->n_right;
+ }
+ gencode(q->n_left, INREGS);
+ nary[--o] = q;
+
+ w = p->n_name;
+ putchar('\t');
+ while (*w != 0) {
+ if (*w == '%') {
+ if (w[1] < '1' || w[1] > (n + '0'))
+ uerror("bad xasm arg number");
+ else
+ adrput(stdout, nary[(int)w[1]-'1']->n_left);
+ w++;
+ } else
+ putchar(*w);
+ w++;
+ }
+ putchar('\n');
+}
+
void
gencode(NODE *p, int cookie)
{
@@ -736,6 +784,11 @@ e2print(NODE *p, int down, int *a, int *b)
fprintf(prfil, " %d", regno(p));
break;
+ case XASM:
+ case XARG:
+ fprintf(prfil, " '%s'", p->n_name);
+ break;
+
case ICON:
case NAME:
case OREG:
@@ -755,16 +808,8 @@ e2print(NODE *p, int down, int *a, int *b)
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 (0 <= p->n_reg &&
- p->n_reg < (ENCRD(MAXREGS) + ENCRA(MAXREGS,0))) /* XXX */
- fprintf(prfil, "REG %s", rnames[DECRA(p->n_reg, 0)]);
- else
- fprintf(prfil, "TEMP %d", gregn(p->n_regw));
- }
+
+ prtreg(prfil, p);
fprintf(prfil, ", SU= %d(%cREG,%s,%s,%s,%s)\n",
TBLIDX(p->n_su),
TCLASS(p->n_su)+'@',
@@ -844,7 +889,7 @@ void
deltemp(NODE *p)
{
struct tmpsave *w;
- NODE *l;
+ NODE *l, *r;
if (p->n_op == TEMP) {
/* Check if already existing */
@@ -859,9 +904,10 @@ deltemp(NODE *p)
w->next = tmpsave;
tmpsave = w;
}
- p->n_op = OREG;
- p->n_rval = FPREG;
- p->n_lval = w->tempaddr;
+ l = mklnode(REG, 0, FPREG, INCREF(p->n_type));
+ r = mklnode(ICON, w->tempaddr, 0, INT);
+ p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type));
+ p->n_op = UMUL;
} else if (p->n_op == ADDROF && p->n_left->n_op != NAME) {
/* TEMPs are already converted to OREGs */
if ((l = p->n_left)->n_op != OREG)
@@ -1021,6 +1067,12 @@ comperr(char *str, ...)
extern char *ftitle;
va_list ap;
+ if (nerrors) {
+ fprintf(stderr,
+ "cannot recover from earlier errors: goodbye!\n");
+ exit(1);
+ }
+
va_start(ap, str);
fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
vfprintf(stderr, str, ap);
@@ -1134,3 +1186,68 @@ rspecial(struct optab *q, int what)
}
return -1;
}
+
+/*
+ * Ensure that a node is correct for the destination.
+ */
+static void
+ltypify(struct interpass *ip, NODE *p)
+{
+ struct interpass *ip2;
+ TWORD t = p->n_left->n_type;
+ NODE *q, *r;
+ char *w;
+// int asg = 0, and = 0;
+
+#ifdef notyet
+ if (myxasm(ip, p))
+ return; /* handled by target-specific code */
+#endif
+ w = p->n_name;
+// if (*w == '=')
+// w++, asg = 1;
+ switch (*w) {
+ case 'r': /* general reg */
+ /* set register class */
+ p->n_label = gclass(p->n_left->n_type);
+ if (optype(p->n_left->n_op) == LTYPE)
+ break;
+ q = mklnode(TEMP, 0, epp->ip_tmpnum++, t);
+ r = tcopy(q);
+ ip2 = ipnode(mkbinode(ASSIGN, q, p->n_left, t));
+ DLIST_INSERT_BEFORE(ip, ip2, qelem);
+ p->n_left = r;
+ break;
+ default:
+ uerror("unsupported xasm option string '%s'", p->n_name);
+ }
+
+
+// fwalk(p, e2print, 0);
+}
+
+/* Extended assembler hacks */
+static void
+fixxasm(struct interpass *ipole)
+{
+ struct interpass *ip;
+ NODE *p;
+
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE || ip->ip_node->n_op != XASM)
+ continue;
+ /* Got an assembler node */
+ p = ip->ip_node->n_left;
+
+ /*
+ * Ensure that the arg nodes can be directly addressable
+ * We decide that everything shall be LTYPE here.
+ */
+ for (; p->n_op == CM; p = p->n_left)
+ ltypify(ip, p->n_right);
+ ltypify(ip, p);
+ p = ip->ip_node->n_right;
+ if (p->n_op != ICON || p->n_type != STRTY)
+ uerror("xasm constraints not supported");
+ }
+}
diff --git a/usr.bin/pcc/mip/regs.c b/usr.bin/pcc/mip/regs.c
index e87069d6a15..55f605a3629 100644
--- a/usr.bin/pcc/mip/regs.c
+++ b/usr.bin/pcc/mip/regs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: regs.c,v 1.15 2008/01/12 17:17:28 ragge Exp $ */
+/* $OpenBSD: regs.c,v 1.16 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2005 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -125,6 +125,7 @@ static REGW precolored, simplifyWorklist, freezeWorklist, spillWorklist,
static REGW initial, *nblock;
static void insnwalk(NODE *p);
#ifdef PCC_DEBUG
+int use_regw;
int nodnum = 100;
#define SETNUM(x) (x)->nodnum = nodnum++
#define ASGNUM(x) (x)->nodnum
@@ -803,6 +804,8 @@ setlive(NODE *p, int set, REGW *rv)
static void
addedge_r(NODE *p, REGW *w)
{
+ RRDEBUG(("addedge_r: node %p regw %p\n", p, w));
+
if (p->n_regw != NULL) {
AddEdge(p->n_regw, w);
return;
@@ -846,6 +849,7 @@ insnwalk(NODE *p)
int o = p->n_op;
struct optab *q = &table[TBLIDX(p->n_su)];
REGW *lr, *rr, *rv, *r, *rrv, *lrv;
+ NODE *lp, *rp;
int i, n;
RDEBUG(("insnwalk %p\n", p));
@@ -881,7 +885,9 @@ insnwalk(NODE *p)
/* Check leaves for results in registers */
lr = optype(o) != LTYPE ? p->n_left->n_regw : NULL;
+ lp = optype(o) != LTYPE ? p->n_left : NULL;
rr = optype(o) == BITYPE ? p->n_right->n_regw : NULL;
+ rp = optype(o) == BITYPE ? p->n_right : NULL;
/* simple needs */
n = ncnt(q->needs);
@@ -947,6 +953,13 @@ insnwalk(NODE *p)
}
if (o == ASSIGN) {
+ /* avoid use of unhandled registers */
+ if (p->n_left->n_op == REG &&
+ !TESTBIT(validregs, regno(p->n_left)))
+ lr = NULL;
+ if (p->n_right->n_op == REG &&
+ !TESTBIT(validregs, regno(p->n_right)))
+ rr = NULL;
/* needs special treatment */
if (lr && rr)
moveadd(lr, rr);
@@ -967,13 +980,13 @@ insnwalk(NODE *p)
} else if (q->rewrite & RLEFT) {
if (lr && rv)
moveadd(rv, lr), lrv = rv;
- if (rr && rv)
- AddEdge(rr, rv);
+ if (rv && rp)
+ addedge_r(rp, rv);
} else if (q->rewrite & RRIGHT) {
if (rr && rv)
moveadd(rv, rr), rrv = rv;
- if (lr && rv)
- AddEdge(lr, rv);
+ if (rv && lp)
+ addedge_r(lp, rv);
}
switch (optype(o)) {
@@ -1734,14 +1747,6 @@ SelectSpill(void)
FreezeMoves(w);
}
-int gregn(REGW *);
-
-int
-gregn(REGW *w)
-{
- return w->nodnum;
-}
-
/*
* Set class on long-lived temporaries based on its type.
*/
@@ -2104,6 +2109,33 @@ RewriteProgram(struct interpass *ip)
return rwtyp;
}
+#ifdef PCC_DEBUG
+/*
+ * Print TEMP/REG contents in a node.
+ */
+void
+prtreg(FILE *fp, NODE *p)
+{
+ int i, n = p->n_su == -1 ? 0 : ncnt(table[TBLIDX(p->n_su)].needs);
+
+ if (use_regw) {
+ fprintf(fp, "TEMP ");
+ if (p->n_regw != NULL) {
+ for (i = 0; i < n+1; i++)
+ fprintf(fp, "%d ", p->n_regw[i].nodnum);
+ } else
+ fprintf(fp, "<undef>");
+ } else {
+ fprintf(fp, "REG ");
+ if (p->n_reg != -1) {
+ for (i = 0; i < n+1; i++)
+ fprintf(fp, "%s ", rnames[DECRA(p->n_reg, i)]);
+ } else
+ fprintf(fp, "<undef>");
+ }
+}
+#endif
+
#ifdef notyet
/*
* Assign instructions, calculate evaluation order and
@@ -2222,7 +2254,9 @@ onlyperm: /* XXX - should not have to redo all */
RDEBUG(("nsucomp allocated %d temps (%d,%d)\n",
tempmax-tempmin, tempmin, tempmax));
+ use_regw = 1;
RPRINTIP(ipole);
+ use_regw = 0;
RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin,
tempmin, tempmax));
diff --git a/usr.bin/pcc/mips/code.c b/usr.bin/pcc/mips/code.c
index be0830362ac..fcb0ec0cd75 100644
--- a/usr.bin/pcc/mips/code.c
+++ b/usr.bin/pcc/mips/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: code.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -36,6 +36,45 @@
#include "pass1.h"
/*
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
+ */
+void
+defloc(struct symtab *sp)
+{
+ static char *loctbl[] = { "text", "data", "section .rodata" };
+ static int lastloc = -1;
+ TWORD t;
+ int s;
+
+ if (sp == NULL) {
+ lastloc = -1;
+ return;
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+ lastloc = s;
+ if (s == PROG)
+ return; /* text is written in prologue() */
+ if (s != lastloc)
+ printf(" .%s\n", loctbl[s]);
+ printf(" .p2align %d\n", ispow2(talign(t, sp->ssue)));
+ if (sp->sclass == EXTDEF)
+ printf(" .globl %s\n", sp->soname);
+ if (sp->slevel == 0) {
+#ifdef USE_GAS
+ printf("\t.type %s,@object\n", sp->soname);
+ printf("\t.size %s," CONFMT "\n", sp->soname,
+ tsize(sp->stype, sp->sdf, sp->ssue));
+#endif
+ printf("%s:\n", sp->soname);
+ } else
+ printf(LABFMT ":\n", sp->soffset);
+}
+
+
+#ifdef notdef
+/*
* cause the alignment to become a multiple of n
* never called for text segment.
*/
@@ -55,11 +94,8 @@ defalign(int n)
void
defnam(struct symtab *p)
{
- char *c = p->sname;
+ char *c = p->soname;
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
-#endif
if (p->sclass == EXTDEF)
printf("\t.globl %s\n", c);
#ifdef USE_GAS
@@ -68,6 +104,7 @@ defnam(struct symtab *p)
#endif
printf("%s:\n", c);
}
+#endif
static int rvnr;
@@ -90,7 +127,7 @@ efcode()
q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue);
q->n_rval = V0;
p = tempnode(0, INCREF(ty), 0, cftnsp->ssue);
- tempnr = p->n_lval;
+ tempnr = regno(p);
p = buildtree(ASSIGN, p, q);
ecomp(p);
@@ -119,7 +156,7 @@ putintemp(struct symtab *sym)
spname = sym;
p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
- sym->soffset = p->n_left->n_lval;
+ sym->soffset = regno(p->n_left);
sym->sflags |= STNODE;
ecomp(p);
}
@@ -132,7 +169,7 @@ param_retptr(void)
NODE *p, *q;
p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue);
- rvnr = p->n_lval;
+ rvnr = regno(p);
q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
q->n_rval = A0;
p = buildtree(ASSIGN, p, q);
@@ -200,7 +237,7 @@ param_64bit(struct symtab *sym, int *regp, int dotemps)
q->n_rval = A0A1 + (reg - A0);
if (dotemps) {
p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
- sym->soffset = p->n_lval;
+ sym->soffset = regno(p);
sym->sflags |= STNODE;
} else {
spname = sym;
@@ -222,7 +259,7 @@ param_32bit(struct symtab *sym, int *regp, int dotemps)
q->n_rval = (*regp)++;
if (dotemps) {
p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
- sym->soffset = p->n_lval;
+ sym->soffset = regno(p);
sym->sflags |= STNODE;
} else {
spname = sym;
@@ -262,7 +299,7 @@ param_double(struct symtab *sym, int *regp, int dotemps)
}
t = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG));
- tmpnr = t->n_lval;
+ tmpnr = regno(t);
q = block(REG, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG));
q->n_rval = A0A1 + (reg - A0);
p = buildtree(ASSIGN, t, q);
@@ -293,7 +330,7 @@ param_float(struct symtab *sym, int *regp, int dotemps)
int tmpnr;
t = tempnode(0, INT, 0, MKSUE(INT));
- tmpnr = t->n_lval;
+ tmpnr = regno(t);
q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
q->n_rval = (*regp)++;
p = buildtree(ASSIGN, t, q);
@@ -406,6 +443,7 @@ bjobcode()
printf("\t.abicalls\n");
}
+#ifdef notdef
/*
* Print character t at position i in one string, until t == -1.
* Locctr & label is already defined.
@@ -445,6 +483,7 @@ bycode(int t, int i)
}
}
}
+#endif
/*
* return the alignment of field of type t
@@ -495,7 +534,7 @@ movearg_struct(NODE *p, NODE *parent, int *regp)
nfree(p);
ty = l->n_type;
t = tempnode(0, l->n_type, l->n_df, l->n_sue);
- tmpnr = t->n_lval;
+ tmpnr = regno(t);
l = buildtree(ASSIGN, t, l);
if (p != parent) {
@@ -620,7 +659,7 @@ moveargs(NODE *p, int *regp)
} else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
/* XXX bounce in and out of temporary to change to longlong */
NODE *t1 = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG));
- int tmpnr = t1->n_lval;
+ int tmpnr = regno(t1);
NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue);
t1 = movearg_64bit(t1, regp);
r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_sue);
@@ -633,7 +672,7 @@ moveargs(NODE *p, int *regp)
} else if (r->n_type == FLOAT) {
/* XXX bounce in and out of temporary to change to int */
NODE *t1 = tempnode(0, INT, 0, MKSUE(INT));
- int tmpnr = t1->n_lval;
+ int tmpnr = regno(t1);
NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue);
t1 = movearg_32bit(t1, regp);
r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_sue);
diff --git a/usr.bin/pcc/mips/local.c b/usr.bin/pcc/mips/local.c
index 4c8a43f0f47..052e7de3fea 100644
--- a/usr.bin/pcc/mips/local.c
+++ b/usr.bin/pcc/mips/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: local.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -75,7 +75,7 @@ clocal(NODE *p)
if (p->n_type == PTR+VOID)
isptrvoid = 1;
r = tempnode(0, p->n_type, p->n_df, p->n_sue);
- tmpnr = r->n_lval;
+ tmpnr = regno(r);
r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_sue);
p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue);
@@ -348,6 +348,28 @@ clocal(NODE *p)
void
myp2tree(NODE *p)
{
+ struct symtab *sp;
+
+ if (p->n_op != FCON)
+ return;
+
+ /* Write float constants to memory */
+
+ sp = tmpalloc(sizeof(struct symtab));
+ sp->sclass = STATIC;
+ sp->slevel = 1; /* fake numeric label */
+ sp->soffset = getlab();
+ sp->sflags = 0;
+ sp->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, btdims[p->n_type].suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
+
}
/*ARGSUSED*/
@@ -484,7 +506,7 @@ ninval(CONSZ off, int fsz, NODE *p)
q->sclass == ILABEL) {
printf("+" LABFMT, q->soffset);
} else
- printf("+%s", exname(q->sname));
+ printf("+%s", exname(q->soname));
}
printf("\n");
break;
@@ -563,6 +585,73 @@ extdec(struct symtab *q)
{
}
+/*
+ * Print out a string of characters.
+ * Assume that the assembler understands C-style escape
+ * sequences.
+ */
+void
+instring(struct symtab *sp)
+{
+ char *s, *str;
+
+ defloc(sp);
+ str = sp->sname;
+
+ /* be kind to assemblers and avoid long strings */
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; ) {
+ if (*s++ == '\\') {
+ (void)esccon(&s);
+ }
+ if (s - str > 60) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = bcon(0);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
+
+/* make a common declaration for id, if reasonable */
+void
+defzero(struct symtab *sp)
+{
+ int off;
+
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,0%o\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",0%o\n", sp->soffset, off);
+}
+
+
+#ifdef notdef
/* make a common declaration for id, if reasonable */
void
commdec(struct symtab *q)
@@ -572,11 +661,7 @@ commdec(struct symtab *q)
off = tsize(q->stype, q->sdf, q->ssue);
off = (off+(SZCHAR-1))/SZCHAR;
-#ifdef GCC_COMPAT
- printf(" .comm %s,%d\n", gcc_findname(q), off);
-#else
- printf(" .comm %s,%d\n", exname(q->sname), off);
-#endif
+ printf(" .comm %s,%d\n", exname(q->soname), off);
}
/* make a local common declaration for id, if reasonable */
@@ -588,11 +673,7 @@ lcommdec(struct symtab *q)
off = tsize(q->stype, q->sdf, q->ssue);
off = (off+(SZCHAR-1))/SZCHAR;
if (q->slevel == 0)
-#ifdef GCC_COMPAT
- printf("\t.lcomm %s,%d\n", gcc_findname(q), off);
-#else
- printf("\t.lcomm %s,%d\n", exname(q->sname), off);
-#endif
+ printf("\t.lcomm %s,%d\n", exname(q->soname), off);
else
printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off);
}
@@ -625,6 +706,7 @@ setloc1(int locc)
if (locc == STRNG)
printf("\t.align 2\n");
}
+#endif
/*
* Initialize a bitfield.
@@ -770,7 +852,7 @@ mips_builtin_va_arg(NODE *f, NODE *a)
/* create a copy to a temp node */
p = tcopy(a->n_left);
q = tempnode(0, p->n_type, p->n_df, p->n_sue);
- tmpnr = q->n_lval;
+ tmpnr = regno(q);
p = buildtree(ASSIGN, q, p);
r = a->n_right;
@@ -821,3 +903,19 @@ bad:
uerror("bad argument to __buildtin_va_copy");
return bcon(0);
}
+/*
+ * Give target the opportunity of handling pragmas.
+ */
+int
+mypragma(char **ary)
+{
+ return 0; }
+
+/*
+ * Called when a identifier has been declared, to give target last word.
+ */
+void
+fixdef(struct symtab *sp)
+{
+}
+
diff --git a/usr.bin/pcc/mips/local2.c b/usr.bin/pcc/mips/local2.c
index 9ff1ed1eafc..0b85505670f 100644
--- a/usr.bin/pcc/mips/local2.c
+++ b/usr.bin/pcc/mips/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: local2.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -755,7 +755,7 @@ fldexpand(NODE *p, int cookie, char **cp)
break;
case 'M':
case 'N':
- val = 1 << UPKFSZ(p->n_rval);
+ val = (CONSZ)1 << UPKFSZ(p->n_rval);
--val;
val <<= UPKFOFF(p->n_rval);
printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff);
@@ -928,7 +928,6 @@ adrput(FILE * io, NODE * p)
conput(io, p);
return;
- case MOVE:
case REG:
if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
print_reg64name(io, p->n_rval, 0);
diff --git a/usr.bin/pcc/mips/macdefs.h b/usr.bin/pcc/mips/macdefs.h
index c892c6e5faf..84d173b8788 100644
--- a/usr.bin/pcc/mips/macdefs.h
+++ b/usr.bin/pcc/mips/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.4 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: macdefs.h,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
diff --git a/usr.bin/pcc/mips/order.c b/usr.bin/pcc/mips/order.c
index 29c28ec5e64..df05ba7ac55 100644
--- a/usr.bin/pcc/mips/order.c
+++ b/usr.bin/pcc/mips/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
diff --git a/usr.bin/pcc/mips/table.c b/usr.bin/pcc/mips/table.c
index 48c2f3f9872..2839d163265 100644
--- a/usr.bin/pcc/mips/table.c
+++ b/usr.bin/pcc/mips/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: table.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
diff --git a/usr.bin/pcc/powerpc/code.c b/usr.bin/pcc/powerpc/code.c
index 74a6025b37d..bc9a54cea42 100644
--- a/usr.bin/pcc/powerpc/code.c
+++ b/usr.bin/pcc/powerpc/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.7 2007/12/28 12:32:55 stefan Exp $ */
+/* $OpenBSD: code.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -32,160 +32,464 @@
#include "pass1.h"
#include "pass2.h"
+static void genswitch_bintree(int num, TWORD ty, struct swents **p, int n);
+
#if 0
-static void genswitch_simple(int num, struct swents **p, int n);
-static void genswitch_bintree(int num, struct swents **p, int n);
static void genswitch_table(int num, struct swents **p, int n);
static void genswitch_mrst(int num, struct swents **p, int n);
#endif
+int lastloc = -1;
+
+static int rvnr;
+
/*
- * cause the alignment to become a multiple of n
- * never called for text segment.
+ * Define everything needed to print out some data (or text).
+ * This means segment, alignment, visibility, etc.
*/
void
-defalign(int n)
+defloc(struct symtab *sp)
{
- if ((n = ispow2(n / SZCHAR)) == -1)
+#if defined(ELFABI)
+ static char *loctbl[] = { "text", "data", "rodata" };
+#elif defined(MACHOABI)
+ static char *loctbl[] = { "text", "data", "const_data" };
+#endif
+ TWORD t;
+ int s, n;
+
+ if (sp == NULL) {
+ lastloc = -1;
+ return;
+ }
+ t = sp->stype;
+ s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
+ if (s != lastloc)
+ printf(" .%s\n", loctbl[s]);
+ lastloc = s;
+
+ if (s == PROG)
+ n = 2;
+ else if ((n = ispow2(talign(t, sp->ssue) / SZCHAR)) == -1)
cerror("defalign: n != 2^i");
printf(" .p2align %d\n", n);
+
+ if (sp->sclass == EXTDEF)
+ printf(" .globl %s\n", exname(sp->soname));
+ if (sp->slevel == 0)
+ printf("%s:\n", exname(sp->soname));
+ else
+ printf(LABFMT ":\n", sp->soffset);
}
-/*
- * define the current location as the name p->sname
- * never called for text segment.
+/* Put a symbol in a temporary
+ * used by bfcode() and its helpers
*/
-void
-defnam(struct symtab *p)
+static void
+putintemp(struct symtab *sym)
{
- char *c = p->sname;
+ NODE *p;
+
+ spname = sym;
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
+ sym->soffset = regno(p->n_left);
+ sym->sflags |= STNODE;
+ ecomp(p);
+}
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
+/* setup a 64-bit parameter (double/ldouble/longlong)
+ * used by bfcode() */
+static void
+param_64bit(struct symtab *sym, int *argoffp, int dotemps)
+{
+ int argoff = *argoffp;
+ NODE *p, *q;
+ int navail;
+
+#if ALLONGLONG == 64
+ /* alignment */
+ ++argoff;
+ argoff &= ~1;
#endif
- if (p->sclass == EXTDEF)
- printf(" .globl %s\n", exname(c));
- printf("%s:\n", exname(c));
+
+ navail = NARGREGS - argoff;
+
+ if (navail < 2) {
+ /* half in and half out of the registers */
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R3 + argoff;
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = FPREG;
+ p = block(PLUS, p, bcon(sym->soffset/SZCHAR), PTR+INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, INT, 0, MKSUE(INT));
+ } else {
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ regno(q) = R3R4 + argoff;
+ if (dotemps) {
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ } else {
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ }
+ }
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ *argoffp = argoff + 2;
}
+/* setup a 32-bit param on the stack
+ * used by bfcode() */
+static void
+param_32bit(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q;
+
+ q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
+ regno(q) = R3 + (*argoffp)++;
+ if (dotemps) {
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ sym->soffset = regno(p);
+ sym->sflags |= STNODE;
+ } else {
+ spname = sym;
+ p = buildtree(NAME, 0, 0);
+ }
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+}
-/*
- * code for the end of a function
- * deals with struct return here
- */
-void
-efcode()
+/* setup a double param on the stack
+ * used by bfcode() */
+static void
+param_double(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q, *t;
+ int tmpnr;
+
+ /*
+ * we have to dump the double from the general register
+ * into a temp, since the register allocator doesn't like
+ * floats to be in CLASSA. This may not work for -xtemps.
+ */
+
+ if (xtemps) {
+ q = block(REG, NIL, NIL, ULONGLONG, 0, MKSUE(ULONGLONG));
+ regno(q) = R3R4 + *argoffp;
+ p = block(REG, NIL, NIL, PTR+ULONGLONG, 0, MKSUE(ULONGLONG));
+ regno(p) = SPREG;
+ p = block(PLUS, p, bcon(-8), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, ULONGLONG, 0, MKSUE(ULONGLONG));
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+
+ t = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ tmpnr = regno(t);
+ p = block(REG, NIL, NIL,
+ INCREF(sym->stype), sym->sdf, sym->ssue);
+ regno(p) = SPREG;
+ p = block(PLUS, p, bcon(-8), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->ssue);
+ p = buildtree(ASSIGN, t, p);
+ ecomp(p);
+ } else {
+ /* bounce straight into temp */
+ p = block(REG, NIL, NIL, ULONGLONG, 0, MKSUE(ULONGLONG));
+ regno(p) = R3R4 + *argoffp;
+ t = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG));
+ tmpnr = regno(t);
+ p = buildtree(ASSIGN, t, p);
+ ecomp(p);
+ }
+
+ (*argoffp) += 2;
+
+ sym->soffset = tmpnr;
+ sym->sflags |= STNODE;
+}
+
+/* setup a float param on the stack
+ * used by bfcode() */
+static void
+param_float(struct symtab *sym, int *argoffp, int dotemps)
+{
+ NODE *p, *q, *t;
+ int tmpnr;
+
+ /*
+ * we have to dump the float from the general register
+ * into a temp, since the register allocator doesn't like
+ * floats to be in CLASSA. This may not work for -xtemps.
+ */
+
+ if (xtemps) {
+ /* bounce onto TOS */
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R3 + (*argoffp);
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = SPREG;
+ p = block(PLUS, p, bcon(-4), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+
+ t = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ tmpnr = regno(t);
+ p = block(REG, NIL, NIL, INCREF(sym->stype),
+ sym->sdf, sym->ssue);
+ regno(p) = SPREG;
+ p = block(PLUS, p, bcon(-4), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->ssue);
+ p = buildtree(ASSIGN, t, p);
+ ecomp(p);
+ } else {
+ /* bounce straight into temp */
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = R3 + (*argoffp);
+ t = tempnode(0, INT, 0, MKSUE(INT));
+ tmpnr = regno(t);
+ p = buildtree(ASSIGN, t, p);
+ ecomp(p);
+ }
+
+ (*argoffp)++;
+
+ sym->soffset = tmpnr;
+ sym->sflags |= STNODE;
+}
+
+/* setup the hidden pointer to struct return parameter
+ * used by bfcode() */
+static void
+param_retstruct(void)
{
-#if 0
NODE *p, *q;
- int sz;
-#endif
-#if 0
- printf("EFCODE:\n");
-#endif
+ /* XXX what if it is a union? */
+ p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue);
+ rvnr = regno(p);
+ q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue);
+ regno(q) = R3;
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+}
- if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
- return;
- assert(0);
-#if 0
- /* 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);
-#endif
+
+/* setup struct parameter
+ * push the registers out to memory
+ * used by bfcode() */
+static void
+param_struct(struct symtab *sym, int *argoffp)
+{
+ int argoff = *argoffp;
+ NODE *p, *q;
+ int navail;
+ int sz;
+ int off;
+ int num;
+ int i;
+
+ navail = NARGREGS - argoff;
+ sz = tsize(sym->stype, sym->sdf, sym->ssue) / SZINT;
+ off = ARGINIT/SZINT + argoff;
+ num = sz > navail ? navail : sz;
+ for (i = 0; i < num; i++) {
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R3 + argoff++;
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = SPREG;
+ p = block(PLUS, p, bcon(4*off++), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+ }
+
+ *argoffp = argoff;
}
/*
- * code for the beginning of a function; a is an array of
- * indices in symtab for the arguments; n is the number
+ * code for the beginning of a function
+ * sp is an array of indices in symtab for the arguments
+ * cnt is the number of arguments
*/
void
-bfcode(struct symtab **a, int n)
+bfcode(struct symtab **sp, int cnt)
{
- int i, m;
-
-#if 0
- printf("BFCODE start with %d arguments\n", n);
+#ifdef USE_GOTNR
+ extern int gotnr;
#endif
- 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);
+ union arglist *usym;
+ int saveallargs = 0;
+ int i, argoff = 0;
+
+ /*
+ * Detect if this function has ellipses and save all
+ * argument registers onto stack.
+ */
+ usym = cftnsp->sdf->dfun;
+ while (usym && usym->type != TNULL) {
+ if (usym->type == TELLIPSIS) {
+ saveallargs = 1;
+ break;
+ }
+ ++usym;
+ }
+
+ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
+ param_retstruct();
+ ++argoff;
}
- m = n <= 8 ? n : 8;
-
-#if 0
- /* if optimised, assign parameters to registers */
- /* XXX consider the size of the types */
- for (i=0; i < m; i++) {
- a[i]->hdr.h_sclass = REGISTER;
- a[i]->hdr.h_offset = R3 + i;
+#ifdef USE_GOTNR
+ if (kflag) {
+ /* put GOT register into temporary */
+ NODE *q, *p;
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = GOTREG;
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ gotnr = regno(p);
+ ecomp(buildtree(ASSIGN, p, q));
}
#endif
- /* if not optimised, */
- /* save the register arguments (R3-R10) onto the stack */
- int passedargoff = ARGINIT + FIXEDSTACKSIZE*8; // XXX must add the size of the stack frame
- int reg = R3;
- for (i=0; i < m; i++) {
- NODE *r, *p;
- a[i]->sclass = PARAM;
- a[i]->soffset = NOOFFSET;
- oalloc(a[i], &passedargoff);
- spname = a[i];
- p = buildtree(NAME, NIL, NIL);
- r = bcon(0);
- r->n_op = REG;
- if (BTYPE(p->n_type) == LONGLONG || BTYPE(p->n_type) == ULONGLONG) {
- r->n_rval = R3R4+(reg-R3);
- reg += 2;
- } else {
- r->n_rval = reg++;
+ /* recalculate the arg offset and create TEMP moves */
+ for (i = 0; i < cnt; i++) {
+
+ if (sp[i] == NULL)
+ continue;
+
+ if ((argoff >= NARGREGS) && !xtemps)
+ break;
+
+ if (argoff >= NARGREGS) {
+ putintemp(sp[i]);
+ } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) {
+ param_struct(sp[i], &argoff);
+ } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) {
+ param_64bit(sp[i], &argoff, xtemps && !saveallargs);
+ } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) {
+ if (features(FEATURE_HARDFLOAT))
+ param_double(sp[i], &argoff,
+ xtemps && !saveallargs);
+ else
+ param_64bit(sp[i], &argoff,
+ xtemps && !saveallargs);
+ } else if (sp[i]->stype == FLOAT) {
+ if (features(FEATURE_HARDFLOAT))
+ param_float(sp[i], &argoff,
+ xtemps && !saveallargs);
+ else
+ param_32bit(sp[i], &argoff,
+ xtemps && !saveallargs);
+ } else {
+ param_32bit(sp[i], &argoff, xtemps && !saveallargs);
}
- r->n_type = p->n_type;
- r->n_sue = p->n_sue;
- r->n_df = p->n_df;
- ecode(buildtree(ASSIGN, p, r));
+ }
+
+ /* if saveallargs, save the rest of the args onto the stack */
+ while (saveallargs && argoff < NARGREGS) {
+ NODE *p, *q;
+ /* int off = (ARGINIT+FIXEDSTACKSIZE*SZCHAR)/SZINT + argoff; */
+ int off = ARGINIT/SZINT + argoff;
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R3 + argoff++;
+ p = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(p) = FPREG;
+ p = block(PLUS, p, bcon(4*off), INT, 0, MKSUE(INT));
+ p = block(UMUL, p, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
}
-#if 1
- /* XXXHACK save the rest of the registers too, for varargs */
- for (; reg < R11; reg++) {
- NODE *r, *l;
- l = bcon(0);
- l->n_op = OREG;
- l->n_lval = (passedargoff/SZCHAR);
- l->n_rval = FPREG;
- l->n_type = INT;
- passedargoff += SZINT;
- r = bcon(0);
- r->n_op = REG;
- r->n_rval = reg;
- r->n_type = INT;
- ecode(buildtree(ASSIGN, l, r));
- }
-#endif
-
-#if 0
- printf("BFCODE end\n");
+ /* profiling */
+ if (pflag) {
+ NODE *p;
+
+#if defined(ELFABI)
+
+ spname = lookup("_mcount", 0);
+ spname->stype = EXTERN;
+ p = buildtree(NAME, NIL, NIL);
+ p->n_sp->sclass = EXTERN;
+ p = clocal(p);
+ p = buildtree(ADDROF, p, NIL);
+ p = block(UCALL, p, NIL, INT, 0, MKSUE(INT));
+ ecomp(funcode(p));
+
+
+#elif defined(MACHOABI)
+
+ NODE *q;
+ int tmpnr;
+
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = R0;
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ tmpnr = regno(p);
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+
+ q = tempnode(tmpnr, INT, 0, MKSUE(INT));
+
+ spname = lookup("mcount", 0);
+ spname->stype = EXTERN;
+ p = buildtree(NAME, NIL, NIL);
+ p->n_sp->sclass = EXTERN;
+ p = clocal(p);
+ p = buildtree(ADDROF, p, NIL);
+ p = block(CALL, p, q, INT, 0, MKSUE(INT));
+ ecomp(funcode(p));
+
#endif
+ }
}
+/*
+ * code for the end of a function
+ * deals with struct return here
+ */
+void
+efcode()
+{
+ NODE *p, *q;
+ int tempnr;
+ int ty;
+
+#ifdef USE_GOTNR
+ extern int gotnr;
+ gotnr = 0;
+#endif
+
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+
+ ty = cftnsp->stype - FTN;
+
+ q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue);
+ regno(q) = R3;
+ p = tempnode(0, INCREF(ty), 0, cftnsp->ssue);
+ tempnr = regno(p);
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+
+ q = tempnode(tempnr, INCREF(ty), 0, cftnsp->ssue);
+ q = buildtree(UMUL, q, NIL);
+
+ p = tempnode(rvnr, INCREF(ty), 0, cftnsp->ssue);
+ p = buildtree(UMUL, p, NIL);
+
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+
+ q = tempnode(rvnr, INCREF(ty), 0, cftnsp->ssue);
+ p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue);
+ regno(p) = R3;
+ p = buildtree(ASSIGN, p, q);
+ ecomp(p);
+}
/*
* by now, the automatics and register variables are allocated
@@ -193,9 +497,6 @@ bfcode(struct symtab **a, int n)
void
bccode()
{
-#if 0
- printf("BCCODE: autooff=%d, SZINT=%d\n", autooff, SZINT);
-#endif
SETOFF(autooff, SZINT);
}
@@ -207,58 +508,69 @@ struct stub nlplist;
void
ejobcode(int flag )
{
-#if 0
- printf("EJOBCODE:\n");
-#endif
+#if defined(MACHOABI)
+ /*
+ * iterate over the stublist and output the PIC stubs
+` */
if (kflag) {
- // iterate over the stublist and output the PIC stubs
struct stub *p;
DLIST_FOREACH(p, &stublist, link) {
printf("\t.section __TEXT, __picsymbolstub1,symbol_stubs,pure_instructions,32\n");
printf("\t.align 5\n");
- printf("%s$stub:\n", p->name);
- printf("\t.indirect_symbol %s\n", p->name);
+ printf("L%s$stub:\n", p->name);
+ if (strcmp(p->name, "mcount") == 0)
+ printf("\t.indirect_symbol %s\n", p->name);
+ else
+ printf("\t.indirect_symbol %s\n",
+ exname(p->name));
printf("\tmflr r0\n");
- printf("\tbcl 20,31,L%s$stub$spb\n", p->name);
- printf("L%s$stub$spb:\n", p->name);
+ printf("\tbcl 20,31,L%s$spb\n", p->name);
+ printf("L%s$spb:\n", p->name);
printf("\tmflr r11\n");
- printf("\taddis r11,r11,ha16(L%s$lazy_ptr-L%s$stub$spb)\n", p->name, p->name);
+ printf("\taddis r11,r11,ha16(L%s$lazy_ptr-L%s$spb)\n",
+ p->name, p->name);
printf("\tmtlr r0\n");
- printf("\tlwzu r12,lo16(L%s$lazy_ptr-L%s$stub$spb)(r11)\n", p->name, p->name);
+ printf("\tlwzu r12,lo16(L%s$lazy_ptr-L%s$spb)(r11)\n",
+ p->name, p->name);
printf("\tmtctr r12\n");
printf("\tbctr\n");
printf("\t.lazy_symbol_pointer\n");
printf("L%s$lazy_ptr:\n", p->name);
- printf("\t.indirect_symbol %s\n", p->name);
+ if (strcmp(p->name, "mcount") == 0)
+ printf("\t.indirect_symbol %s\n", p->name);
+ else
+ printf("\t.indirect_symbol %s\n",
+ exname(p->name));
printf("\t.long dyld_stub_binding_helper\n");
printf("\t.subsections_via_symbols\n");
-
}
printf("\t.non_lazy_symbol_pointer\n");
DLIST_FOREACH(p, &nlplist, link) {
printf("L%s$non_lazy_ptr:\n", p->name);
- printf("\t.indirect_symbol %s\n", p->name);
+ if (strcmp(p->name, "mcount") == 0)
+ printf("\t.indirect_symbol %s\n", p->name);
+ else
+ printf("\t.indirect_symbol %s\n",
+ exname(p->name));
printf("\t.long 0\n");
}
- // memory leak here
}
+#endif
+
}
void
bjobcode()
{
-#if 0
- printf("BJOBCODE:\n");
-#endif
-
DLIST_INIT(&stublist, link);
DLIST_INIT(&nlplist, link);
}
+#ifdef notdef
/*
* Print character t at position i in one string, until t == -1.
* Locctr & label is already defined.
@@ -292,6 +604,7 @@ bycode(int t, int i)
}
}
}
+#endif
/*
* return the alignment of field of type t
@@ -299,7 +612,7 @@ bycode(int t, int i)
int
fldal(unsigned int t)
{
- uerror("illegal field type");
+ uerror("fldal: illegal field type");
return(ALINT);
}
@@ -315,22 +628,14 @@ fldty(struct symtab *p)
int
mygenswitch(int num, TWORD type, struct swents **p, int n)
{
- return 0;
-#if 0
- if (n == 0) {
- if (p[0]->sval != 0)
- branch(p[0]->sval);
- return;
+ if (num > 10) {
+ genswitch_bintree(num, type, p, n);
+ return 1;
}
-#ifdef PCC_DEBUG
- if (xdebug) {
- int i;
- for (i = 1; i <= n; i++)
- printf("%d: %llu\n", i, p[i]->sval);
- }
-#endif
+ return 0;
+#if 0
if (0)
genswitch_table(num, p, n);
if (0)
@@ -339,46 +644,31 @@ mygenswitch(int num, TWORD type, struct swents **p, int n)
#endif
}
-#if 0
-static void
-genswitch_simple(int num, struct swents **p, int n)
-{
- NODE *r;
- int i;
-
- for (i = 1; i <= n; ++i) {
- 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);
-}
-
-static void bintree_rec(int num, struct swents **p, int n, int s, int e);
+static void bintree_rec(TWORD ty, int num,
+ struct swents **p, int n, int s, int e);
static void
-genswitch_bintree(int num, struct swents **p, int n)
+genswitch_bintree(int num, TWORD ty, struct swents **p, int n)
{
int lab = getlab();
if (p[0]->slab == 0)
p[0]->slab = lab;
- bintree_rec(num, p, n, 1, n);
+ bintree_rec(ty, num, p, n, 1, n);
plabel(lab);
}
static void
-bintree_rec(int num, struct swents **p, int n, int s, int e)
+bintree_rec(TWORD ty, int num, struct swents **p, int n, int s, int e)
{
NODE *r;
int rlabel;
int h;
if (s == e) {
- r = tempnode(num, INT, 0, MKSUE(INT));
+ r = tempnode(num, ty, 0, MKSUE(ty));
r = buildtree(NE, r, bcon(p[s]->sval));
cbranch(buildtree(NOT, r, NIL), bcon(p[s]->slab));
branch(p[0]->slab);
@@ -389,15 +679,16 @@ bintree_rec(int num, struct swents **p, int n, int s, int e)
h = s + (e - s) / 2;
- r = tempnode(num, INT, 0, MKSUE(INT));
+ r = tempnode(num, ty, 0, MKSUE(ty));
r = buildtree(GT, r, bcon(p[h]->sval));
cbranch(r, bcon(rlabel));
- bintree_rec(num, p, n, s, h);
+ bintree_rec(ty, num, p, n, s, h);
plabel(rlabel);
- bintree_rec(num, p, n, h+1, e);
+ bintree_rec(ty, num, p, n, h+1, e);
}
+#if 0
static void
genswitch_table(int num, struct swents **p, int n)
@@ -422,7 +713,7 @@ genswitch_table(int num, struct swents **p, int n)
r = tempnode(num, UNSIGNED, 0, MKSUE(UNSIGNED));
r = buildtree(MINUS, r, bcon(minval));
t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED));
- tval = t->n_lval;
+ tval = regno(t);
r = buildtree(ASSIGN, t, r);
ecomp(r);
@@ -448,7 +739,7 @@ genswitch_table(int num, struct swents **p, int n)
r = buildtree(ASSIGN, t, r);
ecomp(r);
- r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED));
+ r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKSUE(UNSIGNED));
r = buildtree(UMUL, r, NIL);
t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR));
t->n_sp = strtbl;
@@ -569,7 +860,7 @@ mrst_rec(int num, struct swents **p, int n, int *state, int lab)
r = buildtree(RS, r, bcon(lowbit));
t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED));
- tval = t->n_lval;
+ tval = regno(t);
r = buildtree(ASSIGN, t, r);
ecomp(r);
@@ -588,7 +879,7 @@ mrst_rec(int num, struct swents **p, int n, int *state, int lab)
r = buildtree(ASSIGN, t, r);
ecomp(r);
- r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED));
+ r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKSUE(UNSIGNED));
r = buildtree(UMUL, r, NIL);
t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR));
t->n_sp = strtbl;
@@ -802,11 +1093,437 @@ mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *l
#endif
/*
+ * Straighten a chain of CM ops so that the CM nodes
+ * only appear on the left node.
+ *
+ * CM CM
+ * CM CM CM b
+ * x y a b CM a
+ * x y
+ *
+ * CM CM
+ * CM CM CM c
+ * CM z CM c CM b
+ * x y a b CM a
+ * CM z
+ * x y
+ */
+static NODE *
+straighten(NODE *p)
+{
+ NODE *r = p->n_right;
+
+ if (p->n_op != CM || r->n_op != CM)
+ return p;
+
+ p->n_right = r->n_left;
+ r->n_left = straighten(p);
+
+ return r;
+}
+
+static NODE *
+reverse1(NODE *p, NODE *a)
+{
+ NODE *l = p->n_left;
+ NODE *r = p->n_right;
+
+ a->n_right = r;
+ p->n_left = a;
+
+ if (l->n_op == CM) {
+ return reverse1(l, p);
+ } else {
+ p->n_right = l;
+ return p;
+ }
+}
+
+/*
+ * Reverse a chain of CM ops
+ */
+static NODE *
+reverse(NODE *p)
+{
+ NODE *l = p->n_left;
+ NODE *r = p->n_right;
+
+ p->n_left = r;
+
+ if (l->n_op == CM)
+ return reverse1(l, p);
+
+ p->n_right = l;
+
+ return p;
+}
+
+/* push arg onto the stack */
+/* called by moveargs() */
+static NODE *
+pusharg(NODE *p, int *regp)
+{
+ NODE *q;
+ int sz;
+ int off;
+
+ /* convert to register size, if smaller */
+ sz = tsize(p->n_type, p->n_df, p->n_sue);
+ if (sz < SZINT)
+ p = block(SCONV, p, NIL, INT, 0, MKSUE(INT));
+
+ q = block(REG, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_sue);
+ regno(q) = SPREG;
+
+ off = ARGINIT/SZCHAR + 4 * (*regp - R3);
+ q = block(PLUS, q, bcon(off), INT, 0, MKSUE(INT));
+ q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_sue);
+ (*regp) += szty(p->n_type);
+
+ return buildtree(ASSIGN, q, p);
+}
+
+/* setup call stack with 32-bit argument */
+/* called from moveargs() */
+static NODE *
+movearg_32bit(NODE *p, int *regp)
+{
+ int reg = *regp;
+ NODE *q;
+
+ q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
+ regno(q) = reg++;
+ q = buildtree(ASSIGN, q, p);
+
+ *regp = reg;
+ return q;
+}
+
+/* setup call stack with 64-bit argument */
+/* called from moveargs() */
+static NODE *
+movearg_64bit(NODE *p, int *regp)
+{
+ int reg = *regp;
+ NODE *q, *r;
+
+#if ALLONGLONG == 64
+ /* alignment */
+ ++reg;
+ reg &= ~1;
+#endif
+
+ if (reg > R10) {
+ *regp = reg;
+ q = pusharg(p, regp);
+ } else if (reg == R10) {
+ /* half in and half out of the registers */
+ r = tcopy(p);
+ if (!features(FEATURE_BIGENDIAN)) {
+ q = block(SCONV, p, NIL, INT, 0, MKSUE(INT));
+ q = movearg_32bit(q, regp); /* little-endian */
+ r = buildtree(RS, r, bcon(32));
+ r = block(SCONV, r, NIL, INT, 0, MKSUE(INT));
+ r = pusharg(r, regp); /* little-endian */
+ } else {
+ q = buildtree(RS, p, bcon(32));
+ q = block(SCONV, q, NIL, INT, 0, MKSUE(INT));
+ q = movearg_32bit(q, regp); /* big-endian */
+ r = block(SCONV, r, NIL, INT, 0, MKSUE(INT));
+ r = pusharg(r, regp); /* big-endian */
+ }
+ q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_sue));
+ } else {
+ q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
+ regno(q) = R3R4 + (reg - R3);
+ q = buildtree(ASSIGN, q, p);
+ *regp = reg + 2;
+ }
+
+ return q;
+}
+
+/* setup call stack with float argument */
+/* called from moveargs() */
+static NODE *
+movearg_float(NODE *p, int *fregp, int *regp)
+{
+#if defined(MACHOABI)
+ NODE *q, *r;
+ TWORD ty = INCREF(p->n_type);
+ int tmpnr;
+#endif
+
+ p = movearg_32bit(p, fregp);
+
+ /*
+ * On OS/X, floats are passed in the floating-point registers
+ * and in the general registers for compatibily with libraries
+ * compiled to handle soft-float.
+ */
+
+#if defined(MACHOABI)
+
+ if (xtemps) {
+ /* bounce into TOS */
+ r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue);
+ regno(r) = SPREG;
+ r = block(PLUS, r, bcon(-4), INT, 0, MKSUE(INT));
+ r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue);
+ r = buildtree(ASSIGN, r, p);
+ ecomp(r);
+
+ /* bounce into temp */
+ r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT));
+ regno(r) = SPREG;
+ r = block(PLUS, r, bcon(-4), INT, 0, MKSUE(INT));
+ r = block(UMUL, r, NIL, INT, 0, MKSUE(INT));
+ q = tempnode(0, INT, 0, MKSUE(INT));
+ tmpnr = regno(q);
+ r = buildtree(ASSIGN, q, r);
+ ecomp(r);
+ } else {
+ /* copy directly into temp */
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(q);
+ r = buildtree(ASSIGN, q, p);
+ ecomp(r);
+ }
+
+ /* copy from temp to register parameter */
+ r = tempnode(tmpnr, INT, 0, MKSUE(INT));
+ q = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(q) = (*regp)++;
+ p = buildtree(ASSIGN, q, r);
+
+#endif
+ return p;
+
+}
+
+/* setup call stack with float/double argument */
+/* called from moveargs() */
+static NODE *
+movearg_double(NODE *p, int *fregp, int *regp)
+{
+#if defined(MACHOABI)
+ NODE *q, *r;
+ TWORD ty = INCREF(p->n_type);
+ int tmpnr;
+#endif
+
+ /* this does the move to a single register for us */
+ p = movearg_32bit(p, fregp);
+
+ /*
+ * On OS/X, doubles are passed in the floating-point registers
+ * and in the general registers for compatibily with libraries
+ * compiled to handle soft-float.
+ */
+
+#if defined(MACHOABI)
+
+ if (xtemps) {
+ /* bounce on TOS */
+ r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue);
+ regno(r) = SPREG;
+ r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_sue);
+ r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue);
+ r = buildtree(ASSIGN, r, p);
+ ecomp(r);
+
+ /* bounce into temp */
+ r = block(REG, NIL, NIL, PTR+LONGLONG, 0, MKSUE(LONGLONG));
+ regno(r) = SPREG;
+ r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, MKSUE(LONGLONG));
+ r = block(UMUL, r, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ q = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG));
+ tmpnr = regno(q);
+ r = buildtree(ASSIGN, q, r);
+ ecomp(r);
+ } else {
+ /* copy directly into temp */
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(q);
+ r = buildtree(ASSIGN, q, p);
+ ecomp(r);
+ }
+
+ /* copy from temp to register parameter */
+ r = tempnode(tmpnr, LONGLONG, 0, MKSUE(LONGLONG));
+ q = block(REG, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ regno(q) = R3R4 - R3 + (*regp);
+ p = buildtree(ASSIGN, q, r);
+
+ (*regp) += 2;
+
+#endif
+
+ return p;
+}
+
+/* setup call stack with a structure */
+/* called from moveargs() */
+static NODE *
+movearg_struct(NODE *p, int *regp)
+{
+ int reg = *regp;
+ NODE *l, *q, *t, *r;
+ int tmpnr;
+ int navail;
+ int num;
+ int sz;
+ int ty;
+ int i;
+
+ assert(p->n_op == STARG);
+
+ navail = NARGREGS - (reg - R3);
+ navail = navail < 0 ? 0 : navail;
+ sz = tsize(p->n_type, p->n_df, p->n_sue) / SZINT;
+ num = sz > navail ? navail : sz;
+
+ /* remove STARG node */
+ l = p->n_left;
+ nfree(p);
+ ty = l->n_type;
+
+ /*
+ * put it into a TEMP, rather than tcopy(), since the tree
+ * in p may have side-affects
+ */
+ t = tempnode(0, ty, l->n_df, l->n_sue);
+ tmpnr = regno(t);
+ q = buildtree(ASSIGN, t, l);
+
+ /* copy structure into registers */
+ for (i = 0; i < num; i++) {
+ t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty));
+ t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT));
+ t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT));
+ t = buildtree(UMUL, t, NIL);
+
+ r = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ regno(r) = reg++;
+ r = buildtree(ASSIGN, r, t);
+
+ q = block(CM, q, r, INT, 0, MKSUE(INT));
+ }
+
+ /* put the rest of the structure on the stack */
+ for (i = num; i < sz; i++) {
+ t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty));
+ t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT));
+ t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT));
+ t = buildtree(UMUL, t, NIL);
+ r = pusharg(t, &reg);
+ q = block(CM, q, r, INT, 0, MKSUE(INT));
+ }
+
+ q = reverse(q);
+
+ *regp = reg;
+ return q;
+}
+
+
+static NODE *
+moveargs(NODE *p, int *regp, int *fregp)
+{
+ NODE *r, **rp;
+ int reg, freg;
+
+ if (p->n_op == CM) {
+ p->n_left = moveargs(p->n_left, regp, fregp);
+ r = p->n_right;
+ rp = &p->n_right;
+ } else {
+ r = p;
+ rp = &p;
+ }
+
+ reg = *regp;
+ freg = *fregp;
+
+#define ISFLOAT(p) (p->n_type == FLOAT || \
+ p->n_type == DOUBLE || \
+ p->n_type == LDOUBLE)
+
+ if (reg > R10 && r->n_op != STARG) {
+ *rp = pusharg(r, regp);
+ } else if (r->n_op == STARG) {
+ *rp = movearg_struct(r, regp);
+ } else if (DEUNSIGN(r->n_type) == LONGLONG) {
+ *rp = movearg_64bit(r, regp);
+ } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
+ if (features(FEATURE_HARDFLOAT))
+ *rp = movearg_double(r, fregp, regp);
+ else
+ *rp = movearg_64bit(r, regp);
+ } else if (r->n_type == FLOAT) {
+ if (features(FEATURE_HARDFLOAT))
+ *rp = movearg_float(r, fregp, regp);
+ else
+ *rp = movearg_32bit(r, regp);
+ } else {
+ *rp = movearg_32bit(r, regp);
+ }
+
+ return straighten(p);
+}
+
+/*
+ * Fixup arguments to pass pointer-to-struct as first argument.
+ *
+ * called from funcode().
+ */
+static NODE *
+retstruct(NODE *p)
+{
+ NODE *l, *r, *t, *q;
+ TWORD ty;
+
+ l = p->n_left;
+ r = p->n_right;
+
+ ty = DECREF(l->n_type) - FTN;
+
+// assert(tsize(ty, l->n_df, l->n_sue) == SZINT);
+
+ /* structure assign */
+ q = tempnode(0, ty, l->n_df, l->n_sue);
+ q = buildtree(ADDROF, q, NIL);
+
+ /* insert hidden assignment at beginning of list */
+ if (r->n_op != CM) {
+ p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_sue);
+ } else {
+ for (t = r; t->n_left->n_op == CM; t = t->n_left)
+ ;
+ t->n_left = block(CM, q, t->n_left, INCREF(ty),
+ l->n_df, l->n_sue);
+ }
+
+ return p;
+}
+
+/*
* Called with a function call with arguments as argument.
* This is done early in buildtree() and only done once.
*/
NODE *
funcode(NODE *p)
{
+ int regnum = R3;
+ int fregnum = F1;
+
+ if (p->n_type == STRTY+FTN || p->n_type == UNIONTY+FTN)
+ p = retstruct(p);
+
+ p->n_right = moveargs(p->n_right, &regnum, &fregnum);
+
+ if (p->n_right == NULL)
+ p->n_op += (UCALL - CALL);
+
return p;
}
diff --git a/usr.bin/pcc/powerpc/local.c b/usr.bin/pcc/powerpc/local.c
index 76a90a122a3..d6636d98443 100644
--- a/usr.bin/pcc/powerpc/local.c
+++ b/usr.bin/pcc/powerpc/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.5 2007/12/22 14:05:04 stefan Exp $ */
+/* $OpenBSD: local.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -27,9 +27,12 @@
*/
#include <assert.h>
-
#include "pass1.h"
+#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
+
+#define SNOUNDERSCORE SLOCAL1
+
extern int kflag;
static
@@ -37,103 +40,206 @@ void simmod(NODE *p);
/* this file contains code which is dependent on the target machine */
-/* don't permit CALLs to be arguments to other CALLs (nest CALLs) */
+#if defined(MACHOABI)
+
+/*
+ * Keep track of PIC stubs.
+ */
+
+void
+addstub(struct stub *list, char *name)
+{
+ struct stub *s;
+
+ DLIST_FOREACH(s, list, link) {
+ if (strcmp(s->name, name) == 0)
+ return;
+ }
+
+ if ((s = permalloc(sizeof(struct stub))) == NULL)
+ cerror("addstub: malloc");
+ if ((s->name = strdup(name)) == NULL)
+ cerror("addstub: strdup");
+ DLIST_INSERT_BEFORE(list, s, link);
+}
+
+#endif
+
+
+/*
+ * Make a symtab entry for PIC use.
+ */
+static struct symtab *
+picsymtab(char *p, char *s, char *s2)
+{
+ struct symtab *sp = IALLOC(sizeof(struct symtab));
+ size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
+
+ sp->sname = sp->soname = IALLOC(len);
+ strlcpy(sp->soname, p, len);
+ strlcat(sp->soname, s, len);
+ strlcat(sp->soname, s2, len);
+ sp->sclass = EXTERN;
+ sp->sflags = sp->slevel = 0;
+ return sp;
+}
+
+int gotnr; /* tempnum for GOT register */
+
+/*
+ * Create a reference for an extern variable.
+ */
static NODE *
-emitinnercall(NODE *r)
+picext(NODE *p)
{
- NODE *tmp1, *tmp2;
+ NODE *q;
+ struct symtab *sp;
-#ifdef PCC_DEBUG
- if (xdebug) {
- printf("clocal::emitinnercall():\n");
- fwalk(r, eprint, 0);
+ if (strncmp(p->n_sp->soname, "__builtin", 9) == 0)
+ return p;
+
+#if defined(ELFABI)
+
+ sp = picsymtab("", p->n_sp->soname, "@got(31)");
+ q = xbcon(0, sp, PTR+VOID);
+ q = block(UMUL, q, 0, PTR+VOID, 0, MKSUE(VOID));
+
+#elif defined(MACHOABI)
+
+ char buf2[64];
+ NODE *r;
+
+ if (p->n_sp->sclass == EXTDEF) {
+ snprintf(buf2, 64, "-L%s$pb", cftnsp->soname);
+ sp = picsymtab("", exname(p->n_sp->soname), buf2);
+ } else {
+ snprintf(buf2, 64, "$non_lazy_ptr-L%s$pb", cftnsp->soname);
+ sp = picsymtab("L", p->n_sp->soname, buf2);
+ addstub(&nlplist, p->n_sp->soname);
}
+#if USE_GOTNR
+ q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID));
+#else
+ q = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID));
+ regno(q) = GOTREG;
+#endif
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+
+ if (p->n_sp->sclass != EXTDEF)
+ q = block(UMUL, q, 0, PTR+VOID, 0, MKSUE(VOID));
+
#endif
- tmp1 = tempnode(0, r->n_type, r->n_df, r->n_sue);
- tmp2 = tempnode(tmp1->n_lval, r->n_type, r->n_df, r->n_sue);
- ecode(buildtree(ASSIGN, tmp1, r));
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp; /* for init */
+ nfree(p);
- return tmp2;
+ return q;
}
-
-static void
-breaknestedcalls(NODE *p)
+
+/*
+ * Create a reference for a static variable
+ */
+
+static NODE *
+picstatic(NODE *p)
{
+ NODE *q;
+ struct symtab *sp;
+
+#if defined(ELFABI)
+
+ if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) {
+ char buf[64];
+ snprintf(buf, 64, LABFMT, (int)p->n_sp->soffset);
+ sp = picsymtab("", buf, "@got(31)");
+ sp->sflags |= SNOUNDERSCORE;
+ } else {
+ sp = picsymtab("", p->n_sp->soname, "@got(31)");
+ }
+ sp->sclass = STATIC;
+ sp->stype = p->n_sp->stype;
+ q = xbcon(0, sp, PTR+VOID);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp;
+ nfree(p);
+
+#elif defined(MACHOABI)
+
+ char buf2[64];
NODE *r;
- for (r = p->n_right; r->n_op == CM; r = r->n_left) {
- if (r->n_right->n_op == CALL)
- r->n_right = emitinnercall(r->n_right);
- if (r->n_left->n_op == CALL)
- r->n_left = emitinnercall(r->n_left);
- }
+ snprintf(buf2, 64, "-L%s$pb", cftnsp->soname);
-#ifdef PCC_DEBUG
- if (xdebug) {
- printf("clocal::breaknestedcalls(): exiting with tree:\n");
- fwalk(p, eprint, 0);
+ if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) {
+ char buf1[64];
+ snprintf(buf1, 64, LABFMT, (int)p->n_sp->soffset);
+ sp = picsymtab("", buf1, buf2);
+ sp->sflags |= SNOUNDERSCORE;
+ } else {
+ sp = picsymtab("", exname(p->n_sp->soname), buf2);
}
+ sp->sclass = STATIC;
+ sp->stype = p->n_sp->stype;
+#if USE_GOTNR
+ q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID));
+#else
+ q = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID));
+ regno(q) = GOTREG;
+#endif
+ r = xbcon(0, sp, INT);
+ q = buildtree(PLUS, q, r);
+ q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue);
+ q->n_sp = p->n_sp;
+ nfree(p);
+
#endif
+
+ return q;
}
-static void
-fixupfuncargs(NODE *r, int *reg)
+static NODE *
+convert_ulltof(NODE *p)
{
-#ifdef PCC_DEBUG
- if (xdebug)
- printf("fixupfuncargs(): r=%p\n", r);
-#endif
+ NODE *q, *r, *l, *t;
+ int ty;
+ int tmpnr;
- if (r->n_op == CM) {
- /* recurse to the bottom of the tree */
- fixupfuncargs(r->n_left, reg);
+ ty = p->n_type;
+ l = p->n_left;
+ nfree(p);
- if (r->n_right->n_op == STARG) {
- assert(0);
- }
+ q = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG));
+ tmpnr = regno(q);
+ t = buildtree(ASSIGN, q, l);
+ ecomp(t);
- r->n_right = block(ASSIGN, NIL, r->n_right,
- r->n_right->n_type, r->n_right->n_df,
- r->n_right->n_sue);
- r->n_right->n_left = block(REG, NIL, NIL, r->n_right->n_type, 0, MKSUE(INT));
+ //q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG));
+ //q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ q = tempnode(tmpnr, LONGLONG, 0, MKSUE(LONGLONG));
+ r = block(SCONV, q, NIL, ty, 0, MKSUE(ty));
- if (r->n_right->n_type == ULONGLONG || r->n_right->n_type == LONGLONG) {
- r->n_right->n_left->n_rval = R3R4 + (*reg) - R3;
- (*reg) += 2;
- } else {
- r->n_right->n_left->n_rval = (*reg);
- (*reg)++;
- }
+ q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG));
+ q = block(RS, q, bcon(1), ULONGLONG, 0, MKSUE(ULONGLONG));
+ q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ q = block(SCONV, q, NIL, ty, 0, MKSUE(ty));
+ t = block(FCON, NIL, NIL, ty, 0, MKSUE(ty));
+ t->n_dcon = 2;
+ l = block(MUL, q, t, ty, 0, MKSUE(ty));
- } else {
+ r = buildtree(COLON, l, r);
- if (r->n_op == STARG) {
- assert(0);
-#if 0
- copystructtostack(r->);
- *r = *(r->n_left)
- nfree(r->n_left);
- return;
-#endif
- }
+ q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG));
+ q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG));
+ l = block(LE, q, xbcon(0, NULL, LONGLONG), INT, 0, MKSUE(INT));
+
+ return clocal(buildtree(QUEST, l, r));
- NODE *l = talloc();
- *l = *r;
- r->n_op = ASSIGN;
- r->n_left = block(REG, NIL, NIL, l->n_type, 0, MKSUE(INT));
- r->n_right = l;
- if (r->n_right->n_type == ULONGLONG || r->n_right->n_type == LONGLONG) {
- r->n_left->n_rval = R3R4 + (*reg) - R3;
- (*reg) += 2;
- } else {
- r->n_left->n_rval = (*reg);
- (*reg)++;
- }
- }
}
+
/* clocal() is called to do local transformations on
* an expression tree preparitory to its being
* written out in intermediate code.
@@ -154,6 +260,8 @@ clocal(NODE *p)
int o;
int m;
TWORD t;
+ int isptrvoid = 0;
+ int tmpnr;
#ifdef PCC_DEBUG
if (xdebug) {
@@ -171,48 +279,21 @@ clocal(NODE *p)
}
#endif
- if (kflag && blevel > 0 && p->n_left->n_op == NAME) {
-
-#if 0
- printf("sclass=%d, squal=%d, slevel=%d: ", p->n_left->n_sp->sclass, p->n_left->n_sp->squal, p->n_left->n_sp->slevel);
- tprint(stdout, p->n_left->n_type, p->n_left->n_qual);
- printf("\n");
-#endif
-
- TWORD t = DECREF(p->n_type);
-
- if (!ISFTN(t)) {
-
- int isextern = (p->n_sp && p->n_sp->sclass == EXTERN);
- int off = 0;
-
- if (isextern) {
- off = p->n_lval;
- p->n_lval = 0;
- }
-
- r = talloc();
- *r = *p;
-
- /* cast to pointer-to-char before adding offset */
- l = block(REG, NIL, NIL, INT, p->n_df, p->n_sue);
- l->n_lval = 0;
- l->n_rval = R31;
-
- r = block(SCONV, r, NIL, INCREF(UCHAR), p->n_df,p->n_sue);
- r = block(PLUS, l, r, r->n_type, r->n_df, r->n_sue);
-
- if (off)
- r = block(PLUS, r, bcon(off), r->n_type, r->n_df, r->n_sue);
-
- p->n_op = SCONV;
- p->n_lval = 0;
- p->n_left = r;
- p->n_rval = 0;
- p->n_right = 0;
- }
-
- }
+ if (kflag == 0 || blevel == 0)
+ break;
+ /* char arrays may end up here */
+ l = p->n_left;
+ if (l->n_op != NAME ||
+ (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
+ break;
+ l = p;
+ p = picstatic(p->n_left);
+ nfree(l);
+ if (p->n_op != UMUL)
+ cerror("ADDROF error");
+ l = p;
+ p = p->n_left;
+ nfree(l);
break;
case NAME:
@@ -230,82 +311,74 @@ clocal(NODE *p)
p = stref(block(STREF, r, p, 0, 0, 0));
break;
+ case USTATIC:
+ if (kflag == 0)
+ break;
+ /* FALLTHROUGH */
+
+ case STATIC:
+ if (kflag == 0) {
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ } else if (blevel > 0) {
+ p = picstatic(p);
+ }
+ break;
+
case REGISTER:
p->n_op = REG;
p->n_lval = 0;
p->n_rval = q->soffset;
break;
- case STATIC:
- if (q->slevel > 0) {
- p->n_lval = 0;
- p->n_sp = q;
- }
- /* FALLTHROUGH */
- default:
- if (kflag && blevel > 0 && !ISFTN(p->n_type)) {
- TWORD t = p->n_type;
- int isextern = p->n_sp->sclass == EXTERN;
- int off = 0;
-
- if (isextern)
- t = INCREF(t);
-
- l = block(REG, NIL, NIL, INCREF(t), p->n_df, p->n_sue);
- l->n_lval = 0;
- l->n_rval = R31;
-
- p->n_op = ICON;
- p->n_type = INCREF(t);
- if (isextern) {
- off = p->n_lval;
- p->n_lval = 0;
- }
-
- p = block(PLUS, l, p, INCREF(t), p->n_df, p->n_sue);
+ case EXTERN:
+ case EXTDEF:
+ if (kflag == 0)
+ break;
+ if (blevel > 0)
+ p = picext(p);
+ break;
- if (isextern) {
- p = block(UMUL, p, NIL, t, p->n_df, p->n_sue);
- if (off)
- p = block(PLUS, p, bcon(off), t, p->n_df, p->n_sue);
- t = DECREF(t);
- }
- p = block(UMUL, p, NIL, t, p->n_df, p->n_sue);
- }
+ case ILABEL:
+ if (kflag && blevel > 0)
+ p = picstatic(p);
+ break;
}
break;
- case STCALL:
- case CALL:
-
- breaknestedcalls(p);
-
- /* Fix function call arguments. */
- /* move everything into the registers */
- {
- int reg = R3;
- fixupfuncargs(p->n_right, &reg);
- }
- /* FALLTHOUGH */
-
-#if 0
case UCALL:
-
- /* check if it's an indirect call and offset with R30 */
- if (p->n_left->n_op == REG) {
- l = block(REG, NIL, NIL, INT, p->n_df, MKSUE(INT));
- l->n_lval = 0;
- l->n_rval = R31;
- p->n_left = block(PLUS, p->n_left, l, p->n_type, p->n_df, p->n_sue);
- }
-#endif
-
-#if 0
- r = tempnode(0, p->n_type, p->n_df, p->n_sue);
- ecomp(buildtree(ASSIGN, r, p));
- return r;
+ case CALL:
+ case USTCALL:
+ case STCALL:
+ if (p->n_type == VOID)
+ break;
+ /*
+ * if the function returns void*, ecode() invokes
+ * delvoid() to convert it to uchar*.
+ * We just let this happen on the ASSIGN to the temp,
+ * and cast the pointer back to void* on access
+ * from the temp.
+ */
+ if (p->n_type == PTR+VOID)
+ isptrvoid = 1;
+ r = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(r);
+ r = buildtree(ASSIGN, r, p);
+
+ p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue);
+ if (isptrvoid) {
+ p = block(PCONV, p, NIL, PTR+VOID,
+ p->n_df, MKSUE(PTR+VOID));
+ }
+#if 1
+ p = buildtree(COMOP, r, p);
+#else
+ /* XXX this doesn't work if the call is already in a COMOP */
+ r = clocal(r);
+ ecomp(r);
#endif
- break;
+ break;
case CBRANCH:
l = p->n_left;
@@ -337,8 +410,7 @@ clocal(NODE *p)
l->n_lval = (unsigned)l->n_lval;
goto delp;
}
- if (l->n_type < INT || l->n_type == LONGLONG ||
- l->n_type == ULONGLONG) {
+ if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) {
/* float etc? */
p->n_left = block(SCONV, l, NIL,
UNSIGNED, 0, MKSUE(UNSIGNED));
@@ -373,9 +445,6 @@ clocal(NODE *p)
return l;
}
- if (xdebug)
- printf("SCONV 1\n");
-
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 &&
@@ -397,6 +466,15 @@ clocal(NODE *p)
return l;
}
+ /*
+ * if converting ULONGLONG to FLOAT/(L)DOUBLE,
+ * replace ___floatunsdidf() with ___floatdidf()
+ */
+ if (l->n_type == ULONGLONG && p->n_type >= FLOAT &&
+ p->n_type <= LDOUBLE) {
+ return convert_ulltof(p);
+ }
+
o = l->n_op;
m = p->n_type;
@@ -449,20 +527,36 @@ clocal(NODE *p)
l->n_sue = MKSUE(m);
nfree(p);
return l;
+ } else if (o == FCON) {
+ l->n_lval = l->n_dcon;
+ l->n_sp = NULL;
+ l->n_op = ICON;
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return clocal(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) &&
+ if ((DEUNSIGN(p->n_type) == CHAR ||
+ DEUNSIGN(p->n_type) == SHORT) &&
(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;
}
+ if ((DEUNSIGN(l->n_type) == CHAR ||
+ DEUNSIGN(l->n_type) == SHORT) &&
+ (p->n_type == FLOAT || p->n_type == DOUBLE ||
+ p->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:
@@ -485,6 +579,16 @@ clocal(NODE *p)
nfree(p);
return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
+ case STNAME:
+ if ((q = p->n_sp) == NULL)
+ return p;
+ if (q->sclass != STNAME)
+ return p;
+ t = p->n_type;
+ p = block(ADDROF, p, NIL, INCREF(t), p->n_df, p->n_sue);
+ p = block(UMUL, p, NIL, t, p->n_df, p->n_sue);
+ break;
+
case FORCE:
/* put return value in return reg */
p->n_op = ASSIGN;
@@ -496,16 +600,14 @@ clocal(NODE *p)
case LS:
case RS:
- /* 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));
- }
+ if (DEUNSIGN(p->n_right->n_type) == INT)
+ break;
+ p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
break;
}
+
#ifdef PCC_DEBUG
if (xdebug) {
printf("clocal end: %p\n", p);
@@ -515,9 +617,114 @@ clocal(NODE *p)
return(p);
}
+/*
+ * Change CALL references to either direct (static) or PLT.
+ */
+static void
+fixnames(NODE *p)
+{
+ struct symtab *sp;
+ struct suedef *sue;
+ NODE *q;
+ char *c;
+ int isu;
+
+ if ((cdope(p->n_op) & CALLFLG) == 0)
+ return;
+
+ isu = 0;
+ q = p->n_left;
+ sue = q->n_sue;
+ if (q->n_op == UMUL)
+ q = q->n_left, isu = 1;
+
+#if defined(ELFABI)
+
+ if (q->n_op == ICON) {
+ sp = q->n_sp;
+
+#elif defined(MACHOABI)
+
+#ifdef USE_GOTNR
+ if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
+#else
+ if (q->n_op == PLUS && q->n_left->n_op == REG &&
+#endif
+ q->n_right->n_op == ICON) {
+ sp = q->n_right->n_sp;
+#endif
+
+ if (sp == NULL)
+ return; /* nothing to do */
+ if (sp->sclass == STATIC && !ISFTN(sp->stype))
+ return; /* function pointer */
+
+ if (sp->sclass != STATIC && sp->sclass != EXTERN &&
+ sp->sclass != EXTDEF)
+ cerror("fixnames");
+
+#if defined(ELFABI)
+
+ if ((c = strstr(sp->soname, "@got(31)")) == NULL)
+ cerror("fixnames2");
+ if (isu) {
+ strcpy(c, "@plt");
+ } else
+ *c = 0;
+
+#elif defined(MACHOABI)
+
+ if ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL &&
+ (c = strstr(sp->soname, "-L")) == NULL)
+ cerror("fixnames2");
+ if (isu) {
+ *c = 0;
+ addstub(&stublist, sp->soname+1);
+ strcpy(c, "$stub");
+ } else
+ *c = 0;
+
+ nfree(q->n_left);
+ q = q->n_right;
+ if (isu)
+ nfree(p->n_left->n_left);
+ nfree(p->n_left);
+ p->n_left = q;
+ q->n_sue = sue;
+
+#endif
+ }
+}
+
void
myp2tree(NODE *p)
{
+ int o = p->n_op;
+ struct symtab *sp;
+
+ if (kflag)
+ walkf(p, fixnames);
+ if (o != FCON)
+ return;
+
+ /* Write float constants to memory */
+ /* Should be voluntary per architecture */
+
+ sp = IALLOC(sizeof(struct symtab));
+ sp->sclass = STATIC;
+ sp->ssue = MKSUE(p->n_type);
+ sp->slevel = 1; /* fake numeric label */
+ sp->soffset = getlab();
+ sp->sflags = 0;
+ sp->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, sp->ssue->suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
}
/*ARGSUSED*/
@@ -546,8 +753,6 @@ cendarg()
int
cisreg(TWORD t)
{
- if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
- return 0; /* not yet */
return 1;
}
@@ -556,8 +761,6 @@ cisreg(TWORD t)
* 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.
*/
@@ -578,71 +781,85 @@ offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
}
/*
- * 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.
+ * Allocate bits on the stack.
+ * 'off' is the number of bits to allocate
+ * '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)
{
-#if 0
- NODE *sp;
-#endif
-
- p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
-
- assert(0);
-#if 0
- /* 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! */
-#endif
-
-}
-
-#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");
- }
+ NODE *q, *r;
+ int nbytes = off / SZCHAR;
+ int stacksize = 24+40; /* this should be p2stacksize */
+
+ /*
+ * After we subtract the requisite bytes
+ * off the stack, we need to step back over
+ * the 40 bytes for the arguments registers
+ * *and* any other parameters which will get
+ * saved to the stack. Unfortunately, we
+ * don't have that information in pass1 and
+ * the parameters will stomp on the allocated
+ * space for alloca().
+ *
+ * No fix yet.
+ */
+ werror("parameters may stomp on alloca()");
+
+ /* compute size */
+ p = buildtree(MUL, p, bcon(nbytes));
+ p = buildtree(PLUS, p, bcon(ALSTACK/SZCHAR));
+
+ /* load the top-of-stack */
+ q = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT));
+ regno(q) = SPREG;
+ q = block(UMUL, q, NIL, INT, 0, MKSUE(INT));
+
+ /* save old top-of-stack value to new top-of-stack position */
+ r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT));
+ regno(r) = SPREG;
+ r = block(MINUSEQ, r, p, INT, 0, MKSUE(INT));
+ r = block(UMUL, r, NIL, INT, 0, MKSUE(INT));
+ ecomp(buildtree(ASSIGN, r, q));
+
+ r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT));
+ regno(r) = SPREG;
+
+ /* skip over the arguments space and align to 16 bytes */
+ r = block(PLUS, r, bcon(stacksize + 15), INT, 0, MKSUE(INT));
+ r = block(RS, r, bcon(4), INT, 0, MKSUE(INT));
+ r = block(LS, r, bcon(4), INT, 0, MKSUE(INT));
+
+ t->n_type = p->n_type;
+ ecomp(buildtree(ASSIGN, t, r));
}
-#endif
-#if 0
/*
* Print out a string of characters.
- * Assume that the assembler understands C-style escape
- * sequences. Location is already set.
+ * Unfortunately, this code assumes that the assembler understands
+ * C-style escape sequences. (which it doesn't!)
+ * Location is already set.
*/
void
-instring(char *str)
+instring(struct symtab *sp)
{
- char *s;
+ char *s, *str = sp->sname;
+
+#if defined(ELFABI)
+
+ defloc(sp);
+
+#elif defined(MACHOABI)
+
+ extern int lastloc;
+ if (lastloc != STRNG)
+ printf(" .cstring\n");
+ lastloc = STRNG;
+ printf(" .p2align 1\n");
+ printf(LABFMT ":\n", sp->soffset);
+
+#endif
/* be kind to assemblers and avoid long strings */
printf("\t.ascii \"");
@@ -659,7 +876,27 @@ instring(char *str)
fwrite(str, 1, s - str, stdout);
printf("\\0\"\n");
}
-#endif
+
+/*
+ * Print out a wide string by calling ninval().
+ */
+void
+inwstring(struct symtab *sp)
+{
+ char *s = sp->sname;
+ NODE *p;
+
+ defloc(sp);
+ p = bcon(0);
+ do {
+ if (*s++ == '\\')
+ p->n_lval = esccon(&s);
+ else
+ p->n_lval = (unsigned char)s[-1];
+ ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p);
+ } while (s[-1] != 0);
+ nfree(p);
+}
static int inbits, inval;
@@ -673,6 +910,9 @@ zbits(OFFSZ off, int fsz)
if (idebug)
printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
+
+#if 0
+ /* little-endian */
if ((m = (inbits % SZCHAR))) {
m = SZCHAR - m;
if (fsz < m) {
@@ -684,6 +924,20 @@ zbits(OFFSZ off, int fsz)
inval = inbits = 0;
}
}
+#endif
+ /* big-endian */
+ if (inbits) {
+ m = SZCHAR - inbits;
+ if (fsz < m) {
+ inbits += fsz;
+ inval <<= fsz;
+ } else {
+ printf("\t.byte %d\n", inval << m);
+ fsz -= m;
+ inval = inbits = 0;
+ }
+ }
+
if (fsz >= SZCHAR) {
printf("\t.space %d\n", fsz/SZCHAR);
fsz -= (fsz/SZCHAR) * SZCHAR;
@@ -703,7 +957,11 @@ 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;
+
+#if 0
+ /* little-endian */
while (fsz + inbits >= SZCHAR) {
inval |= (val << inbits);
printf("\t.byte %d\n", inval & 255);
@@ -715,6 +973,17 @@ infld(CONSZ off, int fsz, CONSZ val)
inval |= (val << inbits);
inbits += fsz;
}
+#endif
+
+ /* big-endian */
+ inval <<= fsz;
+ inval |= val;
+ inbits += fsz;
+ while (inbits >= SZCHAR) {
+ int pval = inval >> (inbits - SZCHAR);
+ printf("\t.byte %d\n", pval & 255);
+ inbits -= SZCHAR;
+ }
}
/*
@@ -728,6 +997,7 @@ ninval(CONSZ off, int fsz, NODE *p)
{
union { float f; double d; long double l; int i[3]; } u;
struct symtab *q;
+ char *c;
TWORD t;
int i;
@@ -735,8 +1005,39 @@ ninval(CONSZ off, int fsz, NODE *p)
if (t > BTMASK)
t = INT; /* pointer */
+ while (p->n_op == SCONV || p->n_op == PCONV) {
+ NODE *l = p->n_left;
+ l->n_type = p->n_type;
+ p = l;
+ }
+
+ if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) {
+ if (p->n_op == UMUL)
+ p = p->n_left;
+ p = p->n_right;
+ q = p->n_sp;
+
+#if defined(ELFABI)
+
+ if ((c = strstr(q->soname, "@got(31)")) != NULL)
+ *c = 0; /* ignore GOT ref here */
+
+#elif defined(MACHOABI)
+
+ if ((c = strstr(q->soname, "$non_lazy_ptr")) != NULL) {
+ q->soname++; /* skip "L" */
+ *c = 0; /* ignore GOT ref here */
+ }
+ else if ((c = strstr(q->soname, "-L")) != NULL)
+ *c = 0; /* ignore GOT ref here */
+
+#endif
+
+ }
+
if (p->n_op != ICON && p->n_op != FCON)
- cerror("ninval: init node not constant");
+ cerror("ninval: init node not constant: node %p [%s]",
+ p, cftnsp->soname);
if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
uerror("element not constant");
@@ -744,28 +1045,46 @@ ninval(CONSZ off, int fsz, NODE *p)
switch (t) {
case LONGLONG:
case ULONGLONG:
+#if 0
+ /* little-endian */
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);
+#endif
+ /* big-endian */
+ i = (p->n_lval & 0xffffffff);
+ p->n_lval >>= 32;
+ 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);
+ printf("\t.long %d", (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));
+ } else {
+
+#if defined(MACHOABI)
+ if ((q->sflags & SNOUNDERSCORE) != 0)
+ printf("+%s", q->soname);
+ else
+#endif
+ printf("+%s", exname(q->soname));
+ }
}
printf("\n");
break;
case SHORT:
case USHORT:
- printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
+ printf("\t.short %d\n", (int)p->n_lval & 0xffff);
break;
case BOOL:
if (p->n_lval > 1)
@@ -778,62 +1097,36 @@ ninval(CONSZ off, int fsz, NODE *p)
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]);
+#if 0
+ /* little-endian */
+ printf("\t.long 0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+#endif
+ /* big-endian */
+ printf("\t.long 0x%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]);
+ printf("\t.long 0x%x\n\t.long 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]);
+ printf("\t.long 0x%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)
{
-#ifndef ELFABI
+#if defined(ELFABI)
+
+ return (p == NULL ? "" : p);
+
+#elif defined(MACHOABI)
+
#define NCHNAM 256
static char text[NCHNAM+1];
int i;
@@ -849,8 +1142,7 @@ exname(char *p)
text[NCHNAM] = '\0'; /* truncate */
return (text);
-#else
- return (p == NULL ? "" : p);
+
#endif
}
@@ -892,17 +1184,30 @@ extdec(struct symtab *q)
/* make a common declaration for id, if reasonable */
void
+defzero(struct symtab *sp)
+{
+ int off;
+
+ off = tsize(sp->stype, sp->sdf, sp->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ printf("\t.%scomm ", sp->sclass == STATIC ? "l" : "");
+ if (sp->slevel == 0)
+ printf("%s,%d\n", exname(sp->soname), off);
+ else
+ printf(LABFMT ",%d\n", sp->soffset, off);
+}
+
+
+#ifdef notdef
+/* 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", exname(gcc_findname(q)), off);
-#else
- printf(" .comm %s,0%o\n", exname(q->sname), off);
-#endif
+ printf("\t.comm %s,0%o\n", exname(q->soname), off);
}
/* make a local common declaration for id, if reasonable */
@@ -914,13 +1219,9 @@ lcommdec(struct symtab *q)
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", exname(gcc_findname(q)), off);
-#else
- printf(" .lcomm %s,0%o\n", exname(q->sname), off);
-#endif
+ printf("\t.lcomm %s,%d\n", exname(q->soname), off);
else
- printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+ printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off);
}
/*
@@ -932,11 +1233,15 @@ deflab1(int label)
printf(LABFMT ":\n", label);
}
-#ifdef ELFABI
+#if defined(ELFABI)
+
static char *loctbl[] = { "text", "data", "section .rodata,",
"section .rodata" };
-#else
+
+#elif defined(MACHOABI)
+
static char *loctbl[] = { "text", "data", "section .rodata,", "cstring" };
+
#endif
void
@@ -952,36 +1257,6 @@ setloc1(int locc)
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
/* simulate and optimise the MOD opcode */
@@ -1004,5 +1279,178 @@ simmod(NODE *p)
#undef ISPOW2
/* other optimizations can go here */
-
+}
+
+/*
+ * Give target the opportunity of handling pragmas.
+ */
+int
+mypragma(char **ary)
+{
+ return 0;
+}
+
+/*
+ * Called when a identifier has been declared, to give target last word.
+ */
+void
+fixdef(struct symtab *sp)
+{
+}
+
+/*
+ * There is very little different here to the standard builtins.
+ * It basically handles promotion of types smaller than INT.
+ */
+
+NODE *
+powerpc_builtin_stdarg_start(NODE *f, NODE *a)
+{
+ NODE *p, *q;
+ int sz = 1;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type))
+ goto bad;
+
+ /* must first deal with argument size; use int size */
+ p = a->n_right;
+ if (p->n_type < INT) {
+ /* round up to word */
+ sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue);
+ }
+
+ p = buildtree(ADDROF, p, NIL); /* address of last arg */
+ p = optim(buildtree(PLUS, p, bcon(sz)));
+ q = block(NAME, NIL, NIL, PTR+VOID, 0, 0);
+ q = buildtree(CAST, q, p);
+ p = q->n_right;
+ nfree(q->n_left);
+ nfree(q);
+ p = buildtree(ASSIGN, a->n_left, p);
+ tfree(f);
+ nfree(a);
+
+ return p;
+
+bad:
+ uerror("bad argument to __builtin_stdarg_start");
+ return bcon(0);
+}
+
+NODE *
+powerpc_builtin_va_arg(NODE *f, NODE *a)
+{
+ NODE *p, *q, *r;
+ int sz, tmpnr;
+
+ /* check num args and type */
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
+ !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
+ goto bad;
+
+ r = a->n_right;
+
+ /* get type size */
+ sz = tsize(r->n_type, r->n_df, r->n_sue) / SZCHAR;
+ if (sz < SZINT/SZCHAR) {
+ werror("%s%s promoted to int when passed through ...",
+ ISUNSIGNED(r->n_type) ? "unsigned " : "",
+ DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
+ sz = SZINT/SZCHAR;
+ r->n_type = INT;
+ r->n_sue = MKSUE(INT);
+ }
+
+ p = tcopy(a->n_left);
+
+#if defined(ELFABI)
+
+ /* alignment */
+ if (SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
+ p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1));
+ p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_sue);
+ }
+
+#endif
+
+ /* create a copy to a temp node */
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tmpnr = regno(q);
+ p = buildtree(ASSIGN, q, p);
+
+ q = tempnode(tmpnr, p->n_type, p->n_df, p->n_sue);
+ q = buildtree(PLUS, q, bcon(sz));
+ q = buildtree(ASSIGN, a->n_left, q);
+
+ q = buildtree(COMOP, p, q);
+
+ nfree(a->n_right);
+ nfree(a);
+ nfree(f);
+
+ p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_sue);
+ p = buildtree(UMUL, p, NIL);
+ p = buildtree(COMOP, q, p);
+
+ return p;
+
+bad:
+ uerror("bad argument to __builtin_va_arg");
+ return bcon(0);
+}
+
+NODE *
+powerpc_builtin_va_end(NODE *f, NODE *a)
+{
+ tfree(f);
+ tfree(a);
+
+ return bcon(0);
+}
+
+NODE *
+powerpc_builtin_va_copy(NODE *f, NODE *a)
+{
+ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
+ goto bad;
+ tfree(f);
+ f = buildtree(ASSIGN, a->n_left, a->n_right);
+ nfree(a);
+ return f;
+
+bad:
+ uerror("bad argument to __buildtin_va_copy");
+ return bcon(0);
+}
+
+NODE *
+powerpc_builtin_return_address(NODE *f, NODE *a)
+{
+ int nframes;
+ int i = 0;
+
+ if (a == NULL || a->n_op != ICON)
+ goto bad;
+
+ nframes = a->n_lval;
+
+ tfree(f);
+ tfree(a);
+
+ f = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(PTR+VOID));
+ regno(f) = SPREG;
+
+ do {
+ f = buildtree(UMUL, f, NIL);
+ } while (i++ < nframes);
+
+ f = block(PLUS, f, bcon(8), INCREF(PTR+VOID), 0, MKSUE(VOID));
+ f = buildtree(UMUL, f, NIL);
+
+ return f;
+bad:
+ uerror("bad argument to __builtin_return_address");
+ return bcon(0);
}
diff --git a/usr.bin/pcc/powerpc/local2.c b/usr.bin/pcc/powerpc/local2.c
index 982db78eaf6..a2428ea536e 100644
--- a/usr.bin/pcc/powerpc/local2.c
+++ b/usr.bin/pcc/powerpc/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.6 2007/12/22 22:56:31 stefan Exp $ */
+/* $OpenBSD: local2.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -34,29 +34,54 @@
#include <string.h>
#include <stdlib.h>
-int argsize(NODE *p);
+#define LOWREG 0
+#define HIREG 1
-static int stkpos;
-
-extern struct stub stublist;
-extern struct stub nlplist;
+char *rnames[] = {
+ REGPREFIX "r0", REGPREFIX "r1",
+ REGPREFIX "r2", REGPREFIX "r3",
+ REGPREFIX "r4", REGPREFIX "r5",
+ REGPREFIX "r6", REGPREFIX "r7",
+ REGPREFIX "r8", REGPREFIX "r9",
+ REGPREFIX "r10", REGPREFIX "r11",
+ REGPREFIX "r12", REGPREFIX "r13",
+ REGPREFIX "r14", REGPREFIX "r15",
+ REGPREFIX "r16", REGPREFIX "r17",
+ REGPREFIX "r18", REGPREFIX "r19",
+ REGPREFIX "r20", REGPREFIX "r21",
+ REGPREFIX "r22", REGPREFIX "r23",
+ REGPREFIX "r24", REGPREFIX "r25",
+ REGPREFIX "r26", REGPREFIX "r27",
+ REGPREFIX "r28", REGPREFIX "r29",
+ REGPREFIX "r30", REGPREFIX "r31",
+ "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0",
+ "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16",
+ "r19r18", "r21r20", "r23r22", "r25r24", "r27r26",
+ "r29r28", "r31r30",
+ REGPREFIX "f0", REGPREFIX "f1",
+ REGPREFIX "f2", REGPREFIX "f3",
+ REGPREFIX "f4", REGPREFIX "f5",
+ REGPREFIX "f6", REGPREFIX "f7",
+ REGPREFIX "f8", REGPREFIX "f9",
+ REGPREFIX "f10", REGPREFIX "f11",
+ REGPREFIX "f12", REGPREFIX "f13",
+ REGPREFIX "f14", REGPREFIX "f15",
+ REGPREFIX "f16", REGPREFIX "f17",
+ REGPREFIX "f18", REGPREFIX "f19",
+ REGPREFIX "f20", REGPREFIX "f21",
+ REGPREFIX "f22", REGPREFIX "f23",
+ REGPREFIX "f24", REGPREFIX "f25",
+ REGPREFIX "f26", REGPREFIX "f27",
+ REGPREFIX "f28", REGPREFIX "f29",
+ REGPREFIX "f30", REGPREFIX "f31",
+};
-static void
-addstub(struct stub *list, char *name)
-{
- struct stub *s;
+static int argsize(NODE *p);
- DLIST_FOREACH(s, list, link) {
- if (strcmp(s->name, name) == 0)
- return;
- }
-
- if ((s = malloc(sizeof(struct stub))) == NULL)
- cerror("addstub: malloc");
- if ((s->name = strdup(name)) == NULL)
- cerror("addstub: strdup");
- DLIST_INSERT_BEFORE(list, s, link);
-}
+static int p2calls;
+static int p2temps; /* TEMPs which aren't autos yet */
+static int p2framesize;
+static int p2maxstacksize;
void
deflab(int label)
@@ -64,89 +89,11 @@ deflab(int label)
printf(LABFMT ":\n", label);
}
-static int regoff[7];
static TWORD ftype;
-static char *funcname = NULL;
/*
* Print out the prolog assembler.
- * addto and regoff are already calculated.
*/
-static void
-prtprolog(struct interpass_prolog *ipp, int addto)
-{
-#if 1
- int i, j;
-#endif
- addto = FIXEDSTACKSIZE;
-
- // get return address (not required for leaf function)
- printf(" mflr %s\n", rnames[R0]);
- // save registers R30 and R31
- printf(" stmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
- // save return address (not required for leaf function)
- printf(" stw %s,8(%s)\n", rnames[R0], rnames[R1]);
- // create the new stack frame
- printf(" stwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]);
-
- if (kflag) {
- funcname = ipp->ipp_name;
- printf(" bcl 20,31,L%s$pb\n", exname(ipp->ipp_name));
- printf("L%s$pb:\n", exname(ipp->ipp_name));
- printf(" mflr %s\n", rnames[R31]);
- }
-
-#ifdef PCC_DEBUG
- if (x2debug) {
- printf("ipp_regs = 0x%x\n", ipp->ipp_regs);
- }
-#endif
-
- for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) {
- if (i & 1) {
- printf(" stw %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;
-
-#ifdef PCC_DEBUG
- if (x2debug)
- printf("offcalc: p2maxautooff=%d\n", p2maxautooff);
-#endif
-
- addto = p2maxautooff;
-
- // space is always allocated on the stack to save the registers
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1) {
- addto += SZINT/SZCHAR;
- regoff[j] = addto;
- }
- }
-
- addto += 8; /* for R31 and R30 */
-
- /* round to 16-byte boundary */
- addto += 15;
- addto &= ~15;
-
-#ifdef PCC_DEBUG
- if (x2debug)
- printf("offcalc: addto=%d\n", addto);
-#endif
-
- return addto;
-}
-
void
prologue(struct interpass_prolog *ipp)
{
@@ -167,22 +114,47 @@ prologue(struct interpass_prolog *ipp)
#endif
ftype = ipp->ipp_type;
- if (ipp->ipp_vis)
- printf(" .globl %s\n", exname(ipp->ipp_name));
- printf(" .align 2\n");
- printf("%s:\n", exname(ipp->ipp_name));
- /*
- * We here know what register to save and how much to
- * add to the stack.
- */
- addto = offcalc(ipp);
- prtprolog(ipp, addto);
+
+ addto = p2framesize;
+
+ if (p2calls != 0 || kflag) {
+ // get return address (not required for leaf function)
+ printf("\tmflr %s\n", rnames[R0]);
+ printf("\tstw %s,8(%s)\n", rnames[R0], rnames[R1]);
+ }
+ // save registers R30 and R31
+ printf("\tstmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
+#ifdef FPREG
+ printf("\tmr %s,%s\n", rnames[FPREG], rnames[R1]);
+#endif
+ // create the new stack frame
+ if (addto > 65535) {
+ printf("\tlis %s,%d\n", rnames[R0], (-addto) >> 16);
+ printf("\tori %s,%s,%d\n", rnames[R0],
+ rnames[R0], (-addto) & 0xffff);
+ printf("\tstwux %s,%s,%s\n", rnames[R1],
+ rnames[R1], rnames[R0]);
+ } else {
+ printf("\tstwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]);
+ }
+
+ if (kflag) {
+#if defined(ELFABI)
+ printf("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n");
+ printf("\tmflr %s\n", rnames[GOTREG]);
+#elif defined(MACHOABI)
+ printf("\tbcl 20,31,L%s$pb\n", ipp->ipp_name);
+ printf("L%s$pb:\n", ipp->ipp_name);
+ printf("\tmflr %s\n", rnames[GOTREG]);
+#endif
+ }
+
}
+
void
eoftn(struct interpass_prolog *ipp)
{
- int i, j;
#ifdef PCC_DEBUG
if (x2debug)
@@ -192,30 +164,18 @@ eoftn(struct interpass_prolog *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)
- printf("\tlwz %s,%d(%s)\n",
- rnames[j], regoff[j], rnames[FPREG]);
-
- }
-
-// assert(ftype != ipp->ipp_type);
-
/* struct return needs special treatment */
- if (ftype == STRTY || ftype == UNIONTY) {
- assert(0);
- printf(" movl 8(%%ebp),%%eax\n");
- printf(" leave\n");
- printf(" ret $4\n");
- } else {
- // unwind stack frame
- printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]);
+ if (ftype == STRTY || ftype == UNIONTY)
+ cerror("eoftn");
+
+ /* unwind stack frame */
+ printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]);
+ if (p2calls != 0 || kflag) {
printf("\tlwz %s,8(%s)\n", rnames[R0], rnames[R1]);
printf("\tmtlr %s\n", rnames[R0]);
- printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
- printf("\tblr\n");
}
+ printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]);
+ printf("\tblr\n");
}
/*
@@ -324,305 +284,556 @@ twollcomp(NODE *p)
}
if (p->n_op >= ULE)
cb1 += 4, cb2 += 4;
- expand(p, 0, "\tcmplw UR,UL # compare 64-bit values (upper)\n");
+ if (p->n_op >= ULE)
+ expand(p, 0, "\tcmplw UL,UR" COM "compare 64-bit values (upper)\n");
+ else
+ expand(p, 0, "\tcmpw UL,UR" COM "compare 64-bit values (upper)\n");
if (cb1) cbgen(cb1, s);
if (cb2) cbgen(cb2, e);
- expand(p, 0, "\tcmplw AR,AL # (and lower)\n");
+ if (p->n_op >= ULE)
+ expand(p, 0, "\tcmplw AL,AR" COM "(and lower)\n");
+ else
+ expand(p, 0, "\tcmpw AL,AR" COM "(and lower)\n");
cbgen(p->n_op, e);
deflab(s);
}
-#if 0
+static void
+shiftop(NODE *p)
+{
+ NODE *r = p->n_right;
+ TWORD ty = p->n_type;
+
+ if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) {
+ expand(p, INBREG, "\tsrwi A1,AL,32-AR" COM "64-bit left-shift\n");
+ expand(p, INBREG, "\tslwi U1,UL,AR\n");
+ expand(p, INBREG, "\tor U1,U1,A1\n");
+ expand(p, INBREG, "\tslwi A1,AL,AR\n");
+ } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) {
+ expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n");
+ if (r->n_lval == 32)
+ expand(p, INBREG, "\tmr U1,AL\n");
+ else
+ expand(p, INBREG, "\tslwi U1,AL,AR-32\n");
+ } else if (p->n_op == LS && r->n_op == ICON) {
+ expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n");
+ expand(p, INBREG, "\tli U1,0\n");
+ } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) {
+ expand(p, INBREG, "\tslwi U1,UL,32-AR" COM "64-bit right-shift\n");
+ expand(p, INBREG, "\tsrwi A1,AL,AR\n");
+ expand(p, INBREG, "\tor A1,A1,U1\n");
+ if (ty == LONGLONG)
+ expand(p, INBREG, "\tsrawi U1,UL,AR\n");
+ else
+ expand(p, INBREG, "\tsrwi U1,UL,AR\n");
+ } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) {
+ if (ty == LONGLONG)
+ expand(p, INBREG, "\tli U1,-1" COM "64-bit right-shift\n");
+ else
+ expand(p, INBREG, "\tli U1,0" COM "64-bit right-shift\n");
+ if (r->n_lval == 32)
+ expand(p, INBREG, "\tmr A1,UL\n");
+ else if (ty == LONGLONG)
+ expand(p, INBREG, "\tsrawi A1,UL,AR-32\n");
+ else
+ expand(p, INBREG, "\tsrwi A1,UL,AR-32\n");
+ } else if (p->n_op == RS && r->n_op == ICON) {
+ expand(p, INBREG, "\tli A1,0" COM "64-bit right-shift\n");
+ expand(p, INBREG, "\tli U1,0\n");
+ }
+}
+
/*
- * Assign to a bitfield.
- * Clumsy at least, but what to do?
+ * Structure assignment.
*/
static void
-bfasg(NODE *p)
+stasg(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");
+ /* R3 = dest, R4 = src, R5 = len */
+ printf("\tli %s,%d\n", rnames[R5], p->n_stsize);
+ if (p->n_left->n_op == OREG) {
+ printf("\taddi %s,%s," CONFMT "\n",
+ rnames[R3], rnames[regno(p->n_left)],
+ p->n_left->n_lval);
+ } else if (p->n_left->n_op == NAME) {
+#if defined(ELFABI)
+ printf("\tli %s,", rnames[R3]);
+ adrput(stdout, p->n_left);
+ printf("@ha\n");
+ printf("\taddi %s,%s,", rnames[R3], rnames[R3]);
+ adrput(stdout, p->n_left);
+ printf("@l\n");
+#elif defined(MACHOABI)
+ printf("\tli %s,ha16(", rnames[R3]);
+ adrput(stdout, p->n_left);
+ printf(")\n");
+ printf("\taddi %s,%s,lo16(", rnames[R3], rnames[R3]);
+ adrput(stdout, p->n_left);
+ printf(")\n");
+#endif
+ }
+ if (kflag) {
+#if defined(ELFABI)
+ printf("\tbl %s@got(30)\n", exname("memcpy"));
+#elif defined(MACHOABI)
+ printf("\tbl L%s$stub\n", "memcpy");
+ addstub(&stublist, "memcpy");
+#endif
+ } else {
+ printf("\tbl %s\n", exname("memcpy"));
}
+}
- /* 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");
+static void
+fpemul(NODE *p)
+{
+ NODE *l = p->n_left;
+ char *ch = NULL;
+
+ if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3";
+ else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3";
+ else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3";
+
+ else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3";
+ else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3";
+ else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3";
+
+ else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3";
+ else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3";
+ else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3";
+
+ else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3";
+ else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3";
+ else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3";
+
+ else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2";
+ else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2";
+ else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2";
+
+ else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2";
+ else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2";
+ else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2";
+
+ else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2";
+ else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2";
+ else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2";
+
+ else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2";
+ else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2";
+ else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2";
+
+ else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2";
+ else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2";
+ else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2";
+
+ else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2";
+ else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2";
+ else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2";
+
+ else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2";
+ else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2";
+ else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2";
+
+ else if (p->n_op == SCONV && p->n_type == FLOAT) {
+ if (l->n_type == DOUBLE) ch = "truncdfsf2";
+ else if (l->n_type == LDOUBLE) ch = "truncdfsf2";
+ else if (l->n_type == ULONGLONG) ch = "floatunsdisf";
+ else if (l->n_type == LONGLONG) ch = "floatdisf";
+ else if (l->n_type == LONG) ch = "floatsisf";
+ else if (l->n_type == ULONG) ch = "floatunsisf";
+ else if (l->n_type == INT) ch = "floatsisf";
+ else if (l->n_type == UNSIGNED) ch = "floatunsisf";
+ } else if (p->n_op == SCONV && p->n_type == DOUBLE) {
+ if (l->n_type == FLOAT) ch = "extendsfdf2";
+ else if (l->n_type == LDOUBLE) ch = "truncdfdf2";
+ else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
+ else if (l->n_type == LONGLONG) ch = "floatdidf";
+ else if (l->n_type == LONG) ch = "floatsidf";
+ else if (l->n_type == ULONG) ch = "floatunssidf";
+ else if (l->n_type == INT) ch = "floatsidf";
+ else if (l->n_type == UNSIGNED) ch = "floatunssidf";
+ } else if (p->n_op == SCONV && p->n_type == LDOUBLE) {
+ if (l->n_type == FLOAT) ch = "extendsfdf2";
+ else if (l->n_type == DOUBLE) ch = "extenddfdf2";
+ else if (l->n_type == ULONGLONG) ch = "floatunsdidf";
+ else if (l->n_type == LONGLONG) ch = "floatdidf";
+ else if (l->n_type == LONG) ch = "floatsidf";
+ else if (l->n_type == ULONG) ch = "floatunssidf";
+ else if (l->n_type == INT) ch = "floatsidf";
+ else if (l->n_type == UNSIGNED) ch = "floatunsidf";
+ } else if (p->n_op == SCONV && p->n_type == ULONGLONG) {
+ if (l->n_type == FLOAT) ch = "fixunssfdi";
+ else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixunsdfdi";
+ } else if (p->n_op == SCONV && p->n_type == LONGLONG) {
+ if (l->n_type == FLOAT) ch = "fixsfdi";
+ else if (l->n_type == DOUBLE) ch = "fixdfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixtfdi";
+ } else if (p->n_op == SCONV && p->n_type == LONG) {
+ if (l->n_type == FLOAT) ch = "fixsfdi";
+ else if (l->n_type == DOUBLE) ch = "fixdfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixtfdi";
+ } else if (p->n_op == SCONV && p->n_type == ULONG) {
+ if (l->n_type == FLOAT) ch = "fixunssfdi";
+ else if (l->n_type == DOUBLE) ch = "fixunsdfdi";
+ else if (l->n_type == LDOUBLE) ch = "fixunstfdi";
+ } else if (p->n_op == SCONV && p->n_type == INT) {
+ if (l->n_type == FLOAT) ch = "fixsfsi";
+ else if (l->n_type == DOUBLE) ch = "fixdfsi";
+ else if (l->n_type == LDOUBLE) ch = "fixdfsi";
+ } else if (p->n_op == SCONV && p->n_type == UNSIGNED) {
+ if (l->n_type == FLOAT) ch = "fixunssfsi";
+ else if (l->n_type == DOUBLE) ch = "fixunsdfsi";
+ else if (l->n_type == LDOUBLE) ch = "fixunsdfsi";
}
- /* 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");
-}
+ if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op);
+
+ if (kflag) {
+#if defined(ELFABI)
+ printf("\tbl __%s@got(30)" COM "soft-float\n", exname(ch));
+#elif defined(MACHOABI)
+ char buf[32];
+ printf("\tbl L__%s$stub" COM "soft-float\n", ch);
+ snprintf(buf, 32, "__%s", ch);
+ addstub(&stublist, buf);
#endif
+ } else {
+ printf("\tbl __%s" COM "soft-float\n", exname(ch));
+ }
+
+ if (p->n_op >= EQ && p->n_op <= GT)
+ printf("\tcmpwi %s,0\n", rnames[R3]);
+}
-#if 0
/*
- * Push a structure on stack as argument.
- * the scratch registers are already free here
+ * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
*/
+
static void
-starg(NODE *p)
+emul(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");
-}
+ char *ch = NULL;
+
+ if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3";
+ else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG ||
+ DEUNSIGN(p->n_type) == INT))
+ ch = "ashlsi3";
+
+ else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3";
+ else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT))
+ ch = "lshrsi3";
+
+ else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3";
+ else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT))
+ ch = "ashrsi3";
+
+ else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3";
+ else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT))
+ ch = "divsi3";
+
+ else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3";
+ else if (p->n_op == DIV && (p->n_type == ULONG ||
+ p->n_type == UNSIGNED))
+ ch = "udivsi3";
+
+ else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3";
+ else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT))
+ ch = "modsi3";
+
+ else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3";
+ else if (p->n_op == MOD && (p->n_type == ULONG ||
+ p->n_type == UNSIGNED))
+ ch = "umodsi3";
+
+ else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3";
+ else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT))
+ ch = "mulsi3";
+
+ else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2";
+ else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2";
+
+ else ch = 0, comperr("ZE");
+ if (kflag) {
+#if defined(ELFABI)
+ printf("\tbl __%s@got(30)" COM "emulated op\n", exname(ch));
+#elif defined(MACHOABI)
+ char buf[32];
+ printf("\tbl L__%s$stub" COM "emulated op\n", ch);
+ snprintf(buf, 32, "__%s", ch);
+ addstub(&stublist, buf);
#endif
+ } else {
+ printf("\tbl __%s" COM "emulated operation\n", exname(ch));
+ }
+}
-#if 0
/*
- * Compare two floating point numbers.
+ * Floating-point conversions (int -> float/double & float/double -> int)
*/
+
static void
-fcomp(NODE *p)
+ftoi(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);
+ NODE *l = p->n_left;
+
+ printf(COM "start conversion float/(l)double to int\n");
+
+ if (l->n_op != OREG) {
+ expand(p, 0, "\tstw AL,-4");
+ printf("(%s)\n", rnames[SPREG]);
+ if (l->n_type == FLOAT)
+ expand(p, 0, "\tlfs A2,");
+ else
+ expand(p, 0, "\tlfd A2,\n");
+ printf("-4(%s)\n", rnames[SPREG]);
+ } else {
+ if (l->n_type == FLOAT)
+ expand(p, 0, "\tlfs A2,AL\n");
+ else
+ expand(p, 0, "\tlfd A2,AL\n");
}
+
+ expand(p, 0, "\tfctiwz A2,A2\n");
+ expand(p, 0, "\tstfd A2,");
+ printf("-8(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\tlwz A1,");
+ printf("-4(%s)\n", rnames[SPREG]);
+
+ printf(COM "end conversion\n");
}
-#endif
-#if 0
-/*
- * Convert an unsigned long long to floating point number.
- */
static void
-ulltofp(NODE *p)
+ftou(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");
+ static int lab = 0;
+ NODE *l = p->n_left;
+ int lab1 = getlab();
+ int lab2 = getlab();
+
+ printf(COM "start conversion of float/(l)double to unsigned\n");
+
+ if (lab == 0) {
+ lab = getlab();
+ expand(p, 0, "\t.data\n");
+ printf(LABFMT ":\t.long 0x41e00000\n\t.long 0\n", lab);
+ expand(p, 0, "\t.text\n");
+ }
+
+ if (l->n_op != OREG) {
+ expand(p, 0, "\tstw AL,");
+ printf("-4(%s)\n", rnames[SPREG]);
+ if (l->n_type == FLOAT)
+ expand(p, 0, "\tlfs A3,");
+ else
+ expand(p, 0, "\tlfd A3,");
+ printf("-4(%s)\n", rnames[SPREG]);
+
+ } else {
+ if (l->n_type == FLOAT)
+ expand(p, 0, "\tlfs A3,AL\n");
+ else
+ expand(p, 0, "\tlfd A3,AL\n");
+ }
+
+#if 0
+ if (kflag) {
+ expand(p, 0, "\taddis A1,");
+ printf("%s,ha16(", rnames[R31]);
+ printf(LABFMT, lab);
+ printf("-L%s$pb)\n", cftnsp->soname);
+ expand(p, 0, "\tlfd A2,lo16(");
+ printf(LABFMT, lab);
+ printf("-L%s$pb)", cftnsp->soname);
+ expand(p, 0, "(A1)\n");
+ } else {
+ expand(p, 0, "\tlfd A2,");
+ printf(LABFMT "\n", lab);
}
- 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);
-}
#endif
-static int
-argsiz(NODE *p)
-{
- TWORD t = p->n_type;
+#if defined(ELFABI)
- 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;
+ expand(p, 0, "\taddis A1,");
+ printf("%s," LABFMT "@ha\n", rnames[R31], lab);
+ expand(p, 0, "\tlfd A2,");
+ printf(LABFMT "@l", lab);
+ expand(p, 0, "(A1)\n");
+
+#elif defined(MACHOABI)
+
+ expand(p, 0, "\taddis A1,");
+ printf("%s,ha16(", rnames[R31]);
+ printf(LABFMT, lab);
+ if (kflag)
+ printf("-L%s$pb", cftnsp->soname);
+ printf(")\n");
+ expand(p, 0, "\tlfd A2,lo16(");
+ printf(LABFMT, lab);
+ if (kflag)
+ printf("-L%s$pb", cftnsp->soname);
+ expand(p, 0, ")(A1)\n");
+
+#endif
+
+ expand(p, 0, "\tfcmpu cr7,A3,A2\n");
+ printf("\tcror 30,29,30\n");
+ printf("\tbeq cr7,"LABFMT "\n", lab1);
+
+ expand(p, 0, "\tfctiwz A2,A3\n");
+ expand(p, 0, "\tstfd A2,");
+ printf("-8(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\tlwz A1,");
+ printf("-4(%s)\n", rnames[SPREG]);
+ printf("\tba " LABFMT "\n", lab2);
+
+ deflab(lab1);
+
+ expand(p, 0, "\tfsub A2,A3,A2\n");
+ expand(p, 0, "\tfctiwz A2,A2\n");
+ expand(p, 0, "\tstfd A2,");
+ printf("-8(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\tlwz A1,");
+ printf("-4(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\txoris A1,A1,0x8000\n");
+
+ deflab(lab2);
+
+ printf(COM "end conversion\n");
}
-void
-zzzcode(NODE *p, int c)
+static void
+itof(NODE *p)
{
-#if 0
- NODE *r, *l;
- int pr, lr, s;
- char *ch;
-#endif
- char inst[50];
+ static int labu = 0;
+ static int labi = 0;
+ int lab;
+ NODE *l = p->n_left;
+
+ printf(COM "start conversion (u)int to float/(l)double\n");
+
+ if (labi == 0 && l->n_type == INT) {
+ labi = getlab();
+ expand(p, 0, "\t.data\n");
+ printf(LABFMT ":\t.long 0x43300000\n\t.long 0x80000000\n", labi);
+ expand(p, 0, "\t.text\n");
+ } else if (labu == 0 && l->n_type == UNSIGNED) {
+ labu = getlab();
+ expand(p, 0, "\t.data\n");
+ printf(LABFMT ":\t.long 0x43300000\n\t.long 0x00000000\n", labu);
+ expand(p, 0, "\t.text\n");
+ }
+
+ if (l->n_type == INT) {
+ expand(p, 0, "\txoris A1,AL,0x8000\n");
+ lab = labi;
+ } else {
+ lab = labu;
+ }
+ expand(p, 0, "\tstw A1,");
+ printf("-4(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\tlis A1,0x4330\n");
+ expand(p, 0, "\tstw A1,");
+ printf("-8(%s)\n", rnames[SPREG]);
+ expand(p, 0, "\tlfd A3,");
+ printf("-8(%s)\n", rnames[SPREG]);
- switch (c) {
#if 0
- 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;
+ if (kflag) {
+ expand(p, 0, "\taddis A1,");
+ printf("%s,ha16(", rnames[R31]);
+ printf(LABFMT, lab);
+ printf("-L%s$pb)\n", cftnsp->soname);
+ expand(p, 0, "\tlfd A2,lo16(");
+ printf(LABFMT, lab);
+ printf("-L%s$pb)", cftnsp->soname);
+ expand(p, 0, "(A1)\n");
+ } else {
+ expand(p, 0, "\tlfd A2,");
+ printf(LABFMT "\n", lab);
+ }
#endif
- case 'D': /* Long long comparision */
- twollcomp(p);
- break;
+#if defined(ELFABI)
-#if 0
- case 'E': /* Assign to bitfield */
- bfasg(p);
- break;
+ expand(p, 0, "\taddis A1,");
+ printf("%s," LABFMT "@ha\n", rnames[R31], lab);
+ expand(p, 0, "\tlfd A2,");
+ printf(LABFMT "@l", lab);
+ expand(p, 0, "(A1)\n");
- case 'F': /* Structure argument */
- if (p->n_stalign != 0) /* already on stack */
- starg(p);
- break;
+#elif defined(MACHOABI)
- case 'G': /* Floating point compare */
- fcomp(p);
- break;
+ expand(p, 0, "\taddis A1,");
+ printf("%s,ha16(", rnames[R31]);
+ printf(LABFMT, lab);
+ if (kflag)
+ printf("-L%s$pb", cftnsp->soname);
+ printf(")\n");
+ expand(p, 0, "\tlfd A2,lo16(");
+ printf(LABFMT, lab);
+ if (kflag)
+ printf("-L%s$pb", cftnsp->soname);
+ expand(p, 0, ")(A1)\n");
- case 'J': /* convert unsigned long long to floating point */
- ulltofp(p);
- break;
+#endif
- case 'N': /* output extended reg name */
- printf("%s", rnames[getlr(p, '1')->n_rval]);
- break;
+ expand(p, 0, "\tfsub A3,A3,A2\n");
+ if (p->n_type == FLOAT)
+ expand(p, 0, "\tfrsp A3,A3\n");
+
+ printf(COM "end conversion\n");
+}
+
+
+static void
+fpconv(NODE *p)
+{
+ NODE *l = p->n_left;
+
+#ifdef PCC_DEBUG
+ if (p->n_op != SCONV)
+ cerror("fpconv 1");
#endif
- case 'O': /* 64-bit left and right shift operators */
+ if (DEUNSIGN(l->n_type) == INT)
+ itof(p);
+ else if (p->n_type == INT)
+ ftoi(p);
+ else if (p->n_type == UNSIGNED)
+ ftou(p);
+ else
+ cerror("unhandled floating-point conversion");
- if (p->n_op == LS && p->n_right->n_lval < 32) {
- expand(p, INBREG, "\tsrwi A1,AL,32-AR ; 64-bit left-shift\n");
- expand(p, INBREG, "\tslwi U1,UL,AR\n");
- expand(p, INBREG, "\tor U1,U1,A1\n");
- expand(p, INBREG, "\tslwi A1,AL,AR\n");
- } else if (p->n_op == LS) {
- expand(p, INBREG, "\tli A1,0 ; 64-bit left-shift\n");
- expand(p, INBREG, "\tslwi U1,AL,AR-32\n");
- } else if (p->n_op == RS && p->n_right->n_lval < 32) {
- expand(p, INBREG, "\tslwi U1,UL,32-AR ; 64-bit right-shift\n");
- expand(p, INBREG, "\tsrwi A1,AL,AR\n");
- expand(p, INBREG, "\tor A1,A1,U1\n");
- expand(p, INBREG, "\tsrwi U1,UL,AR\n");
- } else if (p->n_op == RS) {
- expand(p, INBREG, "\tli U1,0 ; 64-bit right-shift\n");
- expand(p, INBREG, "\tsrwi A1,UL,AR-32\n");
- }
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ switch (c) {
+
+ case 'C': /* floating-point conversions */
+ fpconv(p);
break;
+ case 'D': /* long long comparision */
+ twollcomp(p);
+ break;
-#if 0
- 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("\tbl __%sdi3\n\n", ch,);
- break;
-#endif
+ case 'E': /* print out emulated ops */
+ emul(p);
+ break;
-#if 0
- 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');
+ case 'F': /* print out emulate floating-point ops */
+ fpemul(p);
break;
-#endif
- case 'Q': /* emit struct assign */
- if (p->n_stsize == 4) {
- int sz = sizeof inst;
-
- snprintf(inst, sz, "\tlwz %s,0(AR)\n", rnames[R5]);
- expand(p, INAREG, inst);
- snprintf(inst, sz, "\tstw %s,AL\n", rnames[R5]);
- expand(p, INAREG, inst);
- return;
- }
+ case 'O': /* 64-bit left and right shift operators */
+ shiftop(p);
+ break;
- if ((p->n_stsize & ~0xffff) != 0) {
- printf("\tlis %s,%d\n", rnames[R5], p->n_stsize & 0xffff);
- printf("\taddis %s,%s,%d\n", rnames[R5], rnames[R5], (p->n_stsize >> 16) & 0xffff);
- } else {
- printf("\tli %s,%d\n", rnames[R5], p->n_stsize);
- }
- printf("\taddi %s,%s,%lld\n", rnames[R3], rnames[p->n_left->n_rval], p->n_left->n_lval);
- printf("\tbl %s%s\n", exname("memcpy"),
- kflag ? "$stub" : "");
- addstub(&stublist, exname("memcpy"));
+ case 'Q': /* emit struct assign */
+ stasg(p);
break;
default:
@@ -643,16 +854,41 @@ canaddr(NODE *p)
{
int o = p->n_op;
- if (o==NAME || o==REG || o==ICON || o==OREG ||
- (o==UMUL && shumul(p->n_left)))
+ if (o == NAME || o == REG || o == ICON || o == OREG ||
+ (o == UMUL && shumul(p->n_left)))
return(1);
- return(0);
+ return 0;
}
int
fldexpand(NODE *p, int cookie, char **cp)
{
- return 0;
+ CONSZ val;
+ int shft;
+
+ if (p->n_op == ASSIGN)
+ p = p->n_left;
+
+ shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval);
+
+ switch (**cp) {
+ case 'S':
+ printf("%d", UPKFSZ(p->n_rval));
+ break;
+ case 'H':
+ printf("%d", shft);
+ break;
+ case 'M':
+ case 'N':
+ val = (CONSZ)1 << UPKFSZ(p->n_rval);
+ --val;
+ val <<= shft;
+ printf(CONFMT, (**cp == 'M' ? val : ~val) & 0xffffffff);
+ break;
+ default:
+ comperr("fldexpand");
+ }
+ return 1;
}
/*
@@ -685,10 +921,10 @@ shtemp(NODE *p)
switch (p->n_op) {
case REG:
- return (!istreg(p->n_rval));
+ return (!istreg(regno(p)));
case OREG:
- r = p->n_rval;
+ r = regno(p);
if (R2TEST(r)) {
if (istreg(R2UPK1(r)))
return(0);
@@ -716,46 +952,20 @@ adrcon(CONSZ val)
void
conput(FILE *fp, NODE *p)
{
- char *s;
int val = p->n_lval;
switch (p->n_op) {
case ICON:
-#if 0
- if (p->n_sp)
- printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel);
-#endif
- if (p->n_sp == NULL || (p->n_sp->sclass == ILABEL ||
- (p->n_sp->sclass == STATIC && p->n_sp->slevel > 0)))
- s = p->n_name;
- else
- s = exname(p->n_name);
-
- if (*s != '\0') {
- if (kflag && p->n_sp && ISFTN(p->n_sp->stype)) {
- if (p->n_sp && p->n_sp->sclass == EXTERN) {
- fprintf(fp, "%s$stub", s);
- addstub(&stublist, s);
- } else {
- fprintf(fp, "%s", s);
- }
- } else if (kflag) {
- if (p->n_sp && p->n_sp->sclass == EXTERN) {
- fprintf(fp, "L%s$non_lazy_ptr", s);
- addstub(&nlplist, s);
- } else {
- fprintf(fp, "%s", s);
- }
- fprintf(fp, "-L%s$pb", exname(funcname));
- } else {
- fprintf(fp, "%s", s);
- }
- if (val > 0)
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
fprintf(fp, "+%d", val);
- else if (val < 0)
- fprintf(fp, "-%d", -val);
- } else
- fprintf(fp, "%d", val);
+ } else {
+ if (GCLASS(p->n_type) == CLASSB)
+ fprintf(fp, CONFMT, p->n_lval >> 32);
+ else
+ fprintf(fp, "%d", val);
+ }
return;
default:
@@ -774,19 +984,20 @@ insput(NODE *p)
* Print lower or upper name of 64-bit register.
*/
static void
-reg64name(int rval, int hi)
+reg64name(int reg, int hi)
{
- int off = 3 * (hi != 0);
+ int idx;
+ int off = 0;
-#ifdef ELFABI
- fputc('%', stdout);
-#endif
+ assert(GCLASS(reg) == CLASSB);
+
+ idx = (reg > R14R15 ? (2*(reg - R14R15) + R14) : (reg - R3R4 + R3));
- fprintf(stdout, "%c%c",
- rnames[rval][off],
- rnames[rval][off + 1]);
- if (rnames[rval][off + 2])
- fputc(rnames[rval][off + 2], stdout);
+ if ((hi == HIREG && !features(FEATURE_BIGENDIAN)) ||
+ (hi == LOWREG && features(FEATURE_BIGENDIAN)))
+ off = 1;
+
+ fprintf(stdout, "%s" , rnames[idx + off]);
}
/*
@@ -796,22 +1007,25 @@ reg64name(int rval, int hi)
void
upput(NODE *p, int size)
{
-
size /= SZCHAR;
switch (p->n_op) {
case REG:
- reg64name(p->n_rval, 1);
+ reg64name(regno(p), HIREG);
break;
case NAME:
case OREG:
- p->n_lval += size;
- adrput(stdout, p);
- p->n_lval -= size;
+ if (features(FEATURE_BIGENDIAN))
+ fprintf(stdout, "%d", (int)p->n_lval);
+ else
+ fprintf(stdout, "%d", (int)(p->n_lval + 4));
+ fprintf(stdout, "(%s)", rnames[regno(p)]);
break;
+
case ICON:
fprintf(stdout, CONFMT, p->n_lval >> 32);
break;
+
default:
comperr("upput bad op %d size %d", p->n_op, size);
}
@@ -820,7 +1034,6 @@ upput(NODE *p, int size)
void
adrput(FILE *io, NODE *p)
{
- int r;
/* output an address, with offsets, from p */
if (p->n_op == FLD)
@@ -830,19 +1043,7 @@ adrput(FILE *io, NODE *p)
case NAME:
if (p->n_name[0] != '\0') {
- if (kflag && p->n_sp && (p->n_sp->sclass == EXTERN || p->n_sp->sclass == EXTDEF)) {
- fprintf(io, "L%s$non_lazy_ptr", exname(p->n_name));
- addstub(&nlplist, exname(p->n_name));
- fprintf(io, "-L%s$pb", exname(funcname));
- } else if (kflag && p->n_sp && p->n_sp->sclass == STATIC && p->n_sp->slevel == 0) {
- fprintf(io, "%s", exname(p->n_name));
- fprintf(io, "-L%s$pb", exname(funcname));
- } else if (kflag && p->n_sp && (p->n_sp->sclass == ILABEL || (p->n_sp->sclass == STATIC && p->n_sp->sclass > 0))) {
- fprintf(io, "%s", p->n_name);
- fprintf(io, "-L%s$pb", exname(funcname));
- } else {
- fputs(p->n_name, io);
- }
+ fputs(p->n_name, io);
if (p->n_lval != 0)
fprintf(io, "+" CONFMT, p->n_lval);
} else
@@ -850,9 +1051,12 @@ adrput(FILE *io, NODE *p)
return;
case OREG:
- r = p->n_rval;
- fprintf(io, "%d", (int)p->n_lval);
- fprintf(io, "(%s)", rnames[p->n_rval]);
+ if (DEUNSIGN(p->n_type) == LONGLONG &&
+ features(FEATURE_BIGENDIAN))
+ fprintf(io, "%d", (int)(p->n_lval + 4));
+ else
+ fprintf(io, "%d", (int)p->n_lval);
+ fprintf(io, "(%s)", rnames[regno(p)]);
return;
case ICON:
@@ -860,16 +1064,28 @@ adrput(FILE *io, NODE *p)
conput(io, p);
return;
- case MOVE:
case REG:
+ if (GCLASS(regno(p)) == CLASSB)
+ reg64name(regno(p), LOWREG);
+ else
+ fprintf(io, "%s", rnames[regno(p)]);
+#if 0
switch (p->n_type) {
+ case DOUBLE:
+ case LDOUBLE:
+ if (features(FEATURE_HARDFLOAT)) {
+ fprintf(io, "%s", rnames[regno(p)]);
+ break;
+ }
+ /* FALL-THROUGH */
case LONGLONG:
case ULONGLONG:
- reg64name(p->n_rval, 0);
+ reg64name(regno(p), LOWREG);
break;
default:
- fprintf(io, "%s", rnames[p->n_rval]);
+ fprintf(io, "%s", rnames[regno(p)]);
}
+#endif
return;
default:
@@ -910,15 +1126,58 @@ cbgen(int o, int lab)
printf("\t%s " LABFMT "\n", ccbranches[o-EQ], lab);
}
+static int
+argsize(NODE *p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONGLONG || t == FLOAT || t > BTMASK)
+ return 4;
+ if (t == LONGLONG || t == ULONGLONG)
+ return 8;
+ if (t == DOUBLE || t == LDOUBLE)
+ return 8;
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsize");
+ return 0;
+}
+
+static int
+calc_args_size(NODE *p)
+{
+ int n = 0;
+
+ if (p->n_op == CM) {
+ n += calc_args_size(p->n_left);
+ n += calc_args_size(p->n_right);
+ return n;
+ }
+
+ n += argsize(p);
+
+ return n;
+}
+
+
static void
fixcalls(NODE *p)
{
- /* Prepare for struct return by allocating bounce space on stack */
+ int n = 0;
+
switch (p->n_op) {
case STCALL:
+ case CALL:
+ n = calc_args_size(p->n_right);
+ if (n > p2maxstacksize)
+ p2maxstacksize = n;
+ /* FALLTHROUGH */
case USTCALL:
- if (p->n_stsize+p2autooff > stkpos)
- stkpos = p->n_stsize+p2autooff;
+ case UCALL:
+ ++p2calls;
+ break;
+ case TEMP:
+ p2temps += argsize(p);
break;
}
}
@@ -949,9 +1208,9 @@ storefloat(struct interpass *ip, NODE *p)
int off;
off = BITOOR(freetemp(szty(t)));
- ll = mklnode(OREG, off, FPREG, t);
+ ll = mklnode(OREG, off, SPREG, t);
nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
- p->n_left = mklnode(OREG, off, FPREG, t);
+ p->n_left = mklnode(OREG, off, SPREG, t);
DLIST_INSERT_BEFORE(ip, nip, qelem);
}
return l|r;
@@ -971,17 +1230,38 @@ myreader(struct interpass *ipole)
{
struct interpass *ip;
- stkpos = p2autooff;
+ p2calls = 0;
+ p2temps = 0;
+ p2maxstacksize = 0;
+
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 (p2maxstacksize < NARGREGS*SZINT/SZCHAR)
+ p2maxstacksize = NARGREGS*SZINT/SZCHAR;
+
+ p2framesize = ARGINIT/SZCHAR; /* stack ptr / return addr */
+ p2framesize += 8; /* for R31 and R30 */
+ p2framesize += p2maxautooff; /* autos */
+ p2framesize += p2temps; /* TEMPs that aren't autos */
+ if (p2calls != 0)
+ p2framesize += p2maxstacksize; /* arguments to functions */
+ p2framesize += (ALSTACK/SZCHAR - 1); /* round to 16-byte boundary */
+ p2framesize &= ~(ALSTACK/SZCHAR - 1);
+
+#if 0
+ printf("!!! MYREADER\n");
+ printf("!!! p2maxautooff = %d\n", p2maxautooff);
+ printf("!!! p2autooff = %d\n", p2autooff);
+ printf("!!! p2temps = %d\n", p2temps);
+ printf("!!! p2calls = %d\n", p2calls);
+ printf("!!! p2maxstacksize = %d\n", p2maxstacksize);
+#endif
+
if (x2debug)
printip(ipole);
}
@@ -1038,42 +1318,51 @@ void
rmove(int s, int d, TWORD t)
{
switch (t) {
+ case LDOUBLE:
+ case DOUBLE:
+ if (features(FEATURE_HARDFLOAT)) {
+ printf("\tfmr %s,%s" COM "rmove\n",
+ rnames[d], rnames[s]);
+ break;
+ }
+ /* FALL-THROUGH */
case LONGLONG:
case ULONGLONG:
if (s == d+1) {
/* dh = sl, copy low word first */
printf("\tmr ");
- reg64name(d,0);
+ reg64name(d, LOWREG);
printf(",");
- reg64name(s,0);
+ reg64name(s, LOWREG);
printf("\n");
printf("\tmr ");
- reg64name(d,1);
+ reg64name(d, HIREG);
printf(",");
- reg64name(s,1);
+ reg64name(s, HIREG);
printf("\n");
} else {
/* copy high word first */
printf("\tmr ");
- reg64name(d,1);
+ reg64name(d, HIREG);
printf(",");
- reg64name(s,1);
+ reg64name(s, HIREG);
printf("\n");
printf("\tmr ");
- reg64name(d,0);
+ reg64name(d, LOWREG);
printf(",");
- reg64name(s,0);
+ reg64name(s, LOWREG);
printf("\n");
}
break;
- case LDOUBLE:
-#ifdef notdef
- /* a=b()*c(); will generate this */
- comperr("bad float rmove: %d %d", s, d);
-#endif
- break;
+ case FLOAT:
+ if (features(FEATURE_HARDFLOAT)) {
+ printf("\tfmr %s,%s" COM "rmove\n",
+ rnames[d], rnames[s]);
+ break;
+ }
+ /* FALL-THROUGH */
default:
- printf("\tmr %s,%s\n", rnames[d], rnames[s]);
+ printf("\tmr %s,%s" COM "rmove\n", rnames[d], rnames[s]);
}
}
@@ -1092,57 +1381,52 @@ COLORMAP(int c, int *r)
{
int num = 0;
- switch (c) {
- case CLASSA:
- num += r[CLASSA];
- num += 2*r[CLASSB];
- return num < 30;
- case CLASSB:
- num += 2*r[CLASSB];
- num += r[CLASSA];
- return num < 16;
- }
- assert(0);
- return 0; /* XXX gcc */
+ switch (c) {
+ case CLASSA:
+ num += r[CLASSA];
+ num += 2*r[CLASSB];
+ return num < 30;
+ case CLASSB:
+ num += 2*r[CLASSB];
+ num += r[CLASSA];
+ return num < 16;
+ case CLASSC:
+ return num < 32;
+ }
+ assert(0);
+ return 0; /* XXX gcc */
}
-#ifdef ELFABI
-char *rnames[] = {
- "%r0", "%r1", "%r2", "%r3","%r4","%r5", "%r6", "%r7", "%r8",
- "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16",
- "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", "%r24",
- "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
- /* the order is flipped, because we are big endian */
- "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0",
- "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16",
- "r19r18", "r21r20", "r23r22", "r25r24", "r27r26",
- "r29r28", "r31r30",
-};
-#else
-char *rnames[] = {
- "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", "r8",
- "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16",
- "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24",
- "r25", "r26", "r27", "r28", "r29", "r30", "r31",
- /* the order is flipped, because we are big endian */
- "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0",
- "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16",
- "r19r18", "r21r20", "r23r22", "r25r24", "r27r26",
- "r29r28", "r31r30",
-};
-#endif
-
/*
* Return a class suitable for a specific type.
*/
int
gclass(TWORD t)
{
- if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ if (t == LONGLONG || t == ULONGLONG)
return CLASSB;
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE) {
+ if (features(FEATURE_HARDFLOAT))
+ return CLASSC;
+ if (t == FLOAT)
+ return CLASSA;
+ else
+ return CLASSB;
+ }
return CLASSA;
}
+int
+retreg(int t)
+{
+ int c = gclass(t);
+ if (c == CLASSB)
+ return R3R4;
+ else if (c == CLASSC)
+ return F1;
+ return R3;
+}
+
/*
* Calculate argument sizes.
*/
@@ -1160,9 +1444,10 @@ lastcall(NODE *p)
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);
+ size += argsize(p->n_right);
+ size += argsize(p);
op->n_qual = size; /* XXX */
}
@@ -1180,17 +1465,37 @@ special(NODE *p, int shape)
return SRREG;
break;
case SPCON:
- if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0xffff) == 0)
+ if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0x7fff) == 0)
return SRDIR;
break;
}
return SRNOPE;
}
+static int fset = FEATURE_BIGENDIAN | FEATURE_HARDFLOAT;
+
/*
* Target-dependent command-line options.
*/
void
mflags(char *str)
{
+ if (strcasecmp(str, "big-endian") == 0) {
+ fset |= FEATURE_BIGENDIAN;
+ } else if (strcasecmp(str, "little-endian") == 0) {
+ fset &= ~FEATURE_BIGENDIAN;
+ } else if (strcasecmp(str, "soft-float") == 0) {
+ fset &= ~FEATURE_HARDFLOAT;
+ } else if (strcasecmp(str, "hard-float") == 0) {
+ fset |= FEATURE_HARDFLOAT;
+ } else {
+ fprintf(stderr, "unknown m option '%s'\n", str);
+ exit(1);
+ }
+}
+
+int
+features(int mask)
+{
+ return ((fset & mask) == mask);
}
diff --git a/usr.bin/pcc/powerpc/macdefs.h b/usr.bin/pcc/powerpc/macdefs.h
index 8f9f3746f09..72abba8755f 100644
--- a/usr.bin/pcc/powerpc/macdefs.h
+++ b/usr.bin/pcc/powerpc/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.3 2007/12/22 14:05:04 stefan Exp $ */
+/* $OpenBSD: macdefs.h,v 1.4 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -30,6 +30,8 @@
* Machine-dependent defines for both passes.
*/
+#define ELFABI
+
/*
* Convert (multi-)character constant to integer.
*/
@@ -59,11 +61,15 @@
#define ALDOUBLE 32
#define ALLDOUBLE 32
#define ALLONG 32
+#ifdef ELFABI
+#define ALLONGLONG 64
+#else
#define ALLONGLONG 32
+#endif
#define ALSHORT 16
#define ALPOINT 32
#define ALSTRUCT 32
-#define ALSTACK 32
+#define ALSTACK (16*SZCHAR)
/*
* Min/max values.
@@ -85,12 +91,9 @@
#define MAX_ULONGLONG 0xffffffffffffffffULL
#define CHAR_UNSIGNED
-#define TARGET_STDARGS
#define BOOL_TYPE INT /* what used to store _Bool */
#define WCHAR_TYPE INT /* what used to store wchar_t */
-#define ELFABI
-
/*
* Use large-enough types.
*/
@@ -99,33 +102,32 @@ typedef unsigned long long U_CONSZ;
typedef long long OFFSZ;
#define CONFMT "%lld" /* format for printing constants */
-#ifdef ELFABI
+#if defined(ELFABI)
#define LABFMT ".L%d" /* format for printing labels */
-#else
+#define REGPREFIX "%" /* format for printing registers */
+#elif defined(MACHOABI)
#define LABFMT "L%d" /* format for printing labels */
+#define REGPREFIX
+#else
+#error undefined ABI
#endif
#define STABLBL "LL%d" /* format for stab (debugging) labels */
+
+#ifdef MACHOABI
#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */
+#endif
#undef FIELDOPS /* no bit-field instructions */
-#if 0
-#define RTOLBYTES /* bytes are numbered right to left */
-#endif
#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 szty(t) (((t) == DOUBLE || (t) == FLOAT || \
- (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1)
+#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || \
+ DEUNSIGN(t) == LONGLONG) ? 2 : 1)
/*
* The PPC register definition are taken from apple docs.
@@ -133,6 +135,7 @@ typedef long long OFFSZ;
* The classes used are:
* A - general registers
* B - 64-bit register pairs
+ * C - floating-point registers
*/
#define R0 0 // scratch register
@@ -185,25 +188,110 @@ typedef long long OFFSZ;
#define R28R29 46
#define R30R31 47
-#define NUMCLASS 4 // XXX must always be 4
-#define MAXREGS 48
-
-#define RSTATUS \
- 0, 0, SAREG|TEMPREG, SAREG|TEMPREG, \
- SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
- SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG, \
- SAREG, SAREG, SAREG, SAREG, \
- SAREG, SAREG, SAREG, SAREG, \
- SAREG, SAREG, SAREG, SAREG, \
- SAREG, SAREG, SAREG, SAREG, \
- SAREG, SAREG, SAREG, SAREG, \
- \
- SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \
- SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \
+#define F0 48 // scratch register
+#define F1 49 // return value 0 / argument 0
+#define F2 50 // return value 1 / argument 1
+#define F3 51 // return value 2 / argument 2
+#define F4 52 // return value 3 / argument 3
+#define F5 53 // argument 4
+#define F6 54 // argument 5
+#define F7 55 // argument 6
+#define F8 56 // argument 7
+#define F9 57 // argument 8
+#define F10 58 // argument 9
+#define F11 59 // argument 10
+#define F12 60 // argument 11
+#define F13 61 // argument 12
+#define F14 62
+#define F15 63
+#define F16 64
+#define F17 65
+#define F18 66
+#define F19 67
+#define F20 68
+#define F21 69
+#define F22 70
+#define F23 71
+#define F24 72
+#define F25 73
+#define F26 74
+#define F27 75
+#define F28 76
+#define F29 77
+#define F30 78
+#define F31 79
+
+#define NUMCLASS 3
+#define MAXREGS 64 // XXX cannot have more than 64
+
+#define RSTATUS \
+ 0, /* R0 */ \
+ 0, /* R1 */ \
+ SAREG|TEMPREG, /* R2 */ \
+ SAREG|TEMPREG, /* R3 */ \
+ SAREG|TEMPREG, /* R4 */ \
+ SAREG|TEMPREG, /* R5 */ \
+ SAREG|TEMPREG, /* R6 */ \
+ SAREG|TEMPREG, /* R7 */ \
+ SAREG|TEMPREG, /* R8 */ \
+ SAREG|TEMPREG, /* R9 */ \
+ SAREG|TEMPREG, /* R10 */ \
+ SAREG|TEMPREG, /* R11 */ \
+ SAREG|TEMPREG, /* R12 */ \
+ SAREG, /* R13 */ \
+ SAREG, /* R14 */ \
+ SAREG, /* R15 */ \
+ SAREG, /* R16 */ \
+ SAREG, /* R17 */ \
+ SAREG, /* R18 */ \
+ SAREG, /* R19 */ \
+ SAREG, /* R20 */ \
+ SAREG, /* R21 */ \
+ SAREG, /* R22 */ \
+ SAREG, /* R23 */ \
+ SAREG, /* R24 */ \
+ SAREG, /* R25 */ \
+ SAREG, /* R26 */ \
+ SAREG, /* R27 */ \
+ SAREG, /* R28 */ \
+ SAREG, /* R29 */ \
+ SAREG, /* R30 */ \
+ SAREG, /* R31 */ \
+ \
+ SBREG|TEMPREG, /* R3R4 */ \
+ SBREG|TEMPREG, /* R4R5 */ \
+ SBREG|TEMPREG, /* R5R6 */ \
+ SBREG|TEMPREG, /* R6R7 */ \
+ SBREG|TEMPREG, /* R7R8 */ \
+ SBREG|TEMPREG, /* R8R9 */ \
+ SBREG|TEMPREG, /* R9R10 */ \
\
- SBREG, SBREG, SBREG, SBREG, \
- SBREG, SBREG, SBREG, SBREG, \
- SBREG,
+ SBREG, /* R14R15 */ \
+ SBREG, /* R16R17 */ \
+ SBREG, /* R18R19 */ \
+ SBREG, /* R20R21 */ \
+ SBREG, /* R22R23 */ \
+ SBREG, /* R24R25 */ \
+ SBREG, /* R26R2k */ \
+ SBREG, /* R28R29 */ \
+ SBREG, /* R30R31 */ \
+ \
+ SCREG|TEMPREG, /* F0 */ \
+ SCREG|TEMPREG, /* F1 */ \
+ SCREG|TEMPREG, /* F2 */ \
+ SCREG|TEMPREG, /* F3 */ \
+ SCREG|TEMPREG, /* F4 */ \
+ SCREG|TEMPREG, /* F5 */ \
+ SCREG|TEMPREG, /* F6 */ \
+ SCREG|TEMPREG, /* F7 */ \
+ SCREG|TEMPREG, /* F8 */ \
+ SCREG|TEMPREG, /* F9 */ \
+ SCREG|TEMPREG, /* F10 */ \
+ SCREG|TEMPREG, /* F11 */ \
+ SCREG|TEMPREG, /* F12 */ \
+ SCREG|TEMPREG, /* F13 */ \
+ SCREG, /* F14 */ \
+ SCREG, /* F15 */ \
#define ROVERLAP \
{ -1 }, { -1 }, { -1 }, \
@@ -230,43 +318,83 @@ typedef long long OFFSZ;
{ R18, R19, -1 }, { R20, R21, -1 }, \
{ R22, R23, -1 }, { R24, R25, -1 }, \
{ R26, R27, -1 }, { R28, R29, -1 }, \
- { R30, R31, -1 },
+ { R30, R31, -1 }, \
+ \
+ { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, \
+
+/*
+ * According to the ABI documents, there isn't really a frame pointer;
+ * all references to data on the stack (autos and parameters) are
+ * indexed relative to the stack pointer. However, pcc isn't really
+ * capable of running in this manner, and expects a frame pointer.
+ */
+#define SPREG R1 /* stack pointer */
+#define FPREG R30 /* frame pointer */
+#define GOTREG R31 /* global offset table (PIC) */
-#if 0
+#ifdef FPREG
+#define ARGINIT (24*8) /* # bits above fp where arguments start */
+#define AUTOINIT (8*8) /* # bits above fp where automatics start */
#define BACKAUTO /* stack grows negatively for automatics */
#define BACKTEMP /* stack grows negatively for temporaries */
-#endif
-
+#else
#define ARGINIT (24*8) /* # bits above fp where arguments start */
#define AUTOINIT (56*8) /* # bits above fp where automatics start */
-
-/* XXX - to die */
-#define FPREG R1 /* frame pointer */
-#if 0
-#define STKREG R30 /* stack pointer */
#endif
/* Return a register class based on the type of the node */
-#define PCLASS(p) (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \
- (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SCREG : SAREG))
+#define PCLASS(p) (1 << gclass((p)->n_type))
-#define GCLASS(x) (x < 32 ? CLASSA : CLASSB)
-#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) ((x) == ULONGLONG || (x) == LONGLONG ? R3R4 : R3)
+#define GCLASS(x) ((x) < 32 ? CLASSA : ((x) < 48 ? CLASSB : CLASSC))
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define RETREG(x) retreg(x)
int COLORMAP(int c, int *r);
+int retreg(int ty);
#define SHSTR (MAXSPECIAL+1) /* short struct */
#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
#define SPCON (MAXSPECIAL+3) /* positive constant */
+int features(int f);
+#define FEATURE_BIGENDIAN 0x00010000
+#define FEATURE_PIC 0x00020000
+#define FEATURE_HARDFLOAT 0x00040000
+
struct stub {
struct { struct stub *q_forw, *q_back; } link;
char *name;
};
+extern struct stub stublist;
+extern struct stub nlplist;
+void addstub(struct stub *list, char *name);
+
+#define TARGET_STDARGS
+#define TARGET_BUILTINS \
+ { "__builtin_stdarg_start", powerpc_builtin_stdarg_start }, \
+ { "__builtin_va_arg", powerpc_builtin_va_arg }, \
+ { "__builtin_va_end", powerpc_builtin_va_end }, \
+ { "__builtin_va_copy", powerpc_builtin_va_copy }, \
+ { "__builtin_return_address", powerpc_builtin_return_address },
+
+#define NODE struct node
+struct node;
+NODE *powerpc_builtin_stdarg_start(NODE *f, NODE *a);
+NODE *powerpc_builtin_va_arg(NODE *f, NODE *a);
+NODE *powerpc_builtin_va_end(NODE *f, NODE *a);
+NODE *powerpc_builtin_va_copy(NODE *f, NODE *a);
+NODE *powerpc_builtin_return_address(NODE *f, NODE *a);
+#undef NODE
-#define FIXEDSTACKSIZE 200 /* in bytes */
+#define NARGREGS 8
+
+#ifdef ELFABI
+#define COM " # "
+#else
+#define COM " ; "
+#endif
diff --git a/usr.bin/pcc/powerpc/order.c b/usr.bin/pcc/powerpc/order.c
index 7c72c15deca..1df4bdb82af 100644
--- a/usr.bin/pcc/powerpc/order.c
+++ b/usr.bin/pcc/powerpc/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.4 2007/12/22 14:05:04 stefan Exp $ */
+/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -34,19 +34,26 @@
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 */
+/*
+ * Check size of offset in OREG. Called by oregok() to see if an
+ * OREG can be generated.
+ *
+ * returns 0 if it can, 1 otherwise.
+ */
int
notoff(TWORD t, int r, CONSZ off, char *cp)
{
+#if 0
+ if (off >= 32767 || off <= -32768)
+ printf("; notoff %lld TOO BIG!\n", off);
+#endif
if (cp && cp[0]) return 1;
- return !(off < 32768 && off > -32769); /* YES */
+ return (off >= 32768 || off <= -32769);
}
/*
- * Turn a UMUL-referenced node into OREG.
- * Be careful about register classes, this is a place where classes change.
+ * Generate instructions for an OREG.
+ * Called by swmatch().
*/
void
offstar(NODE *p, int shape)
@@ -67,59 +74,28 @@ offstar(NODE *p, int shape)
/* Converted in ormake() */
return;
}
- /* usually for arraying indexing: */
- 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.
+ * Unable to convert to OREG (notoff() returned failure). Output
+ * suitable instructions to replace OREG.
*/
void
myormake(NODE *q)
{
-#if 1
- NODE *p, *r;
-#endif
+ NODE *p;
if (x2debug)
printf("myormake(%p)\n", q);
-#if 1 /* XXX remove this and add UMUL(SAREG) to table.c !!! */
- p = q->n_left;
- if (q->n_op != OREG && p->n_op == REG) {
- q->n_op = OREG;
- q->n_lval = 0;
- q->n_rval = p->n_rval;
- tfree(p);
- return;
- }
-#endif
-
-#if 1
- /* usually for array indexing */
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) {
- if (isreg(p->n_left) == 0)
- (void)geninsn(p->n_left, INAREG);
- q->n_op = OREG;
- q->n_lval = 0;
- q->n_rval = p->n_left->n_rval;
- tfree(p);
- }
-#endif
-#if 0
+ /*
+ * This handles failed OREGs conversions, due to the offset
+ * being too large for an OREG.
+ */
if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) {
if (isreg(p->n_left) == 0)
(void)geninsn(p->n_left, INAREG);
@@ -132,8 +108,6 @@ myormake(NODE *q)
q->n_rval = p->n_rval;
tfree(p);
}
-#endif
- (void)geninsn(p, INAREG);
}
/*
@@ -186,12 +160,144 @@ setuni(NODE *p, int cookie)
struct rspecial *
nspecial(struct optab *q)
{
-
if (x2debug)
printf("nspecial: op=%d, visit=0x%x: %s", q->op, q->visit, q->cstring);
switch (q->op) {
+ /* soft-float stuff */
+ case RS:
+ case LS:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NRIGHT, R5 },
+ { NRES, R3R4 },
+ { 0 },
+ };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3 },
+ { NRIGHT, R4 },
+ { NRES, R3 },
+ { 0 },
+ };
+ return s;
+ }
+
+ cerror("nspecial LS/RS");
+ break;
+
+ case UMINUS:
+ case SCONV:
+ if (q->lshape == SBREG && q->rshape == SAREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NRES, R3 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SAREG && q->rshape == SBREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3 },
+ { NRES, R3R4 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SAREG && q->rshape == SAREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3 },
+ { NRES, R3 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SBREG && q->rshape == SBREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NRES, R3R4 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SCREG && q->rshape == SBREG) {
+ static struct rspecial s[] = {
+ { NLEFT, F1 },
+ { NEVER, F0 }, /* stomped on */
+ { NRES, R3R4 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SBREG && q->rshape == SCREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NEVER, F0 }, /* stomped on */
+ { NRES, F1 },
+ { 0 }
+ };
+ return s;
+ } else {
+ static struct rspecial s[] = {
+ { NOLEFT, R0 },
+ { 0 } };
+ return s;
+ }
+
+ break;
+
+ case OPLOG:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NRIGHT, R5R6 },
+ { NRES, R3 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NLEFT, R3 },
+ { NRIGHT, R4 },
+ { NRES, R3 },
+ { 0 }
+ };
+ return s;
+ }
+
+ cerror("nspecial oplog");
+ break;
+
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ case MOD:
+ if (q->lshape == SBREG &&
+ (q->ltype & (TDOUBLE|TLDOUBLE|TLONGLONG|TULONGLONG))) {
+ static struct rspecial s[] = {
+ { NLEFT, R3R4 },
+ { NRIGHT, R5R6 },
+ { NRES, R3R4 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SAREG && q->ltype & TFLOAT) {
+ static struct rspecial s[] = {
+ { NLEFT, R3 },
+ { NRIGHT, R4 },
+ { NRES, R3 },
+ { 0 }
+ };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NOLEFT, R0 },
+ { 0 } };
+ return s;
+ }
+
+ cerror("nspecial mul");
+ break;
+
case STASG:
{
static struct rspecial s[] = {
@@ -239,13 +345,10 @@ nspecial(struct optab *q)
}
/* fallthough */
- case SCONV:
case UMUL:
- case MINUS:
case AND:
case OR:
case ER:
- case PLUS:
{
static struct rspecial s[] = {
{ NOLEFT, R0 },
@@ -269,6 +372,7 @@ setorder(NODE *p)
{
return 0; /* nothing differs on x86 */
}
+
/*
* Set registers "live" at function calls (like arguments in registers).
* This is for liveness analysis of registers.
@@ -276,9 +380,19 @@ setorder(NODE *p)
int *
livecall(NODE *p)
{
- static int r[] = { R3, R4, R5, R6, R7, R8, R9, R10, -1 };
+ static int r[] = { R10, R9, R8, R7, R6, R5, R4, R3, R30, R31, -1 };
+ int num = 1;
+
+ if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
+ return &r[8-0];
+
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ num += szty(p->n_right->n_type);
+ num += szty(p->n_right->n_type);
+
+ num = (num > 8 ? 8 : num);
- return &r[0];
+ return &r[8 - num];
}
/*
@@ -287,5 +401,7 @@ livecall(NODE *p)
int
acceptable(struct optab *op)
{
- return 1;
+ if ((op->visit & FEATURE_PIC) != 0)
+ return (kflag != 0);
+ return features(op->visit & 0xffff0000);
}
diff --git a/usr.bin/pcc/powerpc/table.c b/usr.bin/pcc/powerpc/table.c
index a7cb0a707b3..be3cb3e3306 100644
--- a/usr.bin/pcc/powerpc/table.c
+++ b/usr.bin/pcc/powerpc/table.c
@@ -1,6 +1,5 @@
+/* $OpenBSD: table.c,v 1.10 2008/04/11 20:45:52 stefan Exp $ */
/*-
- * $OpenBSD: table.c,v 1.9 2007/11/24 14:08:06 stefan Exp $
- *
* Copyright (c) 2007 Gregory McGarry <g.mcgarry@ieee.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -33,14 +32,14 @@
#define TSWORD TINT|TLONG
#define TWORD TUWORD|TSWORD
-#ifdef ELFABI
+#if defined(ELFABI)
#define HA16(x) # x "@ha"
#define LO16(x) # x "@l"
-#define COM " # "
-#else
+#elif defined(MACHOABI)
#define HA16(x) "ha16(" # x ")"
#define LO16(x) "lo16(" # x ")"
-#define COM " ; "
+#else
+#error undefined ABI
#endif
struct optab table[] = {
@@ -58,71 +57,68 @@ struct optab table[] = {
* Conversions of integral types
*/
-/* convert (u)char to (u)char */
{ SCONV, INAREG,
SAREG, TCHAR|TUCHAR,
SAREG, TCHAR|TUCHAR,
0, RLEFT,
COM "convert between (u)char and (u)char\n", },
-/* convert (u)short to (u)short */
{ SCONV, INAREG,
SAREG, TSHORT|TUSHORT,
SAREG, TSHORT|TUSHORT,
0, RLEFT,
COM "convert between (u)short and (u)short\n", },
-/* convert pointers to (u)int/(u)long */
{ SCONV, INAREG,
SAREG, TPOINT|TWORD,
SAREG, TWORD,
0, RLEFT,
COM "convert a pointer/word to an int\n", },
-/* convert pointers to pointers */
{ SCONV, INAREG,
SAREG, TPOINT,
SAREG, TPOINT,
0, RLEFT,
COM "convert pointers\n", },
-/* convert (u)longlong to (u)longlong */
{ SCONV, INBREG,
SBREG, TLONGLONG|TULONGLONG,
SBREG, TLONGLONG|TULONGLONG,
0, RLEFT,
COM "convert (u)longlong to (u)longlong\n", },
-/* convert char to short */
{ SCONV, INAREG,
SAREG, TCHAR,
SAREG, TSHORT|TSWORD,
NASL|NAREG, RESC1,
" extsb A1,AL" COM "convert char to short/int\n", },
-/* convert uchar to short */
{ SCONV, INAREG,
SAREG, TUCHAR,
SAREG, TSHORT|TSWORD,
- NASL|NAREG, RESC1,
+ 0, RLEFT,
COM "convert uchar to short/int\n", },
-/* convert uchar to ushort/uint/ulong */
{ SCONV, INAREG,
SAREG, TUCHAR,
SAREG, TUSHORT|TUWORD,
- 0, RLEFT,
- COM "convert uchar (AL) to ushort/unsigned (A1)\n", },
+ 0, RLEFT,
+ COM "convert uchar to ushort/unsigned\n", },
/* XXX is this necessary? */
-/* convert char to ushort/uint/ulong */
{ SCONV, INAREG,
SAREG, TCHAR,
SAREG, TUSHORT|TUWORD,
- NASL|NAREG|NSPECIAL, RESC1,
- " extsb A1,AL" COM "convert char (AL) to ushort/unsigned (A1)\n", },
+ NSPECIAL|NAREG|NASL, RESC1,
+ " extsb A1,AL" COM "convert char to ushort/unsigned\n", },
+
+{ SCONV, INBREG | FEATURE_BIGENDIAN,
+ SAREG, TUCHAR|TUSHORT|TUNSIGNED,
+ SBREG, TLONGLONG|TULONGLONG,
+ NBREG, RESC1,
+ " mr U1,AL" COM "convert uchar/ushort/uint to (u)longlong\n"
+ " li A1,0\n", },
-/* convert uchar/ushort/uint to (u)longlong */
{ SCONV, INBREG,
SAREG, TUCHAR|TUSHORT|TUNSIGNED,
SBREG, TLONGLONG|TULONGLONG,
@@ -130,7 +126,13 @@ struct optab table[] = {
" mr A1,AL" COM "convert uchar/ushort/uint to (u)longlong\n"
" li U1,0\n", },
-/* convert char/short/int to (u)longlong */
+{ SCONV, INBREG | FEATURE_BIGENDIAN,
+ SAREG, TCHAR|TSHORT|TSWORD,
+ SBREG, TULONGLONG|TLONGLONG,
+ NBREG, RESC1,
+ " mr U1,AL" COM "convert char/short/int to ulonglong\n"
+ " srawi A1,AL,31\n", },
+
{ SCONV, INBREG,
SAREG, TCHAR|TSHORT|TSWORD,
SBREG, TULONGLONG|TLONGLONG,
@@ -138,7 +140,6 @@ struct optab table[] = {
" mr A1,AL" COM "convert char/short/int to ulonglong\n"
" srawi U1,AL,31\n", },
-/* convert (u)short to (u)char */
{ SCONV, INAREG,
SAREG, TSHORT|TUSHORT,
SAREG, TCHAR|TUCHAR,
@@ -146,49 +147,42 @@ struct optab table[] = {
" andi. A1,AL,255" COM "convert (u)short to (u)char\n", },
/* XXX is this really necessary? */
-/* convert short to (u)int */
{ SCONV, INAREG,
SAREG, TSHORT,
SAREG, TWORD,
NAREG|NASL, RESC1,
" extsh A1,AL" COM "convert short to int\n", },
-/* convert ushort to (u)int. */
{ SCONV, INAREG,
SAREG, TUSHORT,
SAREG, TWORD,
- NASL|NAREG|NSPECIAL, RESC1,
+ NSPECIAL|NAREG|NASL, RESC1,
COM "convert ushort to word\n", },
-/* convert (u)int to (u)char */
{ SCONV, INAREG,
SAREG, TWORD,
SAREG, TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" andi. A1,AL,255" COM "convert (u)int to (u)char\n", },
-/* convert (u)int to (u)short */
{ SCONV, INAREG,
SAREG, TWORD,
SAREG, TSHORT|TUSHORT,
NAREG|NASL|NSPECIAL, RESC1,
" andi. A1,AL,65535" COM "convert (u)int to (u)short\n", },
-/* convert (u)longlong to (u)char */
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TCHAR|TUCHAR,
NAREG|NSPECIAL, RESC1,
" andi. A1,AL,255" COM "(u)longlong to (u)char\n", },
-/* convert (u)longlong to (u)short*/
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TSHORT|TUSHORT,
NAREG|NSPECIAL, RESC1,
" andi. A1,AL,65535" COM "(u)longlong to (u)short\n", },
-/* convert (u)longlong to (u)int */
{ SCONV, INAREG,
SBREG, TLONGLONG|TULONGLONG,
SAREG, TWORD,
@@ -197,7 +191,6 @@ struct optab table[] = {
/* conversions on load from memory */
-/* char */
{ SCONV, INAREG,
SOREG, TCHAR,
SAREG, TWORD,
@@ -205,28 +198,24 @@ struct optab table[] = {
" lbz A1,AL" COM "convert char to int/long\n"
" extsb A1,A1\n", },
-/* uchar */
{ SCONV, INAREG,
SOREG, TUCHAR,
SAREG, TWORD,
NASL|NAREG|NSPECIAL, RESC1,
" lbz A1,AL" COM "convert uchar to int/long\n", },
-/* short */
{ SCONV, INAREG,
SOREG, TSHORT,
SAREG, TWORD,
NASL|NAREG|NSPECIAL, RESC1,
" lha A1,AL" COM "convert short to int/long\n", },
-/* ushort */
{ SCONV, INAREG,
SOREG, TUSHORT,
SAREG, TWORD,
NASL|NAREG|NSPECIAL, RESC1,
" lhz A1,AL" COM "convert ushort to int/long\n", },
-/* (u)longlong to (u)char */
{ SCONV, INAREG,
SOREG, TLONGLONG|TULONGLONG,
SAREG, TCHAR|TUCHAR,
@@ -234,7 +223,6 @@ struct optab table[] = {
" lwz A1,AL" COM "(u)longlong to (u)char\n"
" andi. A1,A1,255\n", },
-/* (u)longlong to (u)short */
{ SCONV, INAREG,
SOREG, TLONGLONG|TULONGLONG,
SAREG, TSHORT|TUSHORT,
@@ -242,91 +230,283 @@ struct optab table[] = {
" lwz A1,AL" COM "(u)longlong to (u)short\n"
" andi. A1,A1,65535\n", },
-/* (u)longlong to (u)int */
{ SCONV, INAREG,
SOREG, TLONGLONG|TULONGLONG,
SAREG, TWORD,
NAREG|NSPECIAL, RESC1,
" lwz A1,AL" COM "(u)longlong to (u)int\n", },
-/* XXX where are the other OREG conversions? endianness problems? */
+/*
+ * floating-point conversions
+ *
+ * There doesn't appear to be an instruction to move values between
+ * the floating-point registers and the general-purpose registers.
+ * So values are bounced into memory...
+ */
+
+{ SCONV, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ COM "convert float to (l)double\n", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SAREG, TFLOAT,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
+{ SCONV, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ " frsp A1,AL" COM "convert (l)double to float\n", },
+
+/* soft-float */
+{ SCONV, INAREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ SCONV, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ COM "convert (l)double to (l)double\n", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ 0, RLEFT,
+ COM "convert (l)double to (l)double (soft-float)\n", },
+
+{ SCONV, INCREG | FEATURE_HARDFLOAT,
+ SAREG, TWORD,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ 2*NCREG|NAREG, RESC3,
+ "ZC", },
+
+/* soft-float */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SAREG, TWORD,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
+{ SCONV, INAREG | FEATURE_HARDFLOAT,
+ SOREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ SAREG, TWORD,
+ 2*NCREG|NAREG, RESC1,
+ "ZC", },
+
+/* soft-float */
+{ SCONV, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TWORD,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INAREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SAREG, TWORD,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ SCONV, INCREG | FEATURE_HARDFLOAT,
+ SBREG, TLONGLONG|TULONGLONG,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NSPECIAL|NCREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INAREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
+{ SCONV, INBREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ SBREG, TLONGLONG|TULONGLONG,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SAREG, TFLOAT,
+ SBREG, TLONGLONG|TULONGLONG,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
+/* soft-float */
+{ SCONV, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TLONGLONG|TULONGLONG,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
/*
* Subroutine calls.
*/
{ CALL, FOREFF,
- SCON|SNAME, TANY,
- SANY, TANY,
+ SCON, TANY,
+ SANY, TANY,
0, 0,
- " bl CL" COM "call (args, no result) to scon/sname (CL)\n", },
+ " bl CL" COM "call (args, no result) to scon\n", },
{ UCALL, FOREFF,
- SCON|SNAME, TANY,
- SANY, TANY,
+ SCON, TANY,
+ SANY, TANY,
0, 0,
- " bl CL" COM "call (no args, no result) to scon/sname (CL)\n", },
+ " bl CL" COM "call (no args, no result) to scon\n", },
{ CALL, INAREG,
- SCON|SNAME, TANY,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1, /* should be 0 */
- " bl CL" COM "call (args, result in r3) to scon/sname (CL)\n", },
+ " bl CL" COM "call (args, result) to scon\n", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " bl CL" COM "call (no args, result) to scon\n", },
{ CALL, INBREG,
- SCON|SNAME, TANY,
- SBREG, TLONGLONG|TULONGLONG,
+ SCON, TANY,
+ SBREG, TLONGLONG|TULONGLONG,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result) to scon\n", },
+
+{ UCALL, INBREG,
+ SCON, TANY,
+ SBREG, TLONGLONG|TULONGLONG,
NBREG|NBSL, RESC1, /* should be 0 */
- " bl CL" COM "call (args, result in r3:r4) to scon/sname (CL)\n", },
+ " bl CL" COM "call (no args, result) to scon\n", },
+
+{ CALL, INCREG | FEATURE_HARDFLOAT,
+ SCON, TANY,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result) to scon\n", },
+
+{ UCALL, INCREG | FEATURE_HARDFLOAT,
+ SCON, TANY,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " bl CL" COM "call (no args, result) to scon\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TFLOAT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result) to scon\n", },
{ UCALL, INAREG,
- SCON|SNAME, TANY,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT,
+ SCON, TANY,
+ SAREG, TFLOAT,
NAREG|NASL, RESC1, /* should be 0 */
- " bl CL" COM "call (no args, result in r3) to scon/sname (CL)\n", },
+ " bl CL" COM "call (no args, result) to scon\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " bl CL" COM "call (args, result) to scon\n", },
{ UCALL, INBREG,
- SCON|SNAME, TANY,
- SBREG, TLONGLONG|TULONGLONG,
+ SCON, TANY,
+ SBREG, TDOUBLE|TLDOUBLE,
NBREG|NBSL, RESC1, /* should be 0 */
- " bl CL" COM "call (no args, result in r3:r4) to scon/sname (CL)\n", },
+ " bl CL" COM "call (no args, result) to scon\n", },
+
+
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " mtctr AL" COM "call (args, no result) to reg\n"
+ " bctrl\n", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " mtctr AL" COM "call (no args, no result) to reg\n"
+ " bctrl\n", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " mtctr AL" COM "call (args, result) to reg\n"
+ " bctrl\n", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " mtctr AL" COM "call (no args, result) to reg\n"
+ " bctrl\n", },
/* struct return */
{ USTCALL, FOREFF,
SCON, TANY,
SANY, TANY,
- NAREG|NASL, 0,
- "ZP call CL\n", },
+ 0, 0,
+ " bl CL\n", },
{ USTCALL, INAREG,
SCON, TANY,
SANY, TANY,
NAREG|NASL, RESC1, /* should be 0 */
- "ZP call CL\n", },
+ " bl CL\n", },
{ USTCALL, INAREG,
- SNAME|SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call *AL\n", },
+ SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " mtctr AL"
+ " bctrl\n", },
{ STCALL, FOREFF,
SCON, TANY,
SANY, TANY,
- NAREG|NASL, 0,
- "ZP call CL\n", },
+ 0, 0,
+ " bl CL\n", },
{ STCALL, INAREG,
SCON, TANY,
SANY, TANY,
NAREG|NASL, RESC1, /* should be 0 */
- "ZP call CL\n", },
+ " bl CL\n", },
{ STCALL, INAREG,
- SNAME|SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call *AL\n", },
+ SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " mtctr AL"
+ " bctrl\n", },
/*
* The next rules handle all binop-style operators.
@@ -334,14 +514,14 @@ struct optab table[] = {
/* XXX AL cannot be R0 */
{ PLUS, INAREG,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
NAREG|NASL|NSPECIAL, RESC1,
" addi A1,AL,AR" COM "addition of constant\n", },
/* XXX AL cannot be R0 */
{ PLUS, INAREG|FORCC,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" addic. A1,AL,AR" COM "addition of constant\n", },
@@ -354,14 +534,14 @@ struct optab table[] = {
" addze U1,UL\n", },
{ PLUS, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" add A1,AL,AR\n", },
{ PLUS, INAREG|FORCC,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" add. A1,AL,AR\n", },
@@ -372,14 +552,39 @@ struct optab table[] = {
" addc A1,AL,AR" COM "64-bit add\n"
" adde U1,UL,UR\n", },
+{ PLUS, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ " fadds A1,AL,AR" COM "float add\n", },
+
+{ PLUS, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ PLUS, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1,
+ " fadd A1,AL,AR" COM "(l)double add\n", },
+
+/* soft-float */
+{ PLUS, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZF", },
+
{ MINUS, INAREG,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
NAREG|NASL|NSPECIAL, RESC1,
" addi A1,AL,-AR\n", },
{ MINUS, INAREG|FORCC,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" addic. A1,AL,-AR\n", },
@@ -392,14 +597,14 @@ struct optab table[] = {
" addme U1,UL\n", },
{ MINUS, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" subf A1,AR,AL\n", },
{ MINUS, INAREG|FORCC,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" subf. A1,AR,AL\n", },
@@ -410,6 +615,32 @@ struct optab table[] = {
" subfc A1,AR,AL" COM "64-bit subtraction\n"
" subfe U1,UR,UL\n", },
+{ MINUS, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ " fsubs A1,AL,AR\n", },
+
+{ MINUS, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ MINUS, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSL, RESC1,
+ " fsub A1,AL,AR" COM "(l)double sub\n", },
+
+/* soft-float */
+{ MINUS, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZF", },
+
+
/*
* The next rules handle all shift operators.
*/
@@ -442,68 +673,100 @@ struct optab table[] = {
SBREG, TLONGLONG|TULONGLONG,
SCON, TANY,
NBREG, RESC1,
- "ZO" },
+ "ZO", },
+
+{ LS, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TANY,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
{ RS, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
" srw A1,AL,AR" COM "right shift\n", },
-{ RS, INAREG|FORCC,
+{ RS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sraw A1,AL,AR" COM "arithmetic right shift\n", },
+
+{ RS, INAREG|FORCC,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
" srw. A1,AL,AR" COM "right shift\n", },
-{ RS, INAREG,
+{ RS, INAREG|FORCC,
+ SAREG, TSWORD|TSHORT|TCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " sraw. A1,AL,AR" COM "arithmetic right shift\n", },
+
+{ RS, INAREG,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
SCON, TANY,
NAREG|NASL, RESC1,
" srwi A1,AL,AR" COM "right shift by constant\n", },
+{ RS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " srawi A1,AL,AR" COM "arithmetic right shift by constant\n", },
+
{ RS, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
SCON, TANY,
NAREG|NASL, RESC1,
" srwi. A1,AL,AR" COM "right shift by constant\n", },
+{ RS, INAREG|FORCC,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " srawi. A1,AL,AR" COM "right shift by constant\n", },
+
{ RS, INBREG,
SBREG, TLONGLONG|TULONGLONG,
SCON, TANY,
NBREG, RESC1,
"ZO" },
+{ RS, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SAREG, TANY,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
+
/*
* The next rules takes care of assignments. "=".
*/
-/* assign 16-bit constant to register */
{ ASSIGN, FOREFF|INAREG,
- SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
0, RDEST,
" li AL,AR\n", },
-/* assign 16-bit constant to register */
{ ASSIGN, FOREFF|INBREG,
- SBREG, TANY,
+ SBREG, TLONGLONG|TULONGLONG,
SSCON, TANY,
0, RDEST,
" li AL,AR\n"
" li UL,UR\n", },
-/* assign constant to register */
{ ASSIGN, FOREFF|INAREG,
- SAREG, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SCON, TANY,
0, RDEST,
" lis AL," HA16(AR) "\n"
" addi AL,AL," LO16(AR) "\n", },
-/* assign constant to register */
{ ASSIGN, FOREFF|INBREG,
- SBREG, TANY,
+ SBREG, TLONGLONG|TULONGLONG,
SCON, TANY,
0, RDEST,
" lis AL," HA16(AR) "\n"
@@ -511,14 +774,12 @@ struct optab table[] = {
" lis UL," HA16(UR) "\n"\
" addi UL,UL," LO16(UR) "\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SOREG, TWORD|TPOINT,
NSPECIAL, RDEST,
- " lwz AL,AR\n", },
+ " lwz AL,AR" COM "assign oreg to reg\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SNAME, TWORD|TPOINT,
@@ -526,7 +787,6 @@ struct optab table[] = {
" lis AL," HA16(AR) COM "assign sname to reg\n"
" lwz AL," LO16(AR) "(AL)\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INBREG,
SBREG, TLONGLONG|TULONGLONG,
SOREG, TLONGLONG|TULONGLONG,
@@ -543,7 +803,6 @@ struct optab table[] = {
" lis UL," HA16(UR) "\n"
" lwz UL," LO16(UR) "(UL)\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INBREG,
SBREG, TLONGLONG|TULONGLONG,
SOREG, TSWORD,
@@ -551,22 +810,19 @@ struct optab table[] = {
" lwz AL,AR" COM "load int/pointer into llong\n"
" srawi UL,AR,31\n" },
-/* assign memory to register */
{ ASSIGN, FOREFF|INBREG,
SBREG, TLONGLONG|TULONGLONG,
SOREG, TUNSIGNED|TPOINT,
NSPECIAL, RDEST,
" lwz AL,AR" COM "load uint/pointer into (u)llong\n"
- " li UL, 0\n" },
+ " li UL,0\n" },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TUCHAR,
SOREG, TUCHAR,
NSPECIAL, RDEST,
" lbz AL,AR\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TUCHAR,
SNAME, TUCHAR,
@@ -574,7 +830,6 @@ struct optab table[] = {
" lis AL," HA16(AR) COM "assign uchar sname to reg\n"
" lbz AL," LO16(AR) "(AL)\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TCHAR,
SOREG, TCHAR,
@@ -582,7 +837,6 @@ struct optab table[] = {
" lbz AL,AR\n"
" extsb AL,AL\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TCHAR,
SNAME, TCHAR,
@@ -591,21 +845,18 @@ struct optab table[] = {
" lbz AL," LO16(AR) "(AL)\n"
" extsb AL,AL\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SOREG, TSHORT,
NSPECIAL, RDEST,
" lha AL,AR\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SOREG, TUSHORT,
NSPECIAL, RDEST,
" lhz AL,AR\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD,
SNAME, TSHORT,
@@ -613,7 +864,6 @@ struct optab table[] = {
" lis AL," HA16(AR) "\n"
" lha AL," LO16(AR) "(AL)\n", },
-/* assign memory to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD,
SNAME, TUSHORT,
@@ -621,14 +871,12 @@ struct optab table[] = {
" lis AL," HA16(AR) "\n"
" lhz AL," LO16(AR) "(AL)\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SOREG, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
NSPECIAL, RDEST,
" stw AR,AL\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SNAME, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
@@ -636,7 +884,6 @@ struct optab table[] = {
" lis A1," HA16(AL) COM "assign reg to sname\n"
" stw AR," LO16(AL) "(A1)\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INBREG,
SOREG, TLONGLONG|TULONGLONG,
SBREG, TLONGLONG|TULONGLONG,
@@ -644,7 +891,6 @@ struct optab table[] = {
" stw AR,AL" COM "store 64-bit value\n"
" stw UR,UL\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INBREG,
SNAME, TLONGLONG|TULONGLONG,
SBREG, TLONGLONG|TULONGLONG,
@@ -654,14 +900,12 @@ struct optab table[] = {
" lis U1," HA16(UL) "\n"
" stw UR," LO16(UL) "(U1)\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SOREG, TCHAR|TUCHAR,
SAREG, TCHAR|TUCHAR,
NSPECIAL, RDEST,
" stb AR,AL\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SNAME, TCHAR|TUCHAR,
SAREG, TCHAR|TUCHAR,
@@ -669,14 +913,12 @@ struct optab table[] = {
" lis A1," HA16(AL) "\n"
" stb AR," LO16(AL) "(A1)\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SOREG, TSHORT|TUSHORT,
SAREG, TSHORT|TUSHORT,
NSPECIAL, RDEST,
" sth AR,AL\n", },
-/* assign register to memory */
{ ASSIGN, FOREFF|INAREG,
SNAME, TSHORT|TUSHORT,
SAREG, TSHORT|TUSHORT,
@@ -684,7 +926,6 @@ struct optab table[] = {
" lis A1," HA16(AL) "\n"
" sth AR," LO16(AL) "(A1)\n", },
-/* assign register to register */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
@@ -698,88 +939,280 @@ struct optab table[] = {
" mr AL,AR" COM "assign UR:AR to UL:AL\n"
" mr UL,UR\n", },
-#if 0
-/* assign register to memory */
-{ ASSIGN, FOREFF,
- SAREG, TPOINT,
- SAREG, TWORD,
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TANY,
+ SAREG, TANY,
+ 3*NAREG, RDEST,
+ " lis A3," HA16(M) COM "bit-field assignment\n"
+ " addi A3,A3," LO16(M) "\n"
+ " lwz A2,AL\n"
+ " slwi A1,AR,H\n"
+ " and A1,A1,A3\n"
+ " not A3,A3\n"
+ " and A2,A2,A3\n"
+ " or A2,A2,A1\n"
+ " stw A2,AL\n"
+ "F mr AD,AR\n"
+ "F slwi AD,AD,32-S\n"
+ "F srwi AD,AD,32-S\n", },
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SOREG, TFLOAT,
+ SCREG, TFLOAT,
0, RDEST,
- " stw AR,0(AL)" COM "indirect assign\n", },
-#endif
+ " stfs AR,AL" COM "store float\n", },
-#if 0
+/* soft-float */
{ ASSIGN, FOREFF|INAREG,
- SFLD, TANY,
- SAREG, TANY,
+ SOREG, TFLOAT,
+ SAREG, TFLOAT,
+ 0, RDEST,
+ " stw AR,AL" COM "store float (soft-float)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SNAME, TFLOAT,
+ SCREG, TFLOAT,
NAREG, RDEST,
- "ZE", },
+ " lis A1," HA16(AL) "\n"
+ " stfs AR," LO16(AL) "(A1)\n", },
-{ ASSIGN, FOREFF,
- SFLD, TANY,
- SAREG, TANY,
- NAREG, 0,
- "ZE", },
-#endif
+/* soft-float */
+{ ASSIGN, FOREFF|INAREG,
+ SNAME, TFLOAT,
+ SAREG, TFLOAT,
+ NAREG, RDEST,
+ " lis A1," HA16(AL) "\n"
+ " stw AR," LO16(AL) "(A1)\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
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SOREG, TFLOAT,
+ 0, RDEST,
+ " lfs AL,AR" COM "load float\n", },
-{ STASG, INAREG|FOREFF,
- SOREG, TANY,
- SAREG, TPTRTO|TANY,
- NSPECIAL, RRIGHT,
- "ZQ", },
+/* soft-float */
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TFLOAT,
+ SOREG, TFLOAT,
+ 0, RDEST,
+ " lwz AL,AR" COM "load float (soft-float)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SNAME, TFLOAT,
+ NAREG, RDEST,
+ " lis A1," HA16(AR) "\n"
+ " lfs AL," LO16(AR) "(A1)\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TFLOAT,
+ SNAME, TFLOAT,
+ NAREG, RDEST,
+ " lis A1," HA16(AR) "\n"
+ " lwz AL," LO16(AR) "(A1)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ 0, RDEST,
+ " fmr AL,AR" COM "assign AR to AL\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ 0, RDEST,
+ " mr AL,AR" COM "assign AR to AL\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SOREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " stfd AR,AL" COM "store (l)double\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INBREG,
+ SOREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " stw AR,AL" COM "store (l)double (soft-float)\n"
+ " stw UR,UL\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SNAME, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NAREG, RDEST,
+ " lis A1," HA16(AL) "\n"
+ " stfd AR," LO16(AL) "(A1)\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INBREG,
+ SNAME, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NAREG, RDEST,
+ " lis A1," HA16(AL) "\n"
+ " stw AR," LO16(AL) "(A1)\n"
+ " lis A1," HA16(UL) "\n"
+ " stw UR," LO16(UL) "(A1)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SOREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " lfd AL,AR" COM "load (l)double\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SOREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " lwz AL,AR" COM "load (l)double (soft-float)\n"
+ " lwz UL,UR\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SNAME, TDOUBLE|TLDOUBLE,
+ NAREG, RDEST,
+ " lis A1," HA16(AR) "\n"
+ " lfd AL," LO16(AR) "(A1)\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SNAME, TDOUBLE|TLDOUBLE,
+ NAREG, RDEST,
+ " lis A1," HA16(AR) "\n"
+ " lwz AL," LO16(AR) "(A1)\n"
+ " lis A1," HA16(UR) "\n"
+ " lwz UL," LO16(UR) "(A1)\n", },
+
+{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fmr AL,AR" COM "assign AR to AL\n", },
+
+/* soft-float */
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " mr AL,AR" COM "assign AR to AL\n"
+ " mr UL,UR\n", },
/*
* DIV/MOD/MUL
*/
{ DIV, INAREG,
- SAREG, TSWORD,
- SAREG, TWORD,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
NAREG|NASL, RESC1,
- " divw A1,AL,AR\n", },
+ " divwu A1,AL,AR\n", },
+
+{ DIV, INAREG|FORCC,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ NAREG|NASL, RESC1|RESCC,
+ " divwu. A1,AL,AR\n", },
{ DIV, INAREG,
- SAREG, TUWORD|TPOINT,
- SAREG, TUWORD|TPOINT,
+ SAREG, TWORD|TSHORT|TCHAR,
+ SAREG, TWORD|TSHORT|TCHAR,
NAREG|NASL, RESC1,
- " divwu A1,AL,AR\n", },
+ " divw A1,AL,AR\n", },
+
+{ DIV, INAREG|FORCC,
+ SAREG, TWORD|TSHORT|TCHAR,
+ SAREG, TWORD|TSHORT|TCHAR,
+ NAREG|NASL, RESC1|RESCC,
+ " divw. A1,AL,AR\n", },
+
+{ DIV, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TLONGLONG|TULONGLONG,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
+
+{ DIV, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG|NCSR, RESC1,
+ " fdivs A1,AL,AR" COM "float divide\n", },
+
+/* soft-float */
+{ DIV, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ DIV, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSR, RESC1,
+ " fdiv A1,AL,AR" COM "(l)double divide\n", },
+
+/* soft-float */
+{ DIV, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
{ MOD, INAREG,
- SAREG, TSWORD,
- SAREG, TSWORD,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
NAREG, RESC1,
- " divw A1,AL,AR" COM "signed modulo\n"
+ " divwu A1,AL,AR" COM "unsigned modulo\n"
" mullw A1,A1,AR\n"
" subf A1,A1,AL\n", },
{ MOD, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG, TUWORD|TPOINT,
+ SAREG, TWORD|TSHORT|TCHAR,
+ SAREG, TWORD|TSHORT|TCHAR,
NAREG, RESC1,
- " divwu A1,AL,AR" COM "unsigned modulo\n"
+ " divw A1,AL,AR" COM "signed modulo\n"
" mullw A1,A1,AR\n"
" subf A1,A1,AL\n", },
+{ MOD, INBREG,
+ SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TLONGLONG|TULONGLONG,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
+
{ MUL, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
NAREG|NASL, RESC1,
" mulli A1,AL,AR\n", },
+{ MUL, INAREG|FORCC,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SSCON, TANY,
+ NAREG|NASL, RESC1|RESCC,
+ " mulli. A1,AL,AR\n", },
+
{ MUL, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
" mullw A1,AL,AR\n", },
+{ MUL, INAREG|FORCC,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASL, RESC1|RESCC,
+ " mullw. A1,AL,AR\n", },
+
{ MUL, INBREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
@@ -794,49 +1227,106 @@ struct optab table[] = {
" mullw A1,AL,AR\n"
" mulhw U1,AL,AR\n", },
+{ MUL, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG|NCSR, RESC1,
+ " fmuls A1,AL,AR" COM "float multiply\n", },
+
+/* soft-float */
+{ MUL, INAREG,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL|NAREG, RESC1,
+ "ZF", },
+
+{ MUL, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TDOUBLE|TLDOUBLE,
+ SCREG, TDOUBLE|TLDOUBLE,
+ NCREG|NCSR, RESC1,
+ " fmul A1,AL,AR" COM "(l)double multiply\n", },
+
+/* soft-float */
+{ MUL, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ "ZF", },
+
/*
* Indirection operators.
*/
{ UMUL, INAREG,
SANY, TANY,
- SOREG, TWORD|TPOINT,
+ SOREG|SNAME, TWORD|TPOINT,
NAREG|NSPECIAL, RESC1,
" lwz A1,AL" COM "word load\n", },
{ UMUL, INAREG,
SANY, TANY,
- SOREG, TCHAR,
+ SOREG|SNAME, TCHAR,
NAREG|NSPECIAL, RESC1,
" lbz A1,AL" COM "char load\n"
" extsb A1,A1\n", },
{ UMUL, INAREG,
SANY, TANY,
- SOREG, TUCHAR,
+ SOREG|SNAME, TUCHAR,
NAREG|NSPECIAL, RESC1,
" lbz A1,AL" COM "uchar load\n", },
{ UMUL, INAREG,
SANY, TANY,
- SOREG, TSHORT,
+ SOREG|SNAME, TSHORT,
NAREG|NSPECIAL, RESC1,
" lha A1,AL" COM "short load\n", },
{ UMUL, INAREG,
SANY, TANY,
- SOREG, TUSHORT,
+ SOREG|SNAME, TUSHORT,
NAREG|NSPECIAL, RESC1,
" lhz A1,AL" COM "ushort load\n", },
{ UMUL, INBREG,
SANY, TANY,
- SOREG, TLONGLONG|TULONGLONG,
- NBREG, RESC1,
+ SOREG|SNAME, TLONGLONG|TULONGLONG,
+ NBREG, RESC1,
" lwz A1,AL" COM "64-bit load\n"
" lwz U1,UL\n", },
-/* XXX UMUL of SNAME and AREG !!! */
+{ UMUL, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NCREG, RESC1,
+ " lfs A1,AL" COM "float load\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NAREG, RESC1,
+ " lwz A1,AL" COM "float load (soft-float)\n", },
+
+{ UMUL, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
+ " lfd A1,AL" COM "(l)double load\n", },
+
+{ UMUL, INBREG,
+ SANY, TANY,
+ SOREG|SNAME, TDOUBLE|TLDOUBLE,
+ NSPECIAL|NBREG, RESC1,
+ " lwz A1,AL" COM "(l)double load (soft-float)\n"
+ " lwz U1,UL\n", },
+
+#if 0
+{ UMUL, INAREG,
+ SANY, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG, RESC1,
+ " lwz A1,(AL)" COM "word load\n", },
+#endif
/*
* Logical/branching operators
@@ -865,8 +1355,8 @@ struct optab table[] = {
/* compare with register */
{ OPLOG, FORCC,
- SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
- SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
0, RESCC,
" cmplw AL,AR\n", },
@@ -874,9 +1364,30 @@ struct optab table[] = {
{ OPLOG, FORCC,
SBREG, TLONGLONG|TULONGLONG,
SBREG, TLONGLONG|TULONGLONG,
- 0, 0,
+ 0, RESCC,
"ZD", },
+/* compare with register */
+{ OPLOG, FORCC | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RESCC,
+ " fcmpu 0,AL,AR\n", },
+
+/* soft-float */
+{ OPLOG, FORCC,
+ SAREG, TFLOAT,
+ SAREG, TFLOAT,
+ NSPECIAL, RESCC,
+ "ZF\n", },
+
+/* soft-float */
+{ OPLOG, FORCC,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SBREG, TDOUBLE|TLDOUBLE,
+ NSPECIAL, RESCC,
+ "ZF", },
+
{ OPLOG, FORCC,
SANY, TANY,
SANY, TANY,
@@ -885,20 +1396,20 @@ struct optab table[] = {
/* AND/OR/ER */
{ AND, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" and A1,AL,AR\n", },
{ AND, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" and. A1,AL,AR\n", },
/* AR must be positive */
{ AND, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SPCON, TANY,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" andi. A1,AL,AR\n", },
@@ -918,27 +1429,27 @@ struct optab table[] = {
" li U1,0\n" },
{ OR, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" or A1,AL,AR\n", },
{ OR, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" or. A1,AL,AR\n", },
{ OR, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR,
- SSCON, TANY,
- NAREG|NASL|NSPECIAL, RESC1,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
" ori A1,AL,AR\n", },
{ OR, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR,
- SSCON, TANY,
- NAREG|NASL|NSPECIAL, RESC1|RESCC,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SPCON, TANY,
+ NAREG|NASL, RESC1|RESCC,
" ori. A1,AL,AR\n", },
{ OR, INBREG,
@@ -950,37 +1461,37 @@ struct optab table[] = {
{ OR, INBREG,
SBREG, TLONGLONG|TULONGLONG,
- SSCON, TANY,
+ SPCON, TANY,
NBREG|NBSL, RESC1,
" ori A1,AL,AR" COM "64-bit or with constant\n" },
{ OR, INBREG|FORCC,
SBREG, TLONGLONG|TULONGLONG,
- SSCON, TANY,
+ SPCON, TANY,
NBREG|NBSL, RESC1|RESCC,
" ori. A1,AL,AR" COM "64-bit or with constant\n" },
{ ER, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1,
" xor A1,AL,AR\n", },
{ ER, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" xor. A1,AL,AR\n", },
{ ER, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR,
- SSCON, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SPCON, TANY,
NAREG|NASL|NSPECIAL, RESC1,
" xori A1,AL,AR\n", },
{ ER, INAREG|FORCC,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR,
- SSCON, TANY,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SPCON, TANY,
NAREG|NASL|NSPECIAL, RESC1|RESCC,
" xori. A1,AL,AR\n", },
@@ -993,13 +1504,13 @@ struct optab table[] = {
{ ER, INBREG,
SBREG, TLONGLONG|TULONGLONG,
- SSCON, TANY,
+ SPCON, TANY,
NBREG|NBSL, RESC1,
" xori A1,AL,AR" COM "64-bit xor with constant\n" },
{ ER, INBREG|FORCC,
SBREG, TLONGLONG|TULONGLONG,
- SSCON, TANY,
+ SPCON, TANY,
NBREG|NBSL, RESC1|RESCC,
" xori. A1,AL,AR" COM "64-bit xor with constant\n" },
@@ -1023,6 +1534,14 @@ struct optab table[] = {
* Convert LTYPE to reg.
*/
+#if defined(ELFABI)
+{ OPLTYPE, INAREG | FEATURE_PIC,
+ SANY, TANY,
+ SNAME, TANY,
+ NAREG, RESC1,
+ " lwz A1,AL" COM "elfabi pic load\n", },
+#endif
+
{ OPLTYPE, INBREG,
SANY, TANY,
SOREG, TLONGLONG|TULONGLONG,
@@ -1039,14 +1558,12 @@ struct optab table[] = {
" lis U1," HA16(UL) "\n"
" lwz U1," LO16(UL) "(U1)\n", },
-/* load word from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
- SOREG, TWORD|TPOINT,
+ SOREG, TWORD|TPOINT,
NAREG, RESC1,
" lwz A1,AL" COM "load word from memory\n", },
-/* load word from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TWORD|TPOINT,
@@ -1054,7 +1571,6 @@ struct optab table[] = {
" lis A1," HA16(AL) COM "load word from sname\n"
" lwz A1," LO16(AL) "(A1)\n", },
-/* load char from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SOREG, TCHAR,
@@ -1062,7 +1578,6 @@ struct optab table[] = {
" lbz A1,AL" COM "load char from memory\n"
" extsb A1,A1\n", },
-/* load char from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TCHAR,
@@ -1071,14 +1586,12 @@ struct optab table[] = {
" lbz A1," LO16(AL) "(A1)\n"
" extsb A1,A1\n", },
-/* load uchar from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SOREG, TUCHAR,
NAREG, RESC1,
" lbz A1,AL" COM "load uchar from memory\n", },
-/* load uchar from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TUCHAR,
@@ -1093,14 +1606,12 @@ struct optab table[] = {
NAREG, RESC1,
" lha A1,AL" COM "load short from memory\n", },
-/* load ushort from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SOREG, TUSHORT,
NAREG, RESC1,
" lhz A1,AL" COM "load ushort from memory\n", },
-/* load short from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TSHORT,
@@ -1108,7 +1619,6 @@ struct optab table[] = {
" lis A1," HA16(AL) COM "load short from sname\n"
" lha A1," LO16(AL) "(A1)\n", },
-/* load ushort from memory */
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TUSHORT,
@@ -1116,14 +1626,12 @@ struct optab table[] = {
" lis A1," HA16(AL) COM "load ushort from sname\n"
" lhz A1," LO16(AL) "(A1)\n", },
-/* load from 16-bit constant */
{ OPLTYPE, INAREG,
SANY, TANY,
SSCON, TANY,
NAREG, RESC1,
" li A1,AL" COM "load 16-bit constant\n", },
-/* load from 16-bit constant */
{ OPLTYPE, INBREG,
SANY, TANY,
SSCON, TANY,
@@ -1131,15 +1639,13 @@ struct optab table[] = {
" li A1,AL" COM "load 16-bit constant\n"
" li U1,UL\n", },
-/* load from constant */
{ OPLTYPE, INAREG,
SANY, TANY,
SCON, TANY,
- NAREG|NASL|NSPECIAL, RESC1,
+ NAREG|NASL, RESC1,
" lis A1," HA16(AL) COM "load constant into register\n"
" addi A1,A1," LO16(AL) "\n", },
-/* load from constant */
{ OPLTYPE, INBREG,
SANY, TANY,
SCON, TANY,
@@ -1149,21 +1655,84 @@ struct optab table[] = {
" lis U1," HA16(UL) "\n"
" addi U1,U1," LO16(UL) "\n", },
-/* load from register */
{ OPLTYPE, INAREG,
SANY, TANY,
SAREG, TANY,
NAREG, RESC1,
" mr A1,AL" COM "load AL into A1\n" },
-/* load from register */
{ OPLTYPE, INBREG,
SANY, TANY,
- SBREG, TLONGLONG|TULONGLONG,
+ SBREG, TANY,
NBREG, RESC1,
" mr A1,AL" COM "load UL:AL into U1:A1\n"
" mr U1,UL\n", },
+{ OPLTYPE, INCREG,
+ SANY, TANY,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
+ " fmr A1,AL" COM "load AL into A1\n", },
+
+{ OPLTYPE, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NCREG, RESC1,
+ " lfs A1,AL" COM "load float\n", },
+
+/* soft-float */
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NAREG, RESC1,
+ " lwz A1,AL" COM "load float (soft-float)\n", },
+
+{ OPLTYPE, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SNAME, TFLOAT,
+ NCREG|NAREG, RESC2,
+ " lis A1," HA16(AL) COM "load sname\n"
+ " lfs A2," LO16(AL) "(A1)\n", },
+
+/* soft-float */
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SNAME, TFLOAT,
+ NAREG, RESC1,
+ " lis A1," HA16(AL) COM "load sname (soft-float)\n"
+ " lwz A1," LO16(AL) "(A1)\n", },
+
+{ OPLTYPE, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SOREG, TDOUBLE|TLDOUBLE,
+ NCREG, RESC1,
+ " lfd A1,AL" COM "load (l)double\n", },
+
+/* soft-float */
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SOREG, TDOUBLE|TLDOUBLE,
+ NBREG, RESC1,
+ " lwz A1,AL" COM "load (l)double (soft-float)\n"
+ " lwz U1,UL\n", },
+
+{ OPLTYPE, INCREG | FEATURE_HARDFLOAT,
+ SANY, TANY,
+ SNAME, TDOUBLE|TLDOUBLE,
+ NCREG|NAREG, RESC2,
+ " lis A1," HA16(AL) COM "load sname\n"
+ " lfd A2," LO16(AL) "(A1)\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SNAME, TDOUBLE|TLDOUBLE,
+ NBREG, RESC1,
+ " lis A1," HA16(AL) COM "load sname (soft-float)\n"
+ " lwz A1," LO16(AL) "(A1)\n"
+ " lis U1," HA16(UL) "\n"
+ " lwz U1," LO16(UL) "(U1)\n", },
+
+
/*
* Negate a word.
*/
@@ -1181,6 +1750,25 @@ struct optab table[] = {
" subfic A1,AL,0\n"
" subfze U1,UL\n", },
+{ UMINUS, INCREG | FEATURE_HARDFLOAT,
+ SCREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ SANY, TANY,
+ NCREG|NCSL, RESC1,
+ " fneg A1,AL\n", },
+
+{ UMINUS, INAREG,
+ SAREG, TFLOAT,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " xoris A1,AL,0x8000" COM "(soft-float)\n", },
+
+{ UMINUS, INBREG,
+ SBREG, TDOUBLE|TLDOUBLE,
+ SANY, TANY,
+ NBREG|NBSL, RESC1,
+ " xoris U1,UL,0x8000" COM "(soft-float)\n"
+ " mr A1,AL\n", },
+
{ COMPL, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
SANY, TANY,
@@ -1199,48 +1787,6 @@ struct optab table[] = {
*/
#if 0
-{ 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", },
-#endif
-
-{ FUNARG, FOREFF,
- SAREG|SNAME|SOREG, TUSHORT,
- SANY, TUSHORT,
- NAREG, 0,
- " movzwl AL,ZN\n pushl ZN\n", },
-
-#if 0
-{ FUNARG, FOREFF,
- SHCH|SNAME|SOREG, TCHAR,
- SANY, TCHAR,
- NAREG, 0,
- " movsbl AL,A1\n pushl A1\n", },
-#endif
-
-#if 0
-{ FUNARG, FOREFF,
- SHCH|SNAME|SOREG, TUCHAR,
- SANY, TUCHAR,
- NAREG, 0,
- " movzbl AL,A1\n pushl A1\n", },
-#endif
-
-#if 0
{ STARG, FOREFF,
SAREG|SOREG|SNAME|SCON, TANY,
SANY, TSTRUCT,
diff --git a/usr.bin/pcc/sparc64/code.c b/usr.bin/pcc/sparc64/code.c
index 442077844b3..a22c306de66 100644
--- a/usr.bin/pcc/sparc64/code.c
+++ b/usr.bin/pcc/sparc64/code.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: code.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -31,7 +32,16 @@ defloc(struct symtab *sp)
lastloc = s;
if (s == PROG)
return;
- printf("\t.align 4\n");
+
+ switch (DEUNSIGN(sp->stype)) {
+ case CHAR: s = 1;
+ case SHORT: s = 2;
+ case INT:
+ case UNSIGNED: s = 4;
+ default: s = 8;
+ }
+ printf("\t.align %d\n", s);
+
if (sp->sclass == EXTDEF)
printf("\t.global %s\n", sp->soname);
if (sp->slevel == 0) {
@@ -52,14 +62,15 @@ efcode()
void
bfcode(struct symtab **sp, int cnt)
{
- int i;
+ int i, off;
NODE *p, *q;
struct symtab *sym;
- for (i=0; i < cnt && i < I7 - I0; i++) {
+ /* Process the first six arguments. */
+ for (i=0; i < cnt && i < 6; i++) {
sym = sp[i];
q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue);
- q->n_rval = i + I0;
+ q->n_rval = RETREG_PRE(sym->stype) + i;
p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
sym->soffset = regno(p);
sym->sflags |= STNODE;
@@ -67,8 +78,19 @@ bfcode(struct symtab **sp, int cnt)
ecomp(p);
}
- if (i < cnt)
- cerror("unprocessed arguments in bfcode"); /* TODO */
+ /* Process the remaining arguments. */
+ for (off = V9RESERVE; i < cnt; i++) {
+ sym = sp[i];
+ spname = sym;
+ p = tempnode(0, sym->stype, sym->sdf, sym->ssue);
+ off = ALIGN(off, (tlen(p) - 1));
+ sym->soffset = off * SZCHAR;
+ off += tlen(p);
+ p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0));
+ sym->soffset = regno(p->n_left);
+ sym->sflags |= STNODE;
+ ecomp(p);
+ }
}
void
@@ -87,30 +109,55 @@ bjobcode()
{
}
+/*
+ * The first six 64-bit arguments are saved in the registers O0 to O5,
+ * which become I0 to I5 after the "save" instruction moves the register
+ * window. Arguments 7 and up must be saved on the stack to %sp+BIAS+176.
+ *
+ * For a pretty picture, see Figure 3-16 in the SPARC Compliance Def 2.4.
+ */
static NODE *
-moveargs(NODE *p, int *regp)
+moveargs(NODE *p, int *regp, int *stacksize)
{
NODE *r, *q;
if (p->n_op == CM) {
- p->n_left = moveargs(p->n_left, regp);
+ p->n_left = moveargs(p->n_left, regp, stacksize);
r = p->n_right;
} else {
r = p;
}
- if (*regp > I7 && r->n_op != STARG)
- cerror("reg > I7 in moveargs"); /* TODO */
- else if (r->n_op == STARG)
+ /* XXX more than six FP args can and should be passed in registers. */
+ if (*regp > 5 && r->n_op != STARG) {
+ /* We are storing the stack offset in n_rval. */
+ r = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue);
+ /* Make sure we are appropriately aligned. */
+ *stacksize = ALIGN(*stacksize, (tlen(r) - 1));
+ r->n_rval = *stacksize;
+ *stacksize += tlen(r);
+ } else if (r->n_op == STARG)
cerror("op STARG in moveargs");
- else if (r->n_type == DOUBLE || r->n_type == LDOUBLE)
- cerror("FP in moveargs");
- else if (r->n_type == FLOAT)
- cerror("FP in moveargs");
else {
- /* Argument can fit in O0...O7. */
q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
- q->n_rval = (*regp)++;
+
+ /*
+ * The first six non-FP arguments go in the registers O0 - O5.
+ * Float arguments are stored in %fp1, %fp3, ..., %fp29, %fp31.
+ * Double arguments are stored in %fp0, %fp2, ..., %fp28, %fp30.
+ * A non-fp argument still increments register, eg.
+ * test(int a, int b, float b)
+ * takes %o0, %o1, %fp5.
+ */
+ if (q->n_type == FLOAT)
+ q->n_rval = F0 + (*regp++ * 2) + 1;
+ else if (q->n_type == DOUBLE)
+ q->n_rval = D0 + *regp++;
+ else if (q->n_type == LDOUBLE)
+ cerror("long double support incomplete");
+ else
+ q->n_rval = O0 + (*regp)++;
+
r = buildtree(ASSIGN, q, r);
}
@@ -125,8 +172,51 @@ moveargs(NODE *p, int *regp)
NODE *
funcode(NODE *p)
{
- int reg = O0;
- p->n_right = moveargs(p->n_right, &reg);
+ NODE *r, *l;
+ int reg = 0, stacksize = 0;
+
+ r = l = 0;
+
+ p->n_right = moveargs(p->n_right, &reg, &stacksize);
+
+ /*
+ * This is a particularly gross and inefficient way to handle
+ * argument overflows. First, we calculate how much stack space
+ * we need in moveargs(). Then we assign it by moving %sp, make
+ * the function call, and then move %sp back.
+ *
+ * What we should be doing is getting the maximum of all the needed
+ * stacksize values to the prologue and doing it all in the "save"
+ * instruction.
+ */
+ if (stacksize != 0) {
+ stacksize = V9STEP(stacksize); /* 16-bit alignment. */
+
+ r = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0;
+ r->n_rval = SP;
+ r = block(MINUS, r, bcon(stacksize), INT, 0, MKSUE(INT));
+
+ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ l->n_lval = 0;
+ l->n_rval = SP;
+ r = buildtree(ASSIGN, l, r);
+
+ p = buildtree(COMOP, r, p);
+
+ r = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_lval = 0;
+ r->n_rval = SP;
+ r = block(PLUS, r, bcon(stacksize), INT, 0, MKSUE(INT));
+
+ l = block(REG, NIL, NIL, INT, 0, MKSUE(INT));
+ l->n_lval = 0;
+ l->n_rval = SP;
+ r = buildtree(ASSIGN, l, r);
+
+ p = buildtree(COMOP, p, r);
+
+ }
return p;
}
diff --git a/usr.bin/pcc/sparc64/local.c b/usr.bin/pcc/sparc64/local.c
index a1a002933db..956013c2c99 100644
--- a/usr.bin/pcc/sparc64/local.c
+++ b/usr.bin/pcc/sparc64/local.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: local.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -50,9 +51,11 @@ clocal(NODE *p)
p = stref(block(STREF, l, r, 0, 0, 0));
}
break;
- case PCONV:
- if (p->n_type > BTMASK && l->n_type > BTMASK) {
- /* Remove unnecessary pointer conversions. */
+ case PCONV: /* Remove what PCONVs we can. */
+ if (l->n_op == SCONV)
+ break;
+
+ if (l->n_op == ICON || (ISPTR(p->n_type) && ISPTR(l->n_type))) {
l->n_type = p->n_type;
l->n_qual = p->n_qual;
l->n_df = p->n_df;
@@ -68,7 +71,8 @@ clocal(NODE *p)
(l->n_type & TMASK) == 0 &&
btdims[p->n_type].suesize ==
btdims[l->n_type].suesize) {
- /* XXX: skip if FP? */
+ if (p->n_type == FLOAT || p->n_type == DOUBLE)
+ break;
l->n_type = p->n_type;
nfree(p);
p = l;
@@ -92,12 +96,18 @@ clocal(NODE *p)
case UCHAR: l->n_lval = l->n_lval & 0377; break;
case SHORT: l->n_lval = (short)l->n_lval; break;
case USHORT: l->n_lval = l->n_lval & 0177777; break;
- case UNSIGNED:
- case ULONG: l->n_lval = l->n_lval & 0xffffffff; break;
- case LONG:
+ case UNSIGNED: l->n_lval = l->n_lval & 0xffffffff; break;
case INT: l->n_lval = (int)l->n_lval; break;
+ case ULONG:
case ULONGLONG: l->n_lval = l->n_lval; break;
+ case LONG:
case LONGLONG: l->n_lval = (long long)l->n_lval; break;
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+ l->n_op = FCON;
+ l->n_dcon = l->n_lval;
+ break;
case VOID:
break;
default:
@@ -122,7 +132,7 @@ clocal(NODE *p)
p->n_op = ASSIGN;
p->n_right = p->n_left;
p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
- p->n_left->n_rval = I0; /* XXX adjust for float/double */
+ p->n_left->n_rval = RETREG_PRE(p->n_type);
break;
}
@@ -139,6 +149,25 @@ clocal(NODE *p)
void
myp2tree(NODE *p)
{
+ struct symtab *sp;
+
+ if (p->n_op != FCON)
+ return;
+
+ sp = tmpalloc(sizeof(struct symtab));
+ sp->sclass = STATIC;
+ sp->slevel = 1;
+ sp->soffset = getlab();
+ sp->sflags = 0;
+ sp->stype = p->n_type;
+ sp->squal = (CON >> TSHIFT);
+
+ defloc(sp);
+ ninval(0, btdims[p->n_type].suesize, p);
+
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = sp;
}
int
@@ -186,7 +215,7 @@ instring(struct symtab *sp)
printf("\t.ascii \"");
for (s = str; *s != 0; *s++) {
- if (*s == '\\')
+ if (*s++ == '\\')
esccon(&s);
if (s - str > 60) {
fwrite(str, 1, s - str, stdout);
@@ -211,29 +240,58 @@ infld(CONSZ off, int fsz, CONSZ val)
void
ninval(CONSZ off, int fsz, NODE *p)
{
+ TWORD t;
+ struct symtab *sp;
+ union { float f; double d; int i; long long l; } u;
+
+ t = p->n_type;
+ sp = p->n_sp;
+
+ if (ISPTR(t))
+ t = LONGLONG;
+
if (p->n_op != ICON && p->n_op != FCON)
cerror("ninval: not a constant");
- if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(p->n_type) != INT)
+ if (p->n_op == ICON && sp != NULL && DEUNSIGN(t) != LONGLONG)
cerror("ninval: not constant");
- switch (DEUNSIGN(p->n_type)) {
+ switch (t) {
case CHAR:
- printf("\t.align 1\n");
+ case UCHAR:
printf("\t.byte %d\n", (int)p->n_lval & 0xff);
break;
case SHORT:
- printf("\t.align 2\n");
+ case USHORT:
printf("\t.half %d\n", (int)p->n_lval &0xffff);
break;
case BOOL:
p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */
case INT:
- printf("\t.align 4\n\t.long " CONFMT "\n", p->n_lval);
+ case UNSIGNED:
+ printf("\t.long " CONFMT "\n", p->n_lval);
break;
+ case LONG:
+ case ULONG:
case LONGLONG:
- printf("\t.align 8\n\t.xword %lld\n", p->n_lval);
+ case ULONGLONG:
+ printf("\t.xword %lld", p->n_lval);
+ if (sp != 0) {
+ if ((sp->sclass == STATIC && sp->slevel > 0)
+ || sp->sclass == ILABEL)
+ printf("+" LABFMT, sp->soffset);
+ else
+ printf("+%s", exname(sp->soname));
+ }
+ printf("\n");
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.long %d\n", u.i);
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ printf("\t.xword %lld\n", u.l);
break;
- /* TODO FP float and double */
}
}
diff --git a/usr.bin/pcc/sparc64/local2.c b/usr.bin/pcc/sparc64/local2.c
index 179a7c78af5..8f7baf49cc5 100644
--- a/usr.bin/pcc/sparc64/local2.c
+++ b/usr.bin/pcc/sparc64/local2.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: local2.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -17,13 +18,6 @@
#include "pass1.h"
#include "pass2.h"
-/*
- * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm
- * means we can use a signed 13-bit constant (simm13). This gives us a
- * shortcut for small constants, instead of loading them into a register.
- * Special handling is required because 13 bits lies between SSCON and SCON.
- */
-#define SIMM13(val) (val < 4096 && val > -4097)
char *
rnames[] = {
@@ -33,13 +27,16 @@ rnames[] = {
"\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7",
"\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7",
- "\%sp", "\%fp",
-
"\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7",
"\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15",
"\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23",
- "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30"
+ "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30",
/*, "\%f31" XXX removed due to 31-element class limit */
+
+ "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14",
+ "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30",
+
+ "\%sp", "\%fp",
};
void
@@ -53,22 +50,22 @@ prologue(struct interpass_prolog *ipp)
{
int i, stack;
- /*
- * SPARCv9 has a 2047 bit stack bias. Looking at output asm from gcc
- * suggests this means we need a base 192 bit offset for %sp. Further
- * steps need to be 8-byte aligned.
- */
- stack = 192 + p2maxautooff + (p2maxautooff % 8);
+ stack = V9RESERVE + V9STEP(p2maxautooff);
for (i=ipp->ipp_regs; i; i >>= 1)
if (i & 1)
- stack += 8;
+ stack += 16;
/* TODO printf("\t.proc %d\n"); */
printf("\t.global %s\n", ipp->ipp_name);
printf("\t.align 4\n");
printf("%s:\n", ipp->ipp_name);
- printf("\tsave %%sp,-%d,%%sp\n", stack);
+ if (SIMM13(stack))
+ printf("\tsave %%sp,-%d,%%sp\n", stack);
+ else {
+ printf("\tsetx -%d,%%g4,%%g1\n", stack);
+ printf("\tsave %%sp,%%g1,%%sp\n");
+ }
}
void
@@ -119,13 +116,15 @@ tlen(NODE *p)
case SHORT:
case USHORT:
return (SZSHORT / SZCHAR);
+ case FLOAT:
+ return (SZFLOAT / SZCHAR);
case DOUBLE:
return (SZDOUBLE / SZCHAR);
case INT:
case UNSIGNED:
+ return (SZINT / SZCHAR);
case LONG:
case ULONG:
- return (SZINT / SZCHAR);
case LONGLONG:
case ULONGLONG:
return SZLONGLONG / SZCHAR;
@@ -139,42 +138,85 @@ tlen(NODE *p)
void
zzzcode(NODE * p, int c)
{
+ char *str;
+ NODE *l, *r;
+ l = p->n_left;
+ r = p->n_right;
+
switch (c) {
- case 'A': /* Load constant to register. */
- if (!ISPTR(p->n_type) && SIMM13(p->n_lval))
- expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n");
- else {
+ case 'A': /* Add const. */
+ if (ISPTR(l->n_type) && l->n_rval == FP)
+ r->n_lval += V9BIAS;
+
+ if (SIMM13(r->n_lval))
+ expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n");
+ else
+ expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n"
+ "\tadd AL,A2,A1\n");
+ break;
+ case 'B': /* Subtract const. */
+ if (ISPTR(l->n_type) && l->n_rval == FP)
+ r->n_lval -= V9BIAS;
+
+ if (SIMM13(r->n_lval))
+ expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n");
+ else
+ expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n"
+ "\tsub AL,A2,A1\n");
+ break;
+ case 'C': /* Load constant to register. */
+ if (ISPTR(p->n_type))
expand(p, 0,
- "\tsethi %h44(AL),A1\t\t! load const\n"
+ "\tsethi %h44(AL),A1\t\t! load label\n"
"\tor A1,%m44(AL),A1\n"
"\tsllx A1,12,A1\n"
"\tor A1,%l44(AL),A1\n");
- }
+ else if (SIMM13(p->n_lval))
+ expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n");
+ else
+ expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n");
break;
- case 'B': /* Subtract const, store in temp. */
- /*
- * If we are dealing with a stack location, SPARCv9 has a
- * stack offset of +2047 bits. This is mostly handled by
- * notoff(), but when passing as an argument this op is used.
- */
- if (ISPTR(p->n_left->n_type) && p->n_left->n_rval == FP)
- p->n_right->n_lval -= 2047;
-
- if (SIMM13(p->n_right->n_lval))
- expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const");
- else {
- expand(p, 0,
- "\tsethi %h44(AR),%g1\t\t! subtract const\n"
- "\tor %g1,%m44(AR),%g1\n"
- "\tsllx %g1,12,%g1\n"
- "\tor %g1,%l44(AR),%g1\n"
- "\tsub AL,%g1,A1\n");
+ case 'F': /* Floating-point comparison, cf. hopcode(). */
+ switch (p->n_op) {
+ case EQ: str = "fbe"; break;
+ case NE: str = "fbne"; break;
+ case ULE:
+ case LE: str = "fbule"; break;
+ case ULT:
+ case LT: str = "fbul"; break;
+ case UGE:
+ case GE: str = "fbuge"; break;
+ case UGT:
+ case GT: str = "fbug"; break;
+ /* XXX
+ case PLUS: str = "add"; break;
+ case MINUS: str = "sub"; break;
+ case AND: str = "and"; break;
+ case OR: str = "or"; break;
+ case ER: str = "xor"; break;*/
+ default:
+ comperr("unknown float code: %d", p->n_op);
+ return;
}
+ printf(str);
+ break;
+
+ case 'Q': /* Structure assignment. */
+ /* TODO Check if p->n_stsize is small and use a few ldx's
+ to move the struct instead of memcpy. The equiv.
+ could be done on all the architectures. */
+ if (l->n_rval != O0)
+ printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]);
+ if (SIMM13(p->n_stsize))
+ printf("\tor %%g0,%d,%%o2\n", p->n_stsize);
+ else
+ printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize);
+ printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n");
+ printf("\tnop\n");
break;
default:
cerror("unknown zzzcode call: %c", c);
-
}
}
@@ -219,13 +261,10 @@ conput(FILE * fp, NODE * p)
if (p->n_name[0] != '\0') {
fprintf(fp, "%s", p->n_name);
- if (p->n_lval < 0) {
- comperr("conput: negative offset (%lld) on label %s\n",
- p->n_lval, p->n_name);
- return;
- }
+ if (p->n_lval > 0)
+ fprintf(fp, "+");
if (p->n_lval)
- fprintf(fp, "+%lld", p->n_lval);
+ fprintf(fp, "%lld", p->n_lval);
} else
fprintf(fp, CONFMT, p->n_lval);
}
@@ -268,9 +307,10 @@ adrput(FILE * io, NODE * p)
return;
case OREG:
fprintf(io, "%s", rnames[p->n_rval]);
- /* SPARCv9 stack bias adjustment. */
if (p->n_rval == FP)
- off += 2047;
+ off += V9BIAS;
+ if (p->n_rval == SP)
+ off += V9BIAS + V9RESERVE;
if (off > 0)
fprintf(io, "+");
if (off)
@@ -280,11 +320,13 @@ adrput(FILE * io, NODE * p)
/* addressable value of the constant */
conput(io, p);
return;
- case MOVE:
case REG:
fputs(rnames[p->n_rval], io);
return;
-
+ case FUNARG:
+ /* We do something odd and store the stack offset in n_rval. */
+ fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval);
+ return;
default:
comperr("bad address, %s, node %p", copst(p->n_op), p);
return;
@@ -320,7 +362,11 @@ rmove(int s, int d, TWORD t)
int
gclass(TWORD t)
{
- return (t == FLOAT || t == DOUBLE || t == LDOUBLE) ? CLASSC : CLASSA;
+ if (t == FLOAT)
+ return CLASSB;
+ if (t == DOUBLE)
+ return CLASSC;
+ return CLASSA;
}
void
@@ -348,12 +394,17 @@ COLORMAP(int c, int *r)
num += r[CLASSA];
return num < 32;
case CLASSB:
- return 0;
+ num += r[CLASSB];
+ num += 2*r[CLASSC];
+ return num < 32;;
case CLASSC:
num += r[CLASSC];
- return num < 32;
+ num += 2*r[CLASSB];
+ return num < 17;
+ case CLASSD:
+ return 0;
default:
- comperr("COLORMAP: unknown class");
+ comperr("COLORMAP: unknown class: %d", c);
return 0;
}
}
diff --git a/usr.bin/pcc/sparc64/macdefs.h b/usr.bin/pcc/sparc64/macdefs.h
index 3e392233e61..75e4fd0cb80 100644
--- a/usr.bin/pcc/sparc64/macdefs.h
+++ b/usr.bin/pcc/sparc64/macdefs.h
@@ -1,3 +1,4 @@
+/* $OpenBSD: macdefs.h,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -14,6 +15,30 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
+/*
+ * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm
+ * means we can use a signed 13-bit constant (simm13). This gives us a
+ * shortcut for small constants, instead of loading them into a register.
+ * Special handling is required because 13 bits lies between SSCON and SCON.
+ */
+#define SIMM13(val) (val < 4096 && val > -4097)
+
+/*
+ * The SPARCv9 ABI specifies a stack bias of 2047 bits. This means that the
+ * end of our call space is %fp+V9BIAS, working back towards %sp+V9BIAS+176.
+ */
+#define V9BIAS 2047
+
+/*
+ * The ABI requires that every frame reserve 176 bits for saving registers
+ * in the case of a spill. The stack size must be 16-bit aligned.
+ */
+#define V9RESERVE 176
+#define V9STEP(x) ALIGN(x, 0xf)
+#define ALIGN(x, y) ((x & y) ? (x + y) & ~y : x)
+
+
#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
#define ARGINIT (7*8) /* XXX */
@@ -26,7 +51,7 @@
#define SZFLOAT 32
#define SZDOUBLE 64
#define SZLDOUBLE 64
-#define SZLONG 32
+#define SZLONG 64
#define SZSHORT 16
#define SZLONGLONG 64
#define SZPOINT(t) 64
@@ -38,12 +63,12 @@
#define ALFLOAT 32
#define ALDOUBLE 64
#define ALLDOUBLE 64
-#define ALLONG 32
+#define ALLONG 64
#define ALLONGLONG 64
#define ALSHORT 16
-#define ALPOINT 32
+#define ALPOINT 64
#define ALSTRUCT 32
-#define ALSTACK 64
+#define ALSTACK 64
/* Min/max values. */
#define MIN_CHAR -128
@@ -55,12 +80,12 @@
#define MIN_INT -1
#define MAX_INT 0x7fffffff
#define MAX_UNSIGNED 0xffffffff
-#define MIN_LONG MIN_INT
-#define MAX_LONG MAX_INT
-#define MAX_ULONG MAX_UNSIGNED
#define MIN_LONGLONG 0x8000000000000000LL
#define MAX_LONGLONG 0x7fffffffffffffffLL
#define MAX_ULONGLONG 0xffffffffffffffffULL
+#define MIN_LONG MIN_LONGLONG
+#define MAX_LONG MAX_LONGLONG
+#define MAX_ULONG MAX_ULONGLONG
#define BOOL_TYPE INT
#define WCHAR_TYPE INT
@@ -83,14 +108,15 @@ typedef long long OFFSZ;
#define BYTEOFF(x) ((x)&03)
#define BITOOR(x) (x)
-#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
- (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
+#define szty(t) ((ISPTR(t) || (t) == DOUBLE || \
+ (t) == LONG || (t) == ULONG || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
/* Register names. */
-#define MAXREGS (31 + 2 + 31)
-#define NUMCLASS 3
+#define MAXREGS (31 + 31 + 16 + 2)
+#define NUMCLASS 4
//define G0 -1
#define G1 0
@@ -125,45 +151,62 @@ typedef long long OFFSZ;
#define I6 29
#define I7 30
-#define SP 31
-#define FP 32
-/*
-#define F0 33
-#define F1 34
-#define F2 35
-#define F3 36
-#define F4 37
-#define F5 38
-#define F6 39
-#define F7 40
-#define F8 41
-#define F9 42
-#define F10 43
-#define F11 44
-#define F12 45
-#define F13 46
-#define F14 47
-#define F15 48
-#define F16 49
-#define F17 50
-#define F18 51
-#define F19 52
-#define F20 53
-#define F21 54
-#define F22 55
-#define F23 56
-#define F24 57
-#define F25 58
-#define F26 59
-#define F27 60
-#define F28 61
-#define F29 62
-#define F30 63
-*/
+#define F0 31
+#define F1 32
+#define F2 33
+#define F3 34
+#define F4 35
+#define F5 36
+#define F6 37
+#define F7 38
+#define F8 39
+#define F9 40
+#define F10 41
+#define F11 42
+#define F12 43
+#define F13 44
+#define F14 45
+#define F15 46
+#define F16 47
+#define F17 48
+#define F18 49
+#define F19 50
+#define F20 51
+#define F21 52
+#define F22 53
+#define F23 54
+#define F24 55
+#define F25 56
+#define F26 57
+#define F27 58
+#define F28 59
+#define F29 60
+#define F30 61
+//define F31 XXX
+#define D0 62
+#define D1 63
+#define D2 64
+#define D3 65
+#define D4 66
+#define D5 67
+#define D6 68
+#define D7 69
+#define D8 70
+#define D9 71
+#define D10 72
+#define D11 73
+#define D12 74
+#define D13 75
+#define D14 76
+#define D15 77
+
+#define SP 78
+#define FP 79
#define FPREG FP
-#define RETREG(x) ((x)==DOUBLE || (x)==LDOUBLE || (x)==FLOAT ? 33 : O0)
+#define RETREG(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : O0)
+#define RETREG_PRE(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : I0)
#define RSTATUS \
/* global */ \
@@ -178,29 +221,48 @@ typedef long long OFFSZ;
/* in */ \
SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
- /* sp */ 0, \
- /* fp */ 0, \
- /* FP */ \
+ /* 32-bit floating point */ \
SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
- SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG /*, SBREG */
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, /*, SBREG */ \
+ /* 64-bit floating point */ \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ /* sp */ SDREG, \
+ /* fp */ SDREG
#define ROVERLAP \
{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
- { -1 }, { -1 }, \
- { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
- { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
- { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \
- { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 } /*, { -1 } */
+/* 32-bit floating point */ \
+ { D0, -1 }, { D0, -1 }, { D1, -1 }, { D1, -1 }, \
+ { D2, -1 }, { D2, -1 }, { D3, -1 }, { D3, -1 }, \
+ { D4, -1 }, { D4, -1 }, { D5, -1 }, { D5, -1 }, \
+ { D6, -1 }, { D6, -1 }, { D7, -1 }, { D7, -1 }, \
+ { D8, -1 }, { D8, -1 }, { D9, -1 }, { D9, -1 }, \
+ { D10, -1 }, { D10, -1 }, { D11, -1 }, { D11, -1 }, \
+ { D12, -1 }, { D12, -1 }, { D13, -1 }, { D13, -1 }, \
+ { D14, -1 }, { D14, -1 }, { D15, -1 }, /* { D15, -1 }, */ \
+/* 64-bit floating point */ \
+ { F0, F1, -1 }, { F2, F3, -1 }, { F4, F5, -1 }, \
+ { F6, F7, -1 }, { F8, F9, -1 }, { F10, F11, -1 }, \
+ { F12, F13, -1 }, { F14, F15, -1 }, { F16, F17, -1 }, \
+ { F18, F19, -1 }, { F20, F21, -1 }, { F22, F23, -1 }, \
+ { F24, F25, -1 }, { F26, F27, -1 }, { F28, F29, -1 }, \
+ { F30, /* F31, */ -1 }, \
+ { -1 }, \
+ { -1 }
-#define GCLASS(x) (x < 32 ? CLASSA : (x < 34 ? CLASSB : CLASSC))
+#define GCLASS(x) (x <= I7 ? CLASSA : \
+ (x <= F30 ? CLASSB : \
+ (x <= D15 ? CLASSC : \
+ (x == SP || x == FP ? CLASSD : 0))))
#define PCLASS(p) (1 << gclass((p)->n_type))
-#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs XXX */
-#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int XXX */
-#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define DECRA(x,y) (((x) >> (y*7)) & 127)
+#define ENCRA(x,y) ((x) << (7+y*7))
+#define ENCRD(x) (x)
int COLORMAP(int c, int *r);
diff --git a/usr.bin/pcc/sparc64/order.c b/usr.bin/pcc/sparc64/order.c
index 271620937b0..250b67fbf36 100644
--- a/usr.bin/pcc/sparc64/order.c
+++ b/usr.bin/pcc/sparc64/order.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: order.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -74,6 +75,19 @@ setuni(NODE *p, int cookie)
struct rspecial *
nspecial(struct optab *q)
{
+ switch (q->op) {
+ case STASG: {
+ static struct rspecial s[] = {
+ { NEVER, O0 },
+ { NRIGHT, O1 },
+ { NEVER, O2 },
+ { 0 }
+ };
+ return s;
+ }
+ }
+
+ comperr("unknown nspecial %d: %s", q - table, q->cstring);
return 0; /* XXX */
}
diff --git a/usr.bin/pcc/sparc64/table.c b/usr.bin/pcc/sparc64/table.c
index 104ef4d3937..cfa3a7ff6c3 100644
--- a/usr.bin/pcc/sparc64/table.c
+++ b/usr.bin/pcc/sparc64/table.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: table.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */
/*
* Copyright (c) 2008 David Crawshaw <david@zentus.com>
*
@@ -16,170 +17,122 @@
#include "pass2.h"
-#define TUWORD TUNSIGNED|TULONG
-#define TSWORD TINT|TLONG
-#define TWORD TUWORD|TSWORD
+#define TS64 TLONG|TLONGLONG
+#define TU64 TULONG|TULONGLONG|TPOINT
+#define T64 TS64|TU64
struct optab table[] = {
{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* empty */
{ PCONV, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
+ SAREG, T64,
+ SAREG, T64,
0, RLEFT,
" ! convert between word and pointer\n", },
-/* Conversions. TODO: check zeroing on down conversions and signed/unsigned */
+/* Conversions. */
{ SCONV, INAREG,
- SOREG, TCHAR,
- SAREG, TSWORD|TSHORT,
- NAREG, RESC1,
- " ldsb [AL],A1 ! int8->int16/int32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TCHAR,
- SAREG, TUWORD|TUSHORT|TUCHAR,
- NAREG, RESC1,
- " ldub [AL],A1 ! int8 -> uint16/uint32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TUCHAR,
- SAREG, TWORD|TSHORT|TUSHORT,
- NAREG, RESC1,
- " ldub [AL],A1 ! int8 -> (u)int16/(u)int32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TCHAR,
- SAREG, TLONGLONG,
- NAREG, RESC1,
- " ldsb [AL],A1 ! int8 -> int64\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TUCHAR,
- SAREG, TLONGLONG|TULONGLONG,
- NAREG, RESC1,
- " ldub [AL],A1 ! uint8 -> (u)int64\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TSHORT|TUSHORT,
- SAREG, TCHAR,
- NAREG, RESC1,
- " ldsh [AL],A1 ! (u)int16 -> int8\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TSHORT|TUSHORT,
- SAREG, TUCHAR,
- NAREG, RESC1,
- " ldsh [AL],A1 ! (u)int16 -> uint8\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TSHORT,
- SAREG, TSWORD,
- NAREG, RESC1,
- " ldsh [AL],A1 ! int16 -> int32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TSHORT,
- SAREG, TUWORD,
- NAREG, RESC1,
- " lduh [AL],A1 ! int16 -> uint32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TUSHORT,
- SAREG, TWORD,
- NAREG, RESC1,
- " lduh [AL],A1 ! uint16 -> int32\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TSHORT,
- SAREG, TLONGLONG,
- NAREG, RESC1,
- " ldsh [AL],A1 ! int16 -> int64\n"
- " nop\n", },
+ SAREG, T64|TUNSIGNED,
+ SAREG, TINT,
+ NAREG|NASL, RESC1,
+ " sra AL,0,A1 \t\t! (u)int64/32 -> (u)int32\n", },
{ SCONV, INAREG,
- SOREG, TSHORT,
- SAREG, TULONGLONG,
- NAREG, RESC1,
- " lduh [AL],A1 ! int16 -> uint64\n"
- " nop\n", },
+ SAREG, T64|TINT|TUNSIGNED,
+ SAREG, TSHORT,
+ NAREG|NASL, RESC1,
+ " sll AL,16,A1 \t\t! (u)int64/32 -> int16\n"
+ " sra AL,16,A1\n"
+ " sra AL, 0,A1\n", },
{ SCONV, INAREG,
- SOREG, TUSHORT,
- SAREG, TLONGLONG|TULONGLONG,
- NAREG, RESC1,
- " lduh [AL],A1 ! uint16 -> uint64\n"
- " nop\n", },
+ SAREG, T64|TINT|TUNSIGNED,
+ SAREG, TUSHORT,
+ NAREG|NASL, RESC1,
+ " sll AL,16,A1 \t\t! (u)int64/32 -> uint16\n"
+ " srl AL,16,A1\n", },
{ SCONV, INAREG,
- SOREG, TWORD,
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
SAREG, TCHAR,
- NAREG, RESC1,
- " ldsw [AL],A1 ! int32 -> int8\n"
- " nop\n", },
+ NAREG|NASL, RESC1,
+ " sll AL,24,A1 \t\t! (u)int64/32/16 -> int8\n"
+ " sra AL,24,A1\n"
+ " sra AL, 0,A1\n", },
{ SCONV, INAREG,
- SOREG, TWORD,
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
SAREG, TUCHAR,
- NAREG, RESC1,
- " lduw [AL],A1 ! int32 -> uint8\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TWORD,
- SAREG, TSHORT,
- NAREG, RESC1,
- " ldsw [AL],A1 ! int32 -> int16\n"
- " nop\n", },
-
-{ SCONV, INAREG,
- SOREG, TWORD,
- SAREG, TUSHORT,
- NAREG, RESC1,
- " lduw [AL],A1 ! int32 -> uint16\n"
- " nop\n", },
+ NAREG|NASL, RESC1,
+ " and AL,0xff,A1 \t\t! (u)int64/32/16 -> uint8\n", },
{ SCONV, INAREG,
- SOREG, TSWORD,
- SAREG, TLONGLONG|TULONGLONG,
- NAREG, RESC1,
- " ldsw [AL],A1 ! int32 -> (u)int64\n"
- " nop\n", },
+ SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT,
+ SAREG, T64,
+ 0, RLEFT,
+ " \t\t! (u)int64...8 -> (u)int64\n", },
{ SCONV, INAREG,
- SOREG, TUWORD,
- SAREG, TLONGLONG|TULONGLONG,
- NAREG, RESC1,
- " lduw [AL],A1 ! int32 -> (u)int64\n"
- " nop\n", },
+ SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TINT,
+ 0, RLEFT,
+ " \t\t! (u)int16/8 -> int32\n", },
{ SCONV, INAREG,
- SOREG, TLONGLONG|TULONGLONG,
- SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
- NAREG, RESC1,
- " ldx [AL],A1 ! int64 -> (u)int8/16/32\n"
- " nop\n", },
+ SAREG, T64|TINT|TSHORT|TCHAR,
+ SAREG, TUNSIGNED,
+ 0, RLEFT,
+ " srl AL, 0,A1 \t\t! int32/16/8 -> uint32\n", },
-/* XXX This op is catching all register-to-register conversions. Some of these
- * need special handling. */
-
{ SCONV, INAREG,
- SAREG, TANY,
- SAREG, TANY,
+ SAREG, TUSHORT|TUCHAR,
+ SAREG, TUNSIGNED,
0, RLEFT,
- " \t\t! XXX in-register convert\n", },
+ " \t\t! uint16/8 -> uint32\n", },
+
+/* Floating-point conversions must be stored and loaded. */
+
+{ SCONV, INBREG,
+ SOREG, T64|TUNSIGNED,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 \t\t! int64 -> float\n"
+ " fxtos A1,A1\n", },
+
+{ SCONV, INBREG,
+ SOREG, TINT|TSHORT|TCHAR,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 \t\t! int32/16/8 -> float\n"
+ " fitos A1,A1\n", }, // XXX need 'lds', 'ldh', etc
+
+{ SCONV, INCREG,
+ SOREG, T64,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 \t\t! (u)int64 -> double\n"
+ " fxtod A1,A1\n", },
+
+{ SCONV, INCREG,
+ SOREG, TINT|TSHORT|TCHAR,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " mov AL,A1 \t\t! int32/16/8 -> double\n"
+ " fitod A1,A1\n", }, // XXX need 'lds' 'ldh' 'ld', etc.
+
+{ SCONV, INBREG,
+ SCREG, TDOUBLE,
+ SBREG, TFLOAT,
+ NBREG, RESC1,
+ " fdtos AL,A1 \t\t! double -> float\n",},
+
+{ SCONV, INCREG,
+ SBREG, TFLOAT,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " fstod AL,A1 \t\t! float -> double\n",},
/* Multiplication and division */
@@ -188,112 +141,205 @@ struct optab table[] = {
SAREG, TANY,
SAREG, TANY,
NAREG|NASR|NASL, RESC1,
- " mulx AL,AR,AR ! multiply\n", },
+ " mulx AL,AR,A1 ! multiply\n", },
+
+{ MUL, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSR|NBSL, RESC1,
+ " fmuls AL,AR,A1 ! multiply float\n", },
+
+{ MUL, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSR|NCSL, RESC1,
+ " fmuld AL,AR,A1 ! multiply double\n", },
{ DIV, INAREG,
- SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG,
- SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
NAREG|NASR|NASL, RESC1,
- " udivx AL,AR,AR ! unsigned division\n", },
+ " udivx AL,AR,A1 ! unsigned division\n", },
{ DIV, INAREG,
- SAREG, TWORD|TSHORT|TCHAR|TLONGLONG,
- SAREG, TWORD|TSHORT|TCHAR|TLONGLONG,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
NAREG|NASR|NASL, RESC1,
- " sdivx AL,AR,AR ! signed division\n", },
-
- /* TODO MOD */
+ " sdivx AL,AR,A1 ! signed division\n", },
+
+{ DIV, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSR|NBSL, RESC1,
+ " fdivs AL,AR,A1 ! divide float\n", },
+
+{ DIV, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSR|NCSL, RESC1,
+ " fdivd AL,AR,A1 ! divide double\n", },
+
+{ MOD, INAREG,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64,
+ NAREG, RESC1,
+ " udivx AL,AR,A1 ! unsigned modulo\n"
+ " mulx A1,AR,A1\n"
+ " sub AL,A1,A1\n", },
+
+{ MOD, INAREG,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ SAREG, TINT|TSHORT|TCHAR|TS64,
+ NAREG, RESC1,
+ " sdivx AL,AR,A1 ! signed modulo\n"
+ " mulx A1,AR,A1\n"
+ " sub AL,A1,A1\n", },
{ PLUS, INAREG,
SAREG, TANY,
SAREG, TANY,
NAREG|NASL, RESC1,
- " add A1,AL,AR\n", },
+ " add AL,AR,A1\n", },
+
+{ PLUS, INBREG,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG|NBSL, RESC1,
+ " fadds AL,AR,A1\n", },
+
+{ PLUS, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG|NCSL, RESC1,
+ " faddd AL,AR,A1\n", },
{ PLUS, INAREG,
SAREG, TANY,
- SCCON, TWORD,
- NAREG|NASL, RESC1,
- " add AL,AR,A1 ! add constant to reg\n", },
+ SCON, TANY,
+ (3*NAREG)|NASL, RESC1,
+ "ZA", },
{ MINUS, INAREG,
SAREG, TANY,
SAREG, TANY,
NAREG|NASL, RESC1,
- " sub AL,AR,AR\n", },
+ " sub AL,AR,A1\n", },
+
+{ MINUS, INBREG,
+ SBREG, TANY,
+ SBREG, TANY,
+ NBREG|NBSL|NBSR, RESC1,
+ " fsubs AL,AR,A1\n", },
+
+{ MINUS, INCREG,
+ SCREG, TANY,
+ SCREG, TANY,
+ NCREG|NCSL|NBSR, RESC1,
+ " fsubd AL,AR,A1\n", },
{ MINUS, INAREG,
SAREG, TANY,
- SSCON, TANY,
- NAREG|NASL, RESC1,
- "ZB\n", },
+ SCON, TANY,
+ (3*NAREG)|NASL, RESC1,
+ "ZB", },
{ UMINUS, INAREG,
SAREG, TANY,
SANY, TANY,
NAREG|NASL, RESC1,
- " sub A1,AL,A1\n", },
+ " sub %g0,AL,A1\n", },
+
+{ UMINUS, INBREG,
+ SBREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1,
+ " fsubs %g0,AL,A1\n", },
+
+{ UMINUS, INCREG,
+ SCREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1,
+ " fsubd %g0,AL,A1\n", },
/* Shifts */
{ RS, INAREG,
- SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
SANY, TANY,
NAREG|NASL, RESC1,
- " sra AL,AR,AL ! shift right\n", },
+ " sra AL,AR,A1 ! shift right\n", },
{ RS, INAREG,
- SAREG, TLONGLONG|TULONGLONG,
+ SAREG, T64,
SANY, TANY,
NAREG|NASL, RESC1,
- " srax AL,AR,AL ! shift right\n", },
+ " srax AL,AR,A1 ! shift right\n", },
{ LS, INAREG,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR,
SANY, TANY,
NAREG|NASL, RESC1,
- " sll AL,AR,AL ! shift left\n", },
+ " sll AL,AR,A1 ! shift left\n", },
{ LS, INAREG,
- SAREG, TLONGLONG|TULONGLONG,
+ SAREG, T64,
SANY, TANY,
NAREG|NASL, RESC1,
- " sllx AL,AR,AL ! shift left\n", },
+ " sllx AL,AR,A1 ! shift left\n", },
+{ COMPL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " orn AL,%g0,A1 ! complement\n", },
/* Assignments */
{ ASSIGN, FOREFF|INAREG,
- SOREG, TWORD,
- SAREG, TWORD,
+ SOREG, TINT|TUNSIGNED,
+ SAREG, TINT|TUNSIGNED,
0, RDEST,
" stw AR,[AL] ! store (u)int32\n"
" nop\n", },
{ ASSIGN, FOREFF|INAREG,
- SOREG, TSHORT|TUSHORT,
- SAREG, TSHORT|TUSHORT,
+ SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
0, RDEST,
" sth AR,[AL] ! store (u)int16\n"
" nop\n", },
{ ASSIGN, FOREFF|INAREG,
- SOREG, TCHAR|TUCHAR,
- SAREG, TCHAR|TUCHAR,
+ SOREG, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
0, RDEST,
" stb AR,[AL] ! store (u)int8\n"
" nop\n", },
{ ASSIGN, FOREFF|INAREG,
- SOREG, TLONGLONG|TULONGLONG|TPOINT,
- SAREG, TLONGLONG|TULONGLONG|TPOINT,
+ SOREG, T64,
+ SAREG, T64,
0, RDEST,
" stx AR,[AL] ! store (u)int64\n"
" nop\n", },
+{ ASSIGN, FOREFF|INBREG,
+ SOREG, TFLOAT,
+ SBREG, TFLOAT,
+ 0, RDEST,
+ " st AR,[AL] ! store float\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SOREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ 0, RDEST,
+ " std AR,[AL] ! store double\n"
+ " nop\n", },
+
{ ASSIGN, FOREFF|INAREG,
- SNAME, TWORD,
- SAREG, TWORD,
+ SNAME, TINT|TUNSIGNED,
+ SAREG, TINT|TUNSIGNED,
NAREG, RDEST,
" sethi %h44(AL),A1 \t! store (u)int32 into sname\n"
" or A1,%m44(AL),A1\n"
@@ -322,8 +368,8 @@ struct optab table[] = {
" nop\n", },
{ ASSIGN, FOREFF|INAREG,
- SNAME, TLONGLONG|TULONGLONG|TPOINT,
- SAREG, TLONGLONG|TULONGLONG|TPOINT,
+ SNAME, T64,
+ SAREG, T64,
NAREG, RDEST,
" sethi %h44(AL),A1 \t! store (u)int64 into sname\n"
" or A1,%m44(AL),A1\n"
@@ -331,25 +377,65 @@ struct optab table[] = {
" stx AR,[A1+%l44(AL)]\n"
" nop\n", },
+{ ASSIGN, FOREFF|INBREG,
+ SNAME, TFLOAT,
+ SBREG, TFLOAT,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store float into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " st AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SNAME, TDOUBLE,
+ SCREG, TDOUBLE,
+ NAREG, RDEST,
+ " sethi %h44(AL),A1 \t! store double into sname\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " std AR,[A1+%l44(AL)]\n"
+ " nop\n", },
+
{ ASSIGN, FOREFF|INAREG,
SAREG, TANY,
SAREG, TANY,
0, RDEST,
- " mov AL, AR ! register move\n", },
+ " mov AR,AL ! register move\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TANY,
+ SBREG, TANY,
+ 0, RDEST,
+ " fmovs AR,AL ! move float\n", },
+
+{ ASSIGN, FOREFF|INCREG,
+ SCREG, TANY,
+ SCREG, TANY,
+ 0, RDEST,
+ " fmovd AR,AL ! move double\n", },
+
+/* Structure assignment. */
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
/* Comparisons. */
{ EQ, FORCC,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TANY,
+ SAREG, TANY,
0, RESCC,
" cmp AL,AR\n"
" be LC\n"
" nop\n", },
{ NE, FORCC,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG, TANY,
+ SAREG, TANY,
0, RESCC,
" cmp AL,AR\n"
" bne LC\n"
@@ -361,13 +447,15 @@ struct optab table[] = {
0, RESCC,
" O AL,LC\n"
" nop\n", },
+
{ OPLOG, FORCC,
SAREG, TANY,
SAREG, TANY,
NAREG|NASL, RESCC,
- " sub AL,AR,A1 ! oplog\n"
+ " sub AL,AR,A1 ! oplog\n"
" O A1,LC\n"
" nop\n", },
+
{ OPLOG, FORCC,
SAREG, TANY,
SCCON, TANY,
@@ -376,33 +464,58 @@ struct optab table[] = {
" O A1,LC\n"
" nop\n", },
+{ OPLOG, FORCC,
+ SBREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG, RESCC,
+ " fcmps AL,AR ! oplog float\n"
+ " ZF LC\n", },
+
+{ OPLOG, FORCC,
+ SOREG, TFLOAT,
+ SBREG, TFLOAT,
+ NBREG, RESCC,
+ " ld [AL], A1 ! oplog float oreg\n"
+ " nop\n"
+ " fcmps A1,AR\n"
+ " ZF LC\n", },
+
+{ OPLOG, FORCC,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESCC,
+ " XXX double oplog\n", },
+
/* Load constants to register. */
{ OPLTYPE, INAREG,
SCON, TANY,
- SNAME, TLONGLONG|TULONGLONG|TPOINT,
+ SNAME, T64,
NAREG, RESC1,
" sethi %h44(AL),A1\t ! load const (u)int64 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " ldx [A1+%l44(AL)],A1\n", },
+ " ldx [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
- SNAME, TWORD,
+ SNAME, TINT,
NAREG, RESC1,
" sethi %h44(AL),A1\t ! load const int32 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " ldsw [A1+%l44(AL)],A1\n", },
+ " ldsw [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
- SNAME, TUWORD,
+ SNAME, TUNSIGNED,
NAREG, RESC1,
" sethi %h44(AL),A1\t! load const uint32 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " lduw [A1+%l44(AL)],A1\n", },
+ " lduw [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
SNAME, TSHORT,
@@ -410,7 +523,8 @@ struct optab table[] = {
" sethi %h44(AL),A1\t! load const int16 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " ldsh [A1+%l44(AL)],A1\n", },
+ " ldsh [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
SNAME, TUSHORT,
@@ -418,7 +532,8 @@ struct optab table[] = {
" sethi %h44(AL),A1\t ! load const uint16 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " lduh [A1+%l44(AL)],A1\n", },
+ " lduh [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
SNAME, TCHAR,
@@ -426,7 +541,8 @@ struct optab table[] = {
" sethi %h44(AL),A1\t\t! load const int8 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " ldsb [A1+%l44(AL)],A1\n", },
+ " ldsb [A1+%l44(AL)],A1\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SCON, TANY,
SNAME, TUCHAR,
@@ -434,14 +550,34 @@ struct optab table[] = {
" sethi %h44(AL),A1\t! load const uint8 to reg\n"
" or A1,%m44(AL),A1\n"
" sllx A1,12,A1\n"
- " ldub [A1+%l44(AL)],A1\n", },
+ " ldub [A1+%l44(AL)],A1\n"
+ " nop\n", },
+
+{ OPLTYPE, INBREG,
+ SBREG, TANY,
+ SNAME, TANY,
+ NAREG|NBREG, RESC2,
+ " sethi %h44(AL),A1\t! load const float to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ld [A1+%l44(AL)],A2\n"
+ " nop\n", },
+
+{ OPLTYPE, INCREG,
+ SCREG, TANY,
+ SNAME, TANY,
+ NAREG|NCREG, RESC2,
+ " sethi %h44(AL),A1\t! load const double to reg\n"
+ " or A1,%m44(AL),A1\n"
+ " sllx A1,12,A1\n"
+ " ldd [A1+%l44(AL)],A2\n"
+ " nop\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SCON, TANY,
- NAREG, RESC1,
- "ZA" },
-
+ (2*NAREG), RESC1,
+ "ZC" },
/* Convert LTYPE to reg. */
@@ -451,7 +587,7 @@ struct optab table[] = {
NAREG, RESC1,
" ldsb [AL],A1 ! load int8 to reg\n"
" nop\n", },
-
+
{ OPLTYPE, INAREG,
SAREG, TANY,
SOREG, TUCHAR,
@@ -475,21 +611,21 @@ struct optab table[] = {
{ OPLTYPE, INAREG,
SAREG, TANY,
- SOREG, TWORD,
+ SOREG, TINT,
NAREG, RESC1,
" ldsw [AL],A1 ! load int32 to reg\n"
" nop\n", },
{ OPLTYPE, INAREG,
SAREG, TANY,
- SOREG, TWORD,
+ SOREG, TUNSIGNED,
NAREG, RESC1,
" lduw [AL],A1 ! load uint32 to reg\n"
" nop\n", },
{ OPLTYPE, INAREG,
SAREG, TANY,
- SOREG, TLONGLONG|TULONGLONG|TPOINT,
+ SOREG, T64,
NAREG, RESC1,
" ldx [AL],A1 ! load (u)int64 to reg\n"
" nop\n", },
@@ -500,6 +636,19 @@ struct optab table[] = {
NAREG, RESC1,
" mov \%g0,A1\t ! load 0 to reg\n", },
+{ OPLTYPE, INBREG,
+ SBREG, TFLOAT,
+ SOREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 ! load float to reg\n"
+ " nop\n", },
+
+{ OPLTYPE, INCREG,
+ SCREG, TDOUBLE,
+ SOREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 ! load double to reg\n"
+ " nop\n", },
/* Jumps. */
@@ -573,6 +722,36 @@ struct optab table[] = {
" call AL ! = (*AL)(args)\n"
" nop\n", },
+/* Function arguments. */
+
+{ FUNARG, FOREFF,
+ SAREG, T64,
+ SANY, TANY,
+ 0, 0,
+ " stx AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TINT|TUNSIGNED,
+ SANY, TANY,
+ 0, 0,
+ " stw AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, 0,
+ " sth AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
+{ FUNARG, FOREFF,
+ SAREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, 0,
+ " stb AL,[%sp+AR] \t! save func arg to stack\n"
+ " nop\n", },
+
/* Indirection. */
@@ -583,20 +762,20 @@ struct optab table[] = {
" O AL,AR,A1\n", },
{ UMUL, INAREG,
- SANY, TLONGLONG|TULONGLONG|TPOINT,
- SOREG, TLONGLONG|TULONGLONG|TPOINT,
+ SANY, T64,
+ SOREG, T64,
NAREG, RESC1,
" ldx [AL],A1 ! (u)int64 load\n"
" nop\n", },
{ UMUL, INAREG,
- SANY, TWORD,
- SOREG, TWORD,
+ SANY, TINT,
+ SOREG, TINT,
NAREG, RESC1,
" ldsw [AL],A1 ! int32 load\n"
" nop\n", },
{ UMUL, INAREG,
- SANY, TUWORD,
- SOREG, TUWORD,
+ SANY, TUNSIGNED,
+ SOREG, TUNSIGNED,
NAREG, RESC1,
" lduw [AL],A1 ! uint32 load\n"
" nop\n", },
@@ -625,6 +804,20 @@ struct optab table[] = {
" lduh [AL],A1 ! uint16 load\n"
" nop\n", },
+{ UMUL, INBREG,
+ SANY, TFLOAT,
+ SOREG, TFLOAT,
+ NBREG, RESC1,
+ " ld [AL],A1 ! load float\n"
+ " nop\n", },
+
+{ UMUL, INCREG,
+ SANY, TDOUBLE,
+ SOREG, TDOUBLE,
+ NCREG, RESC1,
+ " ldd [AL],A1 ! load double\n"
+ " nop\n", },
+
{ FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE, "ERR: printing free op\n" },
};