summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2007-11-16 08:34:56 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2007-11-16 08:34:56 +0000
commit2811f223c5884b622e45a2352c89b8654da77b35 (patch)
tree4d7c2ae0e613bf90f29c140770fa0751b6b07861
parent64b2ea406a218d1075510d5fdbb6bd30b2c0825f (diff)
sync with repe; commit from gmcgarry@:
Bring MIPS support fully up-to-date. Includes the following changes: Support use of different assemblers. Handle big-endian and little-endian code generation. Start support for n32/n64 PIC code generation Update to arguments-in-registers infrastructure. Cleanup handling of branches. Fix register coloring Fix structure assignment. Add longlong instructions Remove unused functions. Indentation fixes. Tested on NetBSD/pmax (little endian).
-rw-r--r--usr.bin/pcc/mips/TODO2
-rw-r--r--usr.bin/pcc/mips/code.c181
-rw-r--r--usr.bin/pcc/mips/local.c298
-rw-r--r--usr.bin/pcc/mips/local2.c1139
-rw-r--r--usr.bin/pcc/mips/macdefs.h304
-rw-r--r--usr.bin/pcc/mips/order.c502
-rw-r--r--usr.bin/pcc/mips/table.c1039
7 files changed, 1974 insertions, 1491 deletions
diff --git a/usr.bin/pcc/mips/TODO b/usr.bin/pcc/mips/TODO
index 4b104cf8ee2..63b5f67c34a 100644
--- a/usr.bin/pcc/mips/TODO
+++ b/usr.bin/pcc/mips/TODO
@@ -1,5 +1,3 @@
-$OpenBSD: TODO,v 1.1 2007/10/07 17:58:51 otto Exp $
-
* Look at long long support for the new register allocator.
* Add floating point support.
diff --git a/usr.bin/pcc/mips/code.c b/usr.bin/pcc/mips/code.c
index 1ada0196529..bbeecd96146 100644
--- a/usr.bin/pcc/mips/code.c
+++ b/usr.bin/pcc/mips/code.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: code.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: code.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -48,7 +48,7 @@ defalign(int n)
n /= SZCHAR;
if (n == 1)
return;
- printf(" .align %d\n", n);
+ printf("\t.align %d\n", n);
}
/*
@@ -64,11 +64,14 @@ defnam(struct symtab *p)
c = gcc_findname(p);
#endif
if (p->sclass == EXTDEF)
- printf(" .globl %s\n", c);
+ printf("\t.globl %s\n", c);
+#ifdef USE_GAS
+ printf("\t.type %s,@object\n", c);
+ printf("\t.size %s," CONFMT "\n", c, tsize(p->stype, p->sdf, p->ssue));
+#endif
printf("%s:\n", c);
}
-
/*
* code for the end of a function
* deals with struct return here
@@ -76,72 +79,65 @@ defnam(struct symtab *p)
void
efcode()
{
- NODE *p, *q;
- int sz;
-
if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
return;
}
/*
- * helper for bfcode() to put register arguments on stack.
- */
-static void
-argmove(struct symtab *s, int regno)
-{
- NODE *p, *r;
-
- s->sclass = PARAM;
- s->soffset = NOOFFSET;
-
- oalloc(s, &passedargoff);
-
- spname = s;
- p = buildtree(NAME, NIL, NIL);
- r = bcon(0);
- r->n_op = REG;
- r->n_rval = regno;
- r->n_type = p->n_type;
- r->n_sue = p->n_sue;
- r->n_df = p->n_df;
- ecode(buildtree(ASSIGN, p, r));
-}
-
-/*
* code for the beginning of a function; a is an array of
* indices in symtab for the arguments; n is the number
*/
void
-bfcode(struct symtab **a, int n)
+bfcode(struct symtab **sp, int cnt)
{
- int i, m;
+ NODE *p, *q;
+ int i, n;
- /* Passed arguments start 64 bits above the framepointer. */
- passedargoff = 64;
-
if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
/* Function returns struct, adjust arg offset */
- for (i = 0; i < n; i++)
- a[i]->soffset += SZPOINT(INT);
+ for (i = 0; i < cnt; i++)
+ sp[i]->soffset += SZPOINT(INT);
}
- m = n <= 4 ? n : 4;
-
- for(i = 0; i < m; i++) {
- /*
- if(a[i]->stype == LONGLONG || a[i]->stype == ULONGLONG) {
- printf("longlong\n");
- argmove(a[i], A0+i);
+ /* recalculate the arg offset and create TEMP moves */
+ for (n = A0, i = 0; i < cnt; i++) {
+ if (n + szty(sp[i]->stype) <= A0 + MIPS_NARGREGS) {
+ if (xtemps) {
+ 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 = n;
+ p = buildtree(ASSIGN, p, q);
+ sp[i]->soffset = p->n_left->n_lval;
+ sp[i]->sflags |= STNODE;
+ } else {
+ // sp[i]->soffset += ARGINIT;
+ spname = sp[i];
+ q = block(REG, NIL, NIL,
+ sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
+ q->n_rval = n;
+ p = buildtree(ASSIGN, buildtree(NAME, 0, 0), q);
+ }
+ ecomp(p);
+ } else {
+ // sp[i]->soffset += ARGINIT;
+ 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);
+ }
- if(i+1 < 4) {
- argmove(a[i], A0+i+1);
- }
-
- i++;
- } else*/
- argmove(a[i], A0+i);
-
- }
}
@@ -173,7 +169,7 @@ bjobcode()
void
bycode(int t, int i)
{
- static int lastoctal = 0;
+ static int lastoctal = 0;
/* put byte i+1 in a string */
@@ -182,17 +178,21 @@ bycode(int t, int i)
puts("\"");
} else {
if (i == 0)
- printf("\t.ascii \"");
- if (t == '\\' || t == '"') {
+ printf("\t.asciiz \"");
+ if (t == 0)
+ return;
+ else if (t == '\\' || t == '"') {
lastoctal = 0;
putchar('\\');
putchar(t);
+ } else if (t == 012) {
+ printf("\\n");
} 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);
+ printf("\"\n\t.asciiz \"%c", t);
} else {
lastoctal = 0;
putchar(t);
@@ -201,16 +201,6 @@ bycode(int t, int i)
}
/*
- * n integer words of zeros
- */
-void
-zecode(int n)
-{
- printf(" .zero %d\n", n * (SZINT/SZCHAR));
- inoff += n * SZINT;
-}
-
-/*
* return the alignment of field of type t
*/
int
@@ -234,6 +224,59 @@ fldty(struct symtab *p)
* XXX - fix genswitch.
*/
void
-genswitch(struct swents **p, int n)
+genswitch(int num, struct swents **p, int n)
+{
+ NODE *r;
+ int i;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ r = tempnode(num, INT, 0, MKSUE(INT));
+ r = buildtree(NE, r, bcon(p[i]->sval));
+ cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
+ }
+ if (p[0]->slab > 0)
+ branch(p[0]->slab);
+}
+
+static void
+moveargs(NODE **n, 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;
+ }
+
+ regnum = *regp;
+ sz = szty(r->n_type);
+
+ if (regnum + sz <= A0 + MIPS_NARGREGS) {
+ t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue);
+ t->n_rval = regnum;
+ t = buildtree(ASSIGN, t, r);
+ } else {
+ t = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue);
+ }
+
+ *n = t;
+ *regp += sz;
+}
+
+/*
+ * 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 = A0;
+ moveargs(&p->n_right, &regnum);
+ return p;
}
diff --git a/usr.bin/pcc/mips/local.c b/usr.bin/pcc/mips/local.c
index 554b53190f3..113e420ce6e 100644
--- a/usr.bin/pcc/mips/local.c
+++ b/usr.bin/pcc/mips/local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: local.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -31,33 +31,73 @@
* Simon Olsson (simols-1@student.ltu.se) 2005.
*/
-# include "pass1.h"
+#include "pass1.h"
-/* this file contains code which is dependent on the target machine */
+static int inbits, inval;
+#ifdef MIPS_BIGENDIAN
+/*
+ * If we're big endian, then all OREG loads of a type
+ * larger than the destination, must have the
+ * offset changed to point to the correct bytes in memory.
+ */
+static NODE *
+offchg(NODE *p)
+{
+ NODE *l = p->n_left;
+
+ if (p->n_op != SCONV)
+ return;
+
+ switch (l->n_type) {
+ case SHORT:
+ case USHORT:
+ if (DEUNSIGN(p->n_type) == CHAR)
+ l->n_lval += 1;
+ break;
+ case LONG:
+ case ULONG:
+ case INT:
+ case UNSIGNED:
+ if (DEUNSIGN(p->n_type) == CHAR)
+ l->n_lval += 3;
+ else if (DEUNSIGNED(p->n_type) == SHORT)
+ l->n_lval += 2;
+ break;
+ case LONGLONG:
+ case ULONGLONG:
+ if (DEUNSIGN(p->n_type) == CHAR)
+ l->n_lval += 7;
+ else if (DEUNSIGNED(p->n_type) == SHORT)
+ l->n_lval += 6;
+ else if (DEUNSIGN(p->n_type) == INT ||
+ DEUNSIGN(p->n_type) == LONG)
+ p->n_lval += 4;
+ default:
+ comperr("offchg: unknown type");
+ break;
+ }
+
+ return p;
+}
+#endif
+
+/* this is called to do local transformations on
+ * an expression tree preparitory to its being
+ * written out in intermediate code.
+ */
NODE *
clocal(NODE *p)
{
- /* this is called to do local transformations on
- an expression tree preparitory to its being
- written out in intermediate code.
- */
-
- /* the major essential job is rewriting the
- automatic variables and arguments in terms of
- REG and OREG nodes */
- /* conversion ops which are not necessary are also clobbered here */
- /* in addition, any special features (such as rewriting
- exclusive or) are easily handled here as well */
-
- register struct symtab *q;
- register NODE *r, *l;
- register int o;
- register int m, ml;
+ struct symtab *q;
+ NODE *r, *l;
+ int o;
+ int m, ml;
TWORD t;
//printf("in:\n");
//fwalk(p, eprint, 0);
+
switch( o = p->n_op ){
case NAME:
@@ -71,7 +111,7 @@ clocal(NODE *p)
/* fake up a structure reference */
r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
r->n_lval = 0;
- r->n_rval = FPREG;
+ r->n_rval = FP;
p = stref(block(STREF, r, p, 0, 0, 0));
break;
@@ -158,6 +198,16 @@ clocal(NODE *p)
return l;
}
+#ifdef MIPS_BIGENDIAN
+ /*
+ * If we're big endian, then all OREG loads of a type
+ * larger than the destination, must have the
+ * offset changed to point to the correct bytes in memory.
+ */
+ if (l->n_type == OREG)
+ p = offchg(p);
+#endif
+
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 &&
@@ -171,13 +221,11 @@ clocal(NODE *p)
}
}
-#if 0
if ((p->n_type == INT || p->n_type == UNSIGNED) &&
ISPTR(l->n_type)) {
nfree(p);
return l;
}
-#endif
o = l->n_op;
m = p->n_type;
@@ -260,15 +308,14 @@ clocal(NODE *p)
/* put return value in return reg */
p->n_op = ASSIGN;
p->n_right = p->n_left;
- p->n_left = block(REG, NIL, NIL, p->n_type, 0,
- MKSUE(INT));
- p->n_left->n_rval = RETREG;
+ p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ p->n_left->n_rval = RETREG(p->n_type);
break;
}
+
//printf("ut:\n");
//fwalk(p, eprint, 0);
-
return(p);
}
@@ -309,23 +356,20 @@ 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.
*/
NODE *
offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
{
- register NODE *p;
+ NODE *p;
if (xdebug)
printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
off, t, d, sue->suesize);
- p = bcon(0);
- p->n_lval = off/SZCHAR; /* Default */
- return(p);
+ p = bcon(off/SZCHAR);
+ return p;
}
/*
@@ -370,65 +414,80 @@ spalloc(NODE *t, NODE *p, OFFSZ off)
* mat be associated with a label
*/
void
-ninval(NODE *p)
+ninval(CONSZ off, int fsz, NODE *p)
{
- struct symtab *q;
- TWORD t;
+ union { float f; double d; long double l; int i[3]; } u;
+ struct symtab *q;
+ TWORD t;
+#ifndef USE_GAS
+ int i;
+#endif
- p = p->n_left;
- t = p->n_type;
- if (t > BTMASK)
- t = INT; /* pointer */
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
- switch (t) {
- case LONGLONG:
- case ULONGLONG:
- inval(p->n_lval & 0xffffffff);
- inval(p->n_lval >> 32);
- break;
- case INT:
- case UNSIGNED:
- printf("\t.long 0x%x", (int)p->n_lval);
- if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
- q->sclass == ILABEL) {
- printf("+" LABFMT, q->soffset);
- } else
- printf("+%s", exname(q->sname));
- }
- printf("\n");
- break;
- default:
- cerror("ninval");
- }
-}
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: init node not constant");
-/*
- * print out an integer.
- */
-void
-inval(CONSZ word)
-{
- word &= 0xffffffff;
- printf(" .long 0x%llx\n", word);
-}
+ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
+ uerror("element not constant");
-/* output code to initialize a floating point value */
-/* the proper alignment has been obtained */
-void
-finval(NODE *p)
-{
- switch (p->n_type) {
- case LDOUBLE:
- printf("\t.tfloat\t0t%.20Le\n", p->n_dcon);
- break;
- case DOUBLE:
- printf("\t.dfloat\t0d%.20e\n", (double)p->n_dcon);
- break;
- case FLOAT:
- printf("\t.ffloat\t0f%.20e\n", (float)p->n_dcon);
- break;
- }
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+#ifdef USE_GAS
+ printf("\t.dword 0x%llx\n", (long long)p->n_lval);
+#else
+ 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
+ break;
+ case BOOL:
+ if (p->n_lval > 1)
+ p->n_lval = p->n_lval != 0;
+ /* FALLTHROUGH */
+ case INT:
+ case UNSIGNED:
+ printf("\t.word 0x%x", (int)p->n_lval);
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+ q->sclass == ILABEL) {
+ printf("+" LABFMT, q->soffset);
+ } else
+ printf("+%s", exname(q->sname));
+ }
+ printf("\n");
+ break;
+ case SHORT:
+ case USHORT:
+ printf("\t.half 0x%x\n", (int)p->n_lval & 0xffff);
+ break;
+ case CHAR:
+ case UCHAR:
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ break;
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.word\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.word\t0x%x\n", u.i[0]);
+ printf("\t.word\t0x%x\n", u.i[1]);
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.word\t0x%x\n", u.i[0]);
+ break;
+ default:
+ cerror("ninval");
+ }
}
/* make a name look like an external name in the local machine */
@@ -504,12 +563,12 @@ lcommdec(struct symtab *q)
off = (off+(SZCHAR-1))/SZCHAR;
if (q->slevel == 0)
#ifdef GCC_COMPAT
- printf(" .lcomm %s,0%o\n", gcc_findname(q), off);
+ printf("\t.lcomm %s,0%o\n", gcc_findname(q), off);
#else
- printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+ printf("\t.lcomm %s,0%o\n", exname(q->sname), off);
#endif
else
- printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+ printf("\t.lcomm " LABFMT ",0%o\n", q->soffset, off);
}
/*
@@ -521,13 +580,68 @@ deflab1(int label)
printf(LABFMT ":\n", label);
}
-static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+static char *loctbl[] = { "text", "data", "bss", "data" };
void
setloc1(int locc)
{
- if (locc == lastloc)
+ //printf("setloc1(%d)\n", locc);
+ if ((locc == lastloc) || (lastloc == DATA && locc == STRNG) || (locc == STRNG || lastloc == DATA))
return;
lastloc = locc;
- printf(" .%s\n", loctbl[locc]);
+ printf("\t.%s\n", loctbl[locc]);
+}
+
+/*
+ * Initialize a bitfield.
+ */
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+ if (idebug)
+ printf("infld off %lld, fsz %d, val %lld inbits %d\n",
+ off, fsz, val, inbits);
+ val &= (1 << fsz)-1;
+ while (fsz + inbits >= SZCHAR) {
+ inval |= (val << inbits);
+ printf("\t.byte %d\n", inval & 255);
+ fsz -= (SZCHAR - inbits);
+ val >>= (SZCHAR - inbits);
+ inval = inbits = 0;
+ }
+ if (fsz) {
+ inval |= (val << inbits);
+ inbits += fsz;
+ }
+}
+
+/*
+ * set fsz bits in sequence to zero.
+ */
+void
+zbits(OFFSZ off, int fsz)
+{
+ int m;
+
+ if (idebug)
+ printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
+ if ((m = (inbits % SZCHAR))) {
+ m = SZCHAR - m;
+ if (fsz < m) {
+ inbits += fsz;
+ return;
+ } else {
+ fsz -= m;
+ printf("\t.byte %d\n", inval);
+ inval = inbits = 0;
+ }
+ }
+ if (fsz >= SZCHAR) {
+ printf("\t.zero %d\n", fsz/SZCHAR);
+ fsz -= (fsz/SZCHAR) * SZCHAR;
+ }
+ if (fsz) {
+ inval = 0;
+ inbits = fsz;
+ }
}
diff --git a/usr.bin/pcc/mips/local2.c b/usr.bin/pcc/mips/local2.c
index 11d151a7f05..056762c1d61 100644
--- a/usr.bin/pcc/mips/local2.c
+++ b/usr.bin/pcc/mips/local2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: local2.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: local2.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -31,121 +31,125 @@
* Simon Olsson (simols-1@student.ltu.se) 2005.
*/
-# include "pass2.h"
-# include <ctype.h>
+#include <ctype.h>
+#include <assert.h>
-void acon(NODE *p);
-int argsize(NODE *p);
-void genargs(NODE *p);
-static void sconv(NODE *p);
-void branchfunc(NODE *p);
-void offchg(NODE *p);
+#include "pass1.h"
+#include "pass2.h"
-void
-lineid(int l, char *fn)
-{
- /* identify line l and file fn */
- printf("# line %d, file %s\n", l, fn);
-}
+static int argsiz(NODE * p);
void
deflab(int label)
{
- printf(LABFMT ":\n", label);
+ printf(LABFMT ":\n", label);
}
static int regoff[32];
static TWORD ftype;
/*
- * Print out the prolog assembler.
- * addto and regoff are already calculated.
- */
-static void
-prtprolog(struct interpass_prolog *ipp, int addto)
-{
- int i, j;
-
- printf(" addi $sp, $sp, -%d\n", addto + 8);
- printf(" sw $ra, %d($sp)\n", addto + 4);
- printf(" sw $fp, %d($sp)\n", addto);
- printf(" addi $fp, $sp, %d\n", addto);
-
- for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
- if (i & 1)
- fprintf(stdout, " sw %s, -%d(%s)\n",
- rnames[j], regoff[j], rnames[FPREG]);
-}
-
-/*
* calculate stack size and offsets
*/
static int
-offcalc(struct interpass_prolog *ipp)
+offcalc(struct interpass_prolog * ipp)
{
- int i, j, addto;
+ int i, j, addto;
- addto = p2maxautooff;
- if (addto >= AUTOINIT)
- addto -= AUTOINIT;
- addto /= SZCHAR;
+ addto = p2maxautooff;
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1) {
- addto += SZINT/SZCHAR;
- regoff[j] = addto;
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) {
+ if (i & 1) {
+ addto += SZINT / SZCHAR;
+ regoff[j] = addto;
+ }
}
- }
-
- return addto;
+
+ return addto;
}
+/*
+ * Print out the prolog assembler.
+ */
void
-prologue(struct interpass_prolog *ipp)
+prologue(struct interpass_prolog * ipp)
{
- int addto;
-
- ftype = ipp->ipp_type;
- if (ipp->ipp_vis)
- printf(" .globl %s\n", ipp->ipp_name);
- printf(" .align 4\n");
- printf("%s:\n", ipp->ipp_name);
- /*
- * We here know what register to save and how much to
- * add to the stack.
- */
- addto = offcalc(ipp);
- prtprolog(ipp, addto);
+ int addto;
+ int i, j;
+
+ ftype = ipp->ipp_type;
+ printf("\t.align 2\n");
+ if (ipp->ipp_vis)
+ printf("\t.globl %s\n", ipp->ipp_name);
+ printf("\t.ent %s\n", ipp->ipp_name);
+ printf("%s:\n", ipp->ipp_name);
+
+ addto = offcalc(ipp);
+#ifdef USE_GAS
+ if (kflag) {
+ printf("\t.frame %s,%d,%s\n", rnames[FP], 12, rnames[RA]);
+ printf("\t.set noreorder\n");
+ printf("\t.cpload $25 # pseudo-op to load GOT ptr into $25\n");
+ printf("\t.set reorder\n");
+ }
+#endif
+ printf("\taddi %s,%s,-%d\n", rnames[SP], rnames[SP], 12);
+#ifdef USE_GAS
+ if (kflag)
+ printf("\t.cprestore 8 # pseudo-op to store GOT ptr at 8(sp)\n");
+#endif
+ printf("\tsw %s,%d(%s)\n", rnames[RA], 4, rnames[SP]);
+ printf("\tsw %s,0(%s)\n", rnames[FP], rnames[SP]);
+ printf("\tmove %s,%s\n", rnames[FP], rnames[SP]);
+ if (addto)
+ printf("\taddi %s,%s,-%d\n", rnames[SP], rnames[SP], addto);
+
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
+ if (i & 1)
+ fprintf(stdout, "\tsw %s,-%d(%s) # save permanents\n",
+ rnames[j], regoff[j], rnames[FP]);
}
void
-eoftn(struct interpass_prolog *ipp)
+eoftn(struct interpass_prolog * ipp)
{
- int i, j;
- int addto;
-
- addto = offcalc(ipp);
-
- if (ipp->ipp_ip.ip_lbl == 0)
- return; /* no code needs to be generated */
-
- /* return from function code */
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1)
- fprintf(stdout, " lw %s, -%d(%s)\n",
- rnames[j], regoff[j], rnames[FPREG]);
- }
-
- printf(" lw $ra, %d($sp)\n", addto + 4);
- printf(" lw $fp, %d($sp)\n", addto);
- printf(" addi $sp, $sp, %d\n", addto + 8);
-
- /* struct return needs special treatment */
- if (ftype == STRTY || ftype == UNIONTY) {
- /* XXX - implement struct return support. */
- } else {
- printf(" jr $ra\n nop\n");
- }
+ int i, j;
+ int addto;
+ int off;
+
+ addto = offcalc(ipp);
+ off = 8;
+
+#ifdef USE_GAS
+ if (kflag)
+ off += 4;
+#endif
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) {
+ if (i & 1)
+ fprintf(stdout, "\tlw %s,-%d(%s)\n",
+ rnames[j], regoff[j], rnames[FP]);
+ }
+
+ printf("\tlw %s,%d($sp)\n", rnames[RA], addto + 4);
+ printf("\tlw %s,%d($sp)\n", rnames[FP], addto);
+ printf("\taddi %s,%s,%d\n", rnames[SP], rnames[SP], addto + off);
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ /* XXX - implement struct return support. */
+ } else {
+ printf("\tjr %s\n", rnames[RA]);
+ printf("\tnop\n");
+ }
+#ifdef USE_GAS
+ printf("\t.end %s\n", ipp->ipp_name);
+ printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name);
+#endif
}
/*
@@ -156,619 +160,596 @@ eoftn(struct interpass_prolog *ipp)
void
hopcode(int f, int o)
{
- char *str;
-
- switch (o) {
- case PLUS:
- str = "addu";
- break;
- case MINUS:
- str = "subu";
- break;
- case AND:
- str = "and";
- break;
- case OR:
- str = "or";
- break;
- case ER:
- str = "xor";
- break;
- default:
- comperr("hopcode2: %d", o);
- str = 0; /* XXX gcc */
- }
-
- printf("%s%c", str, f);
+ char *str;
+
+ switch (o) {
+ case EQ:
+ str = "beqz"; /* pseudo-op */
+ break;
+ case NE:
+ str = "bnez"; /* pseudo-op */
+ break;
+ case LE:
+ str = "blez";
+ break;
+ case LT:
+ str = "bltz";
+ break;
+ case GE:
+ str = "bgez";
+ break;
+ case GT:
+ str = "bgtz";
+ break;
+ case PLUS:
+ str = "addu";
+ break;
+ case MINUS:
+ str = "subu";
+ break;
+ case AND:
+ str = "and";
+ break;
+ case OR:
+ str = "or";
+ break;
+ case ER:
+ str = "xor";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+
+ printf("%s%c", str, f);
}
char *
-rnames[] = { /* keyed to register number tokens */
- "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8",
- "$t9", "$v0", "$v1", "$zero", "$at", "$a0", "$a1", "$a2", "$a3",
- "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", "$k0",
- "$k1", "$gp", "$sp", "$fp", "$ra",
+rnames[] = { /* keyed to register number tokens */
+#ifdef USE_GAS
+ /* gnu assembler */
+ "$zero", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25",
+ "$kt0", "$kt1", "$gp", "$sp", "$fp", "$ra",
+ "$2\0$3\0",
+ "$4\0$5\0", "$5\0$6\0", "$6\0$7\0", "$7\0$8\0",
+ "$8\0$9", "$9\0$10", "$10$11", "$11$12", "$12$13", "$13$14", "$14$15",
+ "$24$25",
+ "$16$17", "$17$18", "$18$19", "$19$20", "$2021", "$21$22", "$22$23",
+#else
+ /* mips assembler */
+ "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
+#if defined(MIPS_N32) || defined(MIPS_N64)
+ "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2", "$t3",
+#else
+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
+#endif
+ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
+ "$t8", "$t9",
+ "$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
+ "$v0$v1",
+ "$a0a1", "$a1$a2", "$a2$a3", "$a3$t0",
+ "$t0t1", "$t1$t2", "$t2$t3", "$t3$t4", "$t4t5", "$t5t6", "$t6t7",
+ "$t8t9",
+ "$s0s1", "$s1$s2", "$s2$s3", "$s3$s4", "$s4$s5", "$s5$s6", "$s6s7",
+#endif
+ "$f0", "$f1", "$f2",
};
+
int
-tlen(p) NODE *p;
+tlen(NODE *p)
{
- switch(p->n_type) {
- case CHAR:
- case UCHAR:
- return(1);
-
- case SHORT:
- case USHORT:
- return(SZSHORT/SZCHAR);
-
- case DOUBLE:
- return(SZDOUBLE/SZCHAR);
-
- case INT:
- case UNSIGNED:
- case LONG:
- case ULONG:
- return(SZINT/SZCHAR);
-
- case LONGLONG:
- case ULONGLONG:
- return SZLONGLONG/SZCHAR;
-
- default:
- if (!ISPTR(p->n_type))
- comperr("tlen type %d not pointer");
- return SZPOINT(p->n_type)/SZCHAR;
- }
+ switch (p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return (1);
+
+ case SHORT:
+ case USHORT:
+ return (SZSHORT / SZCHAR);
+
+ case DOUBLE:
+ return (SZDOUBLE / SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ return (SZINT / SZCHAR);
+
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG / SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type) / SZCHAR;
+ }
}
+#if 0
/*
* Push a structure on stack as argument.
* the scratch registers are already free here
*/
static void
-starg(NODE *p)
+starg(NODE * p)
{
- FILE *fp = stdout;
-
- if (p->n_left->n_op == REG && p->n_left->n_type == PTR+STRTY)
- return; /* already on stack */
+ if (p->n_left->n_op == REG && p->n_left->n_type == PTR + STRTY)
+ return; /* already on stack */
+}
+#endif
+/*
+ * Structure assignment.
+ */
+static void
+stasg(NODE *p)
+{
+ assert(p->n_right->n_rval == A1);
+ /* A0 = dest, A1 = src, A2 = len */
+ printf("\tli %s,%d # structure size\n",
+ rnames[A2], p->n_stsize);
+ if (p->n_left->n_op == OREG) {
+ printf("\taddi %s,%s," CONFMT " # dest address\n",
+ rnames[A0], rnames[p->n_left->n_rval],
+ p->n_left->n_lval);
+ } else if (p->n_left->n_op == NAME) {
+ printf("\tla %s,", rnames[A0]);
+ adrput(stdout, p->n_left);
+ printf("\n");
+ }
+ printf("\taddi %s,%s,-16\n", rnames[SP], rnames[SP]);
+ printf("\tbl %s # structure copy\n",
+ exname("memcpy"));
+ printf("\tnop\n");
+ printf("\taddi %s,%s,16\n", rnames[SP], rnames[SP]);
}
-void
-zzzcode(NODE *p, int c)
+static void
+llshiftop(NODE *p)
{
- NODE *r;
-
- switch (c) {
- case 'A': /* Set the right offset for SCON OREG to REG */
- offchg(p);
- break;
-
- case 'B':
- /*
- * Function arguments
- */
-
- break;
-
- case 'C': /* remove arguments from stack after subroutine call */
- printf(" addi %s, %s, %d\n",
- rnames[STKREG], rnames[STKREG], (p->n_rval + 4) * 4);
- break;
-
- case 'H': /* Fix correct order of sub from stack */
- /* Check which leg was evaluated first */
- if ((p->n_su & DORIGHT) == 0)
- putchar('r');
- break;
-
- case 'I': /* high part of init constant */
- if (p->n_name[0] != '\0')
- comperr("named highword");
- fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff);
- break;
-
- case 'Q': /* Branch instructions */
- branchfunc(p);
- break;
-
- default:
- comperr("zzzcode %c", c);
- }
+ assert(p->n_right->n_op == ICON);
+
+ if (p->n_op == LS && p->n_right->n_lval < 32) {
+ expand(p, INBREG, "\tsrl A1,AL,32-AR ; 64-bit left-shift\n");
+ expand(p, INBREG, "\tsll U1,UL,AR\n");
+ expand(p, INBREG, "\tor U1,U1,A1\n");
+ expand(p, INBREG, "\tsll A1,AL,AR\n");
+ } else if (p->n_op == LS) {
+ expand(p, INBREG, "\tli A1,0 ; 64-bit left-shift\n");
+ expand(p, INBREG, "\tsll U1,AL,AR-32\n");
+ } else if (p->n_op == RS && p->n_right->n_lval < 32) {
+ expand(p, INBREG, "\tsll U1,UL,32-AR ; 64-bit right-shift\n");
+ expand(p, INBREG, "\tsrl A1,AL,AR\n");
+ expand(p, INBREG, "\tor A1,A1,U1\n");
+ expand(p, INBREG, "\tsrl U1,UL,AR\n");
+ } else if (p->n_op == RS) {
+ expand(p, INBREG, "\tli U1,0 ; 64-bit right-shift\n");
+ expand(p, INBREG, "\tsrl A1,UL,AR-32\n");
+ }
}
-/* set up temporary registers */
-void
-setregs()
+/*
+ * Emulate unsupported instruction.
+ */
+static void
+emulop(NODE *p)
{
- /* 12 free regs on the mips (0-9, temporary and 10-11 is v0 and v1). */
- fregs = 12;
+ char *ch;
+
+ 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("ZE");
+ printf("\taddi %s,%s,-16\n", rnames[SP], rnames[SP]);
+ printf("\tbl __%sdi3\n", ch);
+ printf("\tnop\n");
+ printf("\taddi %s,%s,16\n", rnames[SP], rnames[SP]);
}
-/*ARGSUSED*/
-int
-rewfld(NODE *p)
+void
+zzzcode(NODE * p, int c)
{
- return(1);
+ int sz;
+
+ switch (c) {
+
+ case 'C': /* remove arguments from stack after subroutine call */
+ sz = p->n_qual > 16 ? p->n_qual : 16;
+ printf("\taddi %s,%s,%d\n",
+ rnames[STKREG], rnames[STKREG], sz);
+ break;
+
+ case 'I': /* high part of init constant */
+ if (p->n_name[0] != '\0')
+ comperr("named highword");
+ fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff);
+ break;
+
+ case 'Q': /* emit struct assign */
+ stasg(p);
+ break;
+
+ case 'O': /* 64-bit left and right shift operators */
+ llshiftop(p);
+ break;
+
+ case 'E': /* emit emulated ops */
+ emulop(p);
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
}
-int canaddr(NODE *);
+/* ARGSUSED */
int
-canaddr(NODE *p)
+rewfld(NODE * p)
{
- int o = p->n_op;
-
- if (o==NAME || o==REG || o==ICON || o==OREG ||
- (o==UMUL && shumul(p->n_left)))
- return(1);
- return(0);
+ return (1);
}
/*
* Does the bitfield shape match?
*/
int
-flshape(NODE *p)
+flshape(NODE * p)
{
- int o = p->n_op;
+ int o = p->n_op;
- if (o == OREG || o == REG || o == NAME)
- return SRDIR; /* Direct match */
- if (o == UMUL && shumul(p->n_left))
- return SROREG; /* Convert into oreg */
- return SRREG; /* put it into a register */
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
}
/* INTEMP shapes must not contain any temporary registers */
/* XXX should this go away now? */
int
-shtemp(NODE *p)
+shtemp(NODE * p)
{
- return 0;
+ return 0;
#if 0
- int r;
+ int r;
- if (p->n_op == STARG )
- p = p->n_left;
+ if (p->n_op == STARG)
+ p = p->n_left;
- switch (p->n_op) {
- case REG:
- return (!istreg(p->n_rval));
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
- case OREG:
- r = p->n_rval;
- if (R2TEST(r)) {
- if (istreg(R2UPK1(r)))
- return(0);
- r = R2UPK2(r);
- }
- return (!istreg(r));
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return (0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
- case UMUL:
- p = p->n_left;
- return (p->n_op != UMUL && shtemp(p));
- }
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
- if (optype(p->n_op) != LTYPE)
- return(0);
- return(1);
+ if (optype(p->n_op) != LTYPE)
+ return (0);
+ return (1);
#endif
}
void
adrcon(CONSZ val)
{
- printf(CONFMT, val);
+ printf(CONFMT, val);
}
void
-conput(FILE *fp, NODE *p)
+conput(FILE * fp, NODE * p)
{
- int val = p->n_lval;
-
- switch (p->n_op) {
- case ICON:
- if (p->n_name[0] != '\0') {
- fprintf(fp, "%s", p->n_name);
- if (val)
- fprintf(fp, "+%d", val);
- } else
- fprintf(fp, "%d", val);
- return;
-
- default:
- comperr("illegal conput");
- }
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput");
+ }
}
-/*ARGSUSED*/
+/* ARGSUSED */
void
-insput(NODE *p)
+insput(NODE * p)
{
- comperr("insput");
+ comperr("insput");
}
/*
- * Write out the upper address, like the upper register of a 2-register
- * reference, or the next memory location.
+ * Print lower or upper name of 64-bit register.
*/
-void
-upput(NODE *p, int size)
+static void
+print_reg64name(FILE *fp, int rval, int hi)
{
+ int off = 3 * (hi != 0);
- size /= SZCHAR;
- switch (p->n_op) {
- case REG:
- fputs(rnames[p->n_rval + 1], stdout);
- break;
-
- case NAME:
- case OREG:
- p->n_lval += size;
- adrput(stdout, p);
- p->n_lval -= size;
- break;
- case ICON:
- fprintf(stdout, CONFMT, p->n_lval >> 32);
- break;
- default:
- comperr("upput bad op %d size %d", p->n_op, size);
- }
+ fprintf(fp, "%c%c",
+ rnames[rval][off],
+ rnames[rval][off + 1]);
+ if (rnames[rval][off + 2])
+ fputc(rnames[rval][off + 2], fp);
}
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
void
-adrput(FILE *io, NODE *p)
+upput(NODE * p, int size)
{
- int r;
- /* output an address, with offsets, from p */
-
- if (p->n_op == FLD)
- p = p->n_left;
-
- switch (p->n_op) {
-
- case NAME:
- if (p->n_name[0] != '\0')
- fputs(p->n_name, io);
- if (p->n_lval != 0)
- fprintf(io, "+" CONFMT, p->n_lval);
- return;
-
- case OREG:
- r = p->n_rval;
-
- if (p->n_lval)
- fprintf(io, "%d", (int)p->n_lval);
-
- fprintf(io, "(%s)", rnames[p->n_rval]);
- return;
- case ICON:
- /* addressable value of the constant */
- //fputc('$', io);
- conput(io, p);
- return;
-
- case MOVE:
- case REG:
- fprintf(io, "%s", rnames[p->n_rval]);
- return;
-
- default:
- comperr("illegal address, op %d, node %p", p->n_op, p);
- return;
-
- }
+
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ print_reg64name(stdout, p->n_rval, 1);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
}
-/* This function changes the offset of a OREG when doing a type cast. */
void
-offchg(NODE *p)
+adrput(FILE * io, NODE * p)
{
+ int r;
+ /* output an address, with offsets, from p */
- if (p->n_op != SCONV) {
- comperr("illegal offchg");
- }
-
-#ifndef RTOLBYTES
- /* change the offset depending on source and target types */
- switch(p->n_left->n_type) {
- case SHORT:
- case USHORT:
- if (p->n_type == CHAR || p->n_type == UCHAR) {
- p->n_left->n_lval += 1;
- }
- break;
-
- case UNSIGNED:
- case ULONG:
- case INT:
- case LONG:
- if (p->n_type == CHAR || p->n_type == UCHAR) {
- p->n_left->n_lval += 3;
- } else if (p->n_type == SHORT || p->n_type == USHORT) {
- p->n_left->n_lval += 2;
- }
- break;
-
- /* This code is not tested!
- case LONGLONG:
- case ULONGLONG:
- if (p->n_type == CHAR || p->n_type == UCHAR) {
- p->n_lval += 7;
- } else if (p->n_type == SHORT || p->n_type == USHORT) {
- p->n_lval += 6;
- } else if (p->n_type == UNSIGNED || p->n_type == ULONG ||
- p->n_type == INT || p->n_type == LONG) {
-
- p->n_lval += 4;
- }
- break;
- */
- }
-#endif
+ if (p->n_op == FLD)
+ p = p->n_left;
- /* print the code for the OREG */
- if (p->n_left->n_lval) {
- printf("%d", (int)p->n_left->n_lval);
- }
-
- printf("(%s)", rnames[p->n_left->n_rval]);
-
-}
+ switch (p->n_op) {
+
+ case NAME:
+ if (p->n_name[0] != '\0')
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+
+ if (p->n_lval)
+ fprintf(io, "%d", (int) p->n_lval);
+
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ //fputc('$', io);
+ conput(io, p);
+ return;
+ case MOVE:
+ case REG:
+ if (DEUNSIGN(p->n_type) == LONGLONG)
+ print_reg64name(io, p->n_rval, 0);
+ else
+ fputs(rnames[p->n_rval], io);
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
-/* printf conditional and unconditional branches */
+ }
+}
+
+/* printf conditional and unconditional branches */
void
cbgen(int o, int lab)
{
}
-void branchfunc(NODE *p)
+void
+myreader(struct interpass * ipole)
{
- int o = p->n_op;
-
- if (o < EQ || o > GT)
- cerror("bad binary conditional branch: %s", opst[o]);
-
- switch(o) {
- case EQ:
- printf("beq ");
- adrput(stdout, getlr(p, 'L'));
- printf(", ");
- adrput(stdout, getlr(p, 'R'));
- printf(", ");
- break;
- case NE:
- printf("bne ");
- adrput(stdout, getlr(p, 'L'));
- printf(", ");
- adrput(stdout, getlr(p, 'R'));
- printf(", ");
- break;
- case LE:
- expand(p, 0, "blez A1, ");
- break;
- case LT:
- expand(p, 0, "bltz A1, ");
- break;
- case GE:
- expand(p, 0, "bgez A1, ");
- break;
- case GT:
- expand(p, 0, "bgez A1, ");
- break;
- }
- printf(".L%d\n", p->n_label);
- printf(" nop\n");
}
-#if 0
/*
- * Do some local optimizations that must be done after optim is called.
+ * Remove some PCONVs after OREGs are created.
*/
static void
-optim2(NODE *p)
+pconv2(NODE * p)
{
- int op = p->n_op;
- int m, ml;
- NODE *l;
-
- /* Remove redundant PCONV's */
- if (op == PCONV) {
- l = p->n_left;
- m = BTYPE(p->n_type);
- ml = BTYPE(l->n_type);
- if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT ||
- m == DOUBLE || m == STRTY || m == UNIONTY || m == ENUMTY ||
- m == UNSIGNED || m == ULONG || m == ULONGLONG) &&
- (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT ||
- ml == DOUBLE || ml == STRTY || ml == UNIONTY ||
- ml == ENUMTY || ml == UNSIGNED || ml == ULONG ||
- ml == ULONGLONG) && ISPTR(l->n_type)) {
- *p = *l;
- nfree(l);
- op = p->n_op;
- } else
- if (ISPTR(DECREF(p->n_type)) &&
- (l->n_type == INCREF(STRTY))) {
- *p = *l;
- nfree(l);
- op = p->n_op;
- } else
- if (ISPTR(DECREF(l->n_type)) &&
- (p->n_type == INCREF(INT) ||
- p->n_type == INCREF(STRTY) ||
- p->n_type == INCREF(UNSIGNED))) {
- *p = *l;
- nfree(l);
- op = p->n_op;
+ NODE *q;
+
+ if (p->n_op == PLUS) {
+ if (p->n_type == (PTR | SHORT) || p->n_type == (PTR | USHORT)) {
+ if (p->n_right->n_op != ICON)
+ return;
+ if (p->n_left->n_op != PCONV)
+ return;
+ if (p->n_left->n_left->n_op != OREG)
+ return;
+ q = p->n_left->n_left;
+ nfree(p->n_left);
+ p->n_left = q;
+ /*
+ * This will be converted to another OREG later.
+ */
}
-
- }
- /* Add constands, similar to the one in optim() */
- if (op == PLUS && p->n_right->n_op == ICON) {
- l = p->n_left;
- if (l->n_op == PLUS && l->n_right->n_op == ICON &&
- (p->n_right->n_name[0] == '\0' ||
- l->n_right->n_name[0] == '\0')) {
- l->n_right->n_lval += p->n_right->n_lval;
- if (l->n_right->n_name[0] == '\0')
- l->n_right->n_name = p->n_right->n_name;
- nfree(p->n_right);
- *p = *l;
- nfree(l);
}
- }
-
- /* Convert "PTR undef" (void *) to "PTR uchar" */
- /* XXX - should be done in MI code */
- if (BTYPE(p->n_type) == VOID)
- p->n_type = (p->n_type & ~BTMASK) | UCHAR;
}
-#endif
-static void
-myhardops(NODE *p)
+void
+mycanon(NODE * p)
{
- int ty = optype(p->n_op);
- NODE *l, *r, *q;
-
- if (ty == UTYPE)
- return myhardops(p->n_left);
- if (ty != BITYPE)
- return;
- myhardops(p->n_right);
- if (p->n_op != STASG)
- return;
-
- /*
- * If the structure size to copy is less than 32 byte, let it
- * be and generate move instructions later. Otherwise convert it
- * to memcpy() calls, unless it has a STCALL function as its
- * right node, in which case it is untouched.
- * STCALL returns are handled special.
- */
- if (p->n_right->n_op == STCALL || p->n_right->n_op == USTCALL)
- return;
- l = p->n_left;
- if (l->n_op == UMUL)
- l = nfree(l);
- else if (l->n_op == NAME) {
- l->n_op = ICON; /* Constant reference */
- l->n_type = INCREF(l->n_type);
- } else
- comperr("myhardops");
- r = p->n_right;
- q = mkbinode(CM, l, r, 0);
- q = mkbinode(CM, q, mklnode(ICON, p->n_stsize, 0, INT), 0);
- p->n_op = CALL;
- p->n_right = q;
- p->n_left = mklnode(ICON, 0, 0, 0);
- p->n_left->n_name = "memcpy";
+ walkf(p, pconv2);
}
void
-myreader(NODE *p)
+myoptim(struct interpass * ip)
{
- int e2print(NODE *p, int down, int *a, int *b);
- // walkf(p, optim2);
- myhardops(p);
- if (x2debug) {
- printf("myreader final tree:\n");
- fwalk(p, e2print, 0);
- }
}
/*
- * Remove some PCONVs after OREGs are created.
+ * Move data between registers. While basic registers aren't a problem,
+ * we have to handle the special case of overlapping composite registers.
*/
-static void
-pconv2(NODE *p)
+void
+rmove(int s, int d, TWORD t)
{
- NODE *q;
-
- if (p->n_op == PLUS) {
- if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
- if (p->n_right->n_op != ICON)
- return;
- if (p->n_left->n_op != PCONV)
- return;
- if (p->n_left->n_left->n_op != OREG)
- return;
- q = p->n_left->n_left;
- nfree(p->n_left);
- p->n_left = q;
- /*
- * This will be converted to another OREG later.
- */
- }
- }
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ if (s == d+1) {
+ /* dh = sl, copy low word first */
+ printf("\tmove ");
+ print_reg64name(stdout, d, 0);
+ print_reg64name(stdout, s, 0);
+ printf("\tmove ");
+ print_reg64name(stdout, d, 1);
+ print_reg64name(stdout, s, 1);
+ } else {
+ /* copy high word first */
+ printf("\tmove ");
+ print_reg64name(stdout, d, 1);
+ print_reg64name(stdout, s, 1);
+ printf("\tmove ");
+ print_reg64name(stdout, d, 0);
+ print_reg64name(stdout, s, 0);
+ }
+ printf("\n");
+ break;
+ case LDOUBLE:
+#ifdef notdef
+ /* a=b()*c(); will generate this */
+ comperr("bad float rmove: %d %d", s, d);
+#endif
+ break;
+ default:
+ printf("\tmove %s,%s\n", rnames[d], rnames[s]);
+ }
}
-void
-mycanon(NODE *p)
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ *
+ * On MIPS, we have:
+ *
+ * 32 32-bit registers (8 reserved)
+ * 26 64-bit pseudo registers (1 unavailable)
+ * 3? floating-point registers
+ */
+int
+COLORMAP(int c, int *r)
{
- walkf(p, pconv2);
+ int num = 0;
+
+ switch (c) {
+ case CLASSA:
+ num += r[CLASSA];
+ num += 2*r[CLASSB];
+ return num < 24;
+ case CLASSB:
+ num += 2*r[CLASSB];
+ num += r[CLASSA];
+ return num < 25;
+ case CLASSC:
+ num += r[CLASSC];
+ return num < 3;
+ }
+ assert(0);
+ return 0; /* XXX gcc */
}
-void
-mygenregs(NODE *p)
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
{
- if (p->n_op == MINUS && p->n_type == DOUBLE &&
- (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) {
- p->n_su |= DORIGHT;
- }
- /* Must walk down correct node first for logops to work */
- if (p->n_op != CBRANCH)
- return;
- p = p->n_left;
- if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG))
- return;
- p->n_su &= ~DORIGHT;
+ return CLASSA;
}
/*
- * Remove last goto.
+ * Calculate argument sizes.
*/
void
-myoptim(struct interpass *ip)
+lastcall(NODE * p)
{
-#if 0
- while (ip->sqelem.sqe_next->type != IP_EPILOG)
- ip = ip->sqelem.sqe_next;
- if (ip->type != IP_NODE || ip->ip_node->n_op != GOTO)
- comperr("myoptim");
- tfree(ip->ip_node);
- *ip = *ip->sqelem.sqe_next;
-#endif
-}
+ NODE *op = p;
+ int size = 0;
-struct hardops hardops[] = {
- { MUL, LONGLONG, "__muldi3" },
- { MUL, ULONGLONG, "__muldi3" },
- { DIV, LONGLONG, "__divdi3" },
- { DIV, ULONGLONG, "__udivdi3" },
- { MOD, LONGLONG, "__moddi3" },
- { MOD, ULONGLONG, "__umoddi3" },
- { RS, LONGLONG, "__ashrdi3" },
- { RS, ULONGLONG, "__lshrdi3" },
- { LS, LONGLONG, "__ashldi3" },
- { LS, ULONGLONG, "__ashldi3" },
-#if 0
- { STASG, PTR+STRTY, "memcpy" },
- { STASG, PTR+UNIONTY, "memcpy" },
+#ifdef PCC_DEBUG
+ if (x2debug)
+ printf("lastcall:\n");
#endif
- { 0 },
-};
-void
-rmove(int s, int d, TWORD t)
-{
- printf(" move %s, %s\n", rnames[d], rnames[s]);
+ p->n_qual = 0;
+ if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
+ return;
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ size += argsiz(p->n_right);
+ size += argsiz(p);
+ op->n_qual = size; /* XXX */
}
+static int
+argsiz(NODE * p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONGLONG || t == FLOAT || t > BTMASK)
+ return 4;
+ if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
+ return 8;
+ if (t == LDOUBLE)
+ return 12;
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
-
+/*
+ * Special shapes.
+ */
+int
+special(NODE * p, int shape)
+{
+ return SRNOPE;
+}
diff --git a/usr.bin/pcc/mips/macdefs.h b/usr.bin/pcc/mips/macdefs.h
index 71e5b17f955..20f0cf37d02 100644
--- a/usr.bin/pcc/mips/macdefs.h
+++ b/usr.bin/pcc/mips/macdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: macdefs.h,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: macdefs.h,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -35,6 +35,10 @@
* Machine-dependent defines for both passes.
*/
+#if TARGOS == netbsd
+#define USE_GAS
+#endif
+
/*
* Convert (multi-)character constant to integer.
* Assume: If only one value; store at left side (char size), otherwise
@@ -42,17 +46,18 @@
*/
#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
-#define ARGINIT 64 /* # bits above fp where arguments start */
-#define AUTOINIT 0 /* # bits below fp where automatics start */
+#define ARGINIT (12*8) /* # bits above fp where arguments start */
+#define AUTOINIT (0) /* # bits below fp where automatics start */
/*
* Storage space requirements
*/
#define SZCHAR 8
+#define SZBOOL 32
#define SZINT 32
#define SZFLOAT 32
#define SZDOUBLE 64
-#define SZLDOUBLE 96
+#define SZLDOUBLE 128
#define SZLONG 32
#define SZSHORT 16
#define SZLONGLONG 64
@@ -62,6 +67,7 @@
* Alignment constraints
*/
#define ALCHAR 8
+#define ALBOOL 32
#define ALINT 32
#define ALFLOAT 32
#define ALDOUBLE 32
@@ -92,8 +98,10 @@
#define MAX_LONGLONG 0x7fffffffffffffffLL
#define MAX_ULONGLONG 0xffffffffffffffffULL
-/* Default char is unsigned */
#undef CHAR_UNSIGNED
+#define TARGET_STDARGS
+#define BOOL_TYPE INT
+#define WCHAR_TYPE INT
/*
* Use large-enough types.
@@ -103,31 +111,17 @@ typedef unsigned long long U_CONSZ;
typedef long long OFFSZ;
#define CONFMT "%lld" /* format for printing constants */
-#define LABFMT ".L%d" /* format for printing labels */
-#define STABLBL ".LL%d" /* format for stab (debugging) labels */
-#ifdef FORTRAN
-#define XL 8
-#define FLABELFMT "%s:\n"
-#define USETEXT ".text"
-#define USECONST ".data\t0" /* XXX - fix */
-#define USEBSS ".data\t1" /* XXX - fix */
-#define USEINIT ".data\t2" /* XXX - fix */
-#define MAXREGVAR 3 /* XXX - fix */
-#define BLANKCOMMON "_BLNK_"
-#define MSKIREG (M(TYSHORT)|M(TYLONG))
-#define TYIREG TYLONG
-#define FSZLENG FSZLONG
-#define FUDGEOFFSET 1
-#define AUTOREG EBP
-#define ARGREG EBP
-#define ARGOFFSET 4
+#ifdef USE_GAS
+#define LABFMT "$L%d" /* format for printing labels */
+#define STABLBL "$LL%d" /* format for stab (debugging) labels */
+#else
+#define LABFMT "L%d" /* format for printing labels */
+#define STABLBL "LL%d" /* format for stab (debugging) labels */
#endif
#define BACKAUTO /* stack grows negatively for automatics */
#define BACKTEMP /* stack grows negatively for temporaries */
-#define MYP2TREE(p) myp2tree(p);
-
#undef FIELDOPS /* no bit-field instructions */
#define RTOLBYTES /* bytes are numbered right to left */
@@ -136,92 +130,194 @@ typedef long long OFFSZ;
/* Definitions mostly used in pass2 */
#define BYTEOFF(x) ((x)&03)
-#define wdal(k) (BYTEOFF(k)==0)
-#define BITOOR(x) ((x)/SZCHAR) /* bit offset to oreg offset */
-
-#define STOARG(p)
-#define STOFARG(p)
-#define STOSTARG(p)
-#define genfcall(a,b) gencall(a,b)
+#define BITOOR(x) (x) /* bit offset to oreg offset */
#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
(t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1)
/*
* Register names. These must match rnames[] and rstatus[] in local2.c.
- * The crazy order of the registers are due to the current register
- * allocations strategy and should be fixed.
*/
-#define T0 0
-#define T1 1
-#define T2 2
-#define T3 3
-#define T4 4
-#define T5 5
-#define T6 6
-#define T7 7
-#define T8 8
-#define T9 9
-
-#define V0 10
-#define V1 11
-
-#define ZERO 12
-#define AT 13
-
-#define A0 14
-#define A1 15
-#define A2 16
-#define A3 17
-
-#define S0 18
-#define S1 19
-#define S2 20
-#define S3 21
-#define S4 22
-#define S5 23
-#define S6 24
-#define S7 25
-
-#define K0 26
-#define K1 27
-
-#define GP 28
-#define SP 29
-#define FP 30
-#define RA 31
-
-#define RETREG V0 /* Return register */
-#define REGSZ 32 /* number of registers */
+#define ZERO 0
+#define AT 1
+#define V0 2
+#define V1 3
+#define A0 4
+#define A1 5
+#define A2 6
+#define A3 7
+#if defined(MIPS_N32) || defined(MIPS_N64)
+#define A4 8
+#define A5 9
+#define A6 10
+#define A7 11
+#define T0 12
+#define T1 13
+#define T2 14
+#define T3 15
+#else
+#define T0 8
+#define T1 9
+#define T2 10
+#define T3 11
+#define T4 12
+#define T5 13
+#define T6 14
+#define T7 15
+#endif
+#define S0 16
+#define S1 17
+#define S2 18
+#define S3 19
+#define S4 20
+#define S5 21
+#define S6 22
+#define S7 23
+#define T8 24
+#define T9 25
+#define K0 26
+#define K1 27
+#define GP 28
+#define SP 29
+#define FP 30
+#define RA 31
+
+#define V0V1 32
+#define A0A1 33
+#define A1A2 34
+#define A2A3 35
+#if defined(MIPS_N32) || defined(MIPS_N64)
+#define A3A4 36
+#define A4A5 37
+#define A5A6 38
+#define A6A7 39
+#define T0T1 41
+#define T1T2 42
+#define T2T3 43
+#else
+#define T0T1 37
+#define T1T2 38
+#define T2T3 39
+#define T3T4 40
+#define T4T5 41
+#define T5T6 42
+#define T6T7 43
+#endif
+#define T8T9 44
+#define S0S1 45
+#define S1S2 46
+#define S2S3 47
+#define S3S4 48
+#define S4S5 49
+#define S5S6 50
+#define S6S7 51
+
+#define F0 52
+#define F1 53
+#define F2 54
+
+#define MAXREGS 55
+#define NUMCLASS 3
+
+#define RETREG(x) ((x) == ULONGLONG || (x) == LONGLONG ? V0V1 : V0)
#define FPREG FP /* frame pointer */
-#define STKREG SP /* stack pointer */
-#define MINRVAR S0 /* first register variable */
-#define MAXRVAR S7 /* last register variable */
+#define STKREG SP
-#define NREGREG (MAXRVAR-MINRVAR+1)
+#if defined(MIPS_N32) || defined(MIPS_N64)
+#define MIPS_NARGREGS 8
+#else
+#define MIPS_NARGREGS 4
+#endif
-/*
- * Register types are described by bitmasks.
- */
-#define AREGS (REGBIT(T0)|REGBIT(T1)|REGBIT(T2)|REGBIT(T3)| \
- REGBIT(T4)|REGBIT(T5)|REGBIT(T6)|REGBIT(T7)|REGBIT(T8)|REGBIT(T9)|\
- REGBIT(V0)|REGBIT(V1)|REGBIT(A0)|REGBIT(A1)|REGBIT(A2)|REGBIT(A3)|\
- REGBIT(S0)|REGBIT(S1)|REGBIT(S2)|REGBIT(S3)|REGBIT(S4)|REGBIT(S5)|\
- REGBIT(S6)|REGBIT(S7))
-#define TAREGS (REGBIT(T0)|REGBIT(T1)|REGBIT(T2)|REGBIT(T3)|REGBIT(T4)|\
- REGBIT(T5)|REGBIT(T6)|REGBIT(T7)|REGBIT(T8)|REGBIT(T9)|\
- REGBIT(V0)|REGBIT(V1))
-
-/* For floating point? */
-#define BREGS 0xff00
-#define TBREGS BREGS
-
-//#define MYADDEDGE(x, t) if (t < INT) { AddEdge(x, ESI); AddEdge(x, EDI); }
-#define MYADDEDGE(x, t)
-#define PCLASS(p) SAREG
-
-#define MYREADER(p) myreader(p)
-#define MYCANON(p) mycanon(p)
-#define MYOPTIM
-
-#define special(a, b) SRNOPE
+#define RSTATUS \
+ 0, 0, \
+ SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \
+ SAREG|TEMPREG, SAREG|TEMPREG, \
+ 0, 0, \
+ 0, 0, 0, 0, \
+ \
+ SBREG|TEMPREG, \
+ SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \
+ SBREG|TEMPREG, /* only available on n32/n64 */ \
+ SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \
+ SBREG|TEMPREG, /* only available on o32 */ \
+ SBREG|TEMPREG, \
+ SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \
+ SBREG, SBREG, SBREG, SBREG, \
+ SBREG, SBREG, SBREG, \
+ SCREG, SCREG, SCREG
+
+#define ROVERLAP \
+ { -1 }, { -1 }, \
+ { V0V1, -1 }, { V0V1, -1 }, \
+ { A0A1, -1 }, \
+ { A0A1, A1A2, -1 }, \
+ { A1A2, A2A3, -1 }, \
+ { A2A3, -1 }, \
+ \
+ { T0T1, -1 }, \
+ { T0T1, T1T2, -1 }, \
+ { T1T2, T2T3, -1 }, \
+ { T2T3, T3T4, -1 }, \
+ { T3T4, T4T5, -1 }, \
+ { T4T5, T5T6, -1 }, \
+ { T5T6, T6T7, -1 }, \
+ { T6T7, -1 }, \
+ \
+ { S0S1, -1 }, \
+ { S0S1, S1S2, -1 }, \
+ { S1S2, S2S3, -1 }, \
+ { S2S3, S3S4, -1 }, \
+ { S3S4, S4S5, -1 }, \
+ { S4S5, S5S6, -1 }, \
+ { S5S6, S6S7, -1 }, \
+ { S6S7, -1 }, \
+ \
+ { T8T9, -1 }, \
+ { T8T9, -1 }, \
+ \
+ { -1 }, { -1 }, \
+ { -1 }, { -1 }, { -1 }, { -1 }, \
+ \
+ { V0, V1, -1 }, \
+ \
+ { A0, A1, -1 }, \
+ { A1, A2, -1 }, \
+ { A2, A3, -1 }, \
+ \
+ { -1 }, /* only useful on n32/n64 */ \
+ { T0, T1, T1T2, -1 }, \
+ { T1, T2, T0T1, T2T3, -1 }, \
+ { T2, T3, T1T2, T3T4, -1 }, \
+ { T3, T4, T2T3, T4T5, -1 }, /* only useful on o32 */ \
+ { T4, T5, T3T4, T5T6, -1 }, \
+ { T5, T6, T4T5, T6T7, -1 }, \
+ { T6, T7, T5T6, -1 }, \
+ \
+ { T8, T9, -1 }, \
+ \
+ { S0, S1, S1S2, -1 }, \
+ { S1, S2, S0S1, S2S3, -1 }, \
+ { S2, S3, S1S2, S3S4, -1 }, \
+ { S3, S4, S2S3, S4S5, -1 }, \
+ { S4, S5, S3S4, S5S6, -1 }, \
+ { S5, S6, S4S5, S6S7, -1 }, \
+ { S6, S7, S5S6, -1 }, \
+ \
+ { -1 }, \
+ { -1 }, \
+ { -1 },
+
+
+#define GCLASS(x) (x < 32 ? CLASSA : (x < 52 ? CLASSB : CLASSC))
+#define PCLASS(p) (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \
+ (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SCREG : SAREG))
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+
+int COLORMAP(int c, int *r);
diff --git a/usr.bin/pcc/mips/order.c b/usr.bin/pcc/mips/order.c
index 9a028f6092c..bd6850a6f89 100644
--- a/usr.bin/pcc/mips/order.c
+++ b/usr.bin/pcc/mips/order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: order.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: order.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -31,15 +31,13 @@
* Simon Olsson (simols-1@student.ltu.se) 2005.
*/
-# include "pass2.h"
-
-int canaddr(NODE *);
+#include "pass2.h"
/* should we delay the INCR or DECR operation p */
int
-deltest(NODE *p)
+deltest(NODE * p)
{
- return 0;
+ return 0;
}
/*
@@ -47,64 +45,62 @@ deltest(NODE *p)
* XXX - nothing can be autoincremented for now.
*/
int
-autoincr(NODE *p)
+autoincr(NODE * p)
{
- return 0;
+ return 0;
}
-/* is it legal to make an OREG or NAME entry which has an
- * offset of off, (from a register of r), if the
- * resulting thing had type t */
+/*
+ * is it legal to make an OREG or NAME entry which has an offset of off,
+ * (from a register of r), if the resulting thing had type t
+ */
int
notoff(TWORD t, int r, CONSZ off, char *cp)
{
- return(0); /* YES */
+ return (0); /* YES */
}
/*
* Turn a UMUL-referenced node into OREG.
*/
-int
-offstar(NODE *p)
+void
+offstar(NODE * p, int shape)
{
- if (x2debug)
- printf("offstar(%p)\n", p);
-
- if( p->n_op == PLUS || p->n_op == MINUS ){
- if( p->n_right->n_op == ICON ){
- geninsn(p->n_left, INTAREG|INAREG);
- p->n_su = -1;
- return 1;
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (p->n_op == PLUS || p->n_op == MINUS) {
+ if (p->n_right->n_op == ICON) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
}
- }
- geninsn(p, INTAREG|INAREG);
- return 0;
+ (void)geninsn(p, INAREG);
}
/*
- * Shape matches for UMUL. Cooperates with offstar().
+ * Do the actual conversion of offstar-found OREGs into real OREGs.
*/
-int
-shumul(NODE *p)
+void
+myormake(NODE * q)
{
-
- if (x2debug)
- printf("shumul(%p)\n", p);
-
- /* Always turn it into OREG on x86 */
- return SOREG;
+ if (x2debug)
+ printf("myormake(%p)\n", q);
}
/*
- * Rewrite increment/decrement operation.
+ * Shape matches for UMUL. Cooperates with offstar().
*/
int
-setincr(NODE *p)
+shumul(NODE * p)
{
- if (x2debug)
- printf("setincr(%p)\n", p);
+ if (x2debug)
+ printf("shumul(%p)\n", p);
- return(0);
+ /* Always turn it into OREG */
+ return SOREG;
}
/*
@@ -112,29 +108,29 @@ setincr(NODE *p)
* Called as a result of table lookup.
*/
int
-setbin(NODE *p)
+setbin(NODE * p)
{
- if (x2debug)
- printf("setbin(%p)\n", p);
- return 0;
+ if (x2debug)
+ printf("setbin(%p)\n", p);
+ return 0;
}
/* setup for assignment operator */
int
-setasg(NODE *p, int cookie)
+setasg(NODE * p, int cookie)
{
- if (x2debug)
- printf("setasg(%p)\n", p);
- return(0);
+ if (x2debug)
+ printf("setasg(%p)\n", p);
+ return (0);
}
/* setup for unary operator */
int
-setuni(NODE *p, int cookie)
+setuni(NODE * p, int cookie)
{
- return 0;
+ return 0;
}
/*
@@ -145,118 +141,145 @@ setuni(NODE *p, int cookie)
* - mask is registers that will be clobbered.
*/
struct rspecial *
-nspecial(struct optab *q)
+nspecial(struct optab * q)
{
- static int v0[] = { V0, -1 };
- static int v0v1[] = { V0, V1, -1 };
-
- static struct rspecial ucall = { v0, 0, v0v1, v0 };
+ switch (q->op) {
+
+ case MOD:
+ case DIV:
+ case RS:
+ case LS:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+#if 0
+// <stdin>, line 6: compiler error: Coalesce: src class 1, dst class 2
+ { NLEFT, A0A1 },
+ { NRIGHT, A2A3 },
+ { NRES, V0V1 },
+#endif
+ { 0 },
+ };
+ return s;
+ }
+ printf("op: %d\n", q->op);
+ printf("::: > %d\n", q->ltype);
+ break;
+
+ case STASG:
+ {
+ static struct rspecial s[] = {
+ { NEVER, A0 },
+ { NRIGHT, A1 },
+ { NEVER, A2 },
+ { NRES, A0 },
+ { 0 } };
+ return s;
+ }
+ }
- switch (q->op) {
+ comperr("nspecial entry %d: %s", q - table, q->cstring);
- default:
- comperr("nspecial entry %d", q - table);
- }
- return 0; /* XXX gcc */
+ return 0; /* XXX gcc */
}
+#if 0
/*
* Splitup a function call and give away its arguments first.
*/
void
-gencall(NODE *p, NODE *prev)
+gencall(NODE * p, NODE * prev)
{
- NODE *n = 0; /* XXX gcc */
- static int storearg(NODE *);
- int o = p->n_op;
- int ty = optype(o);
-
- if (ty == LTYPE)
- return;
-
- switch (o) {
- case CALL:
- /* Normal call, just push args and be done with it */
- p->n_op = UCALL;
-
- gencall(p->n_left, p);
- p->n_rval = storearg(p->n_right);
-
- break;
-
- case UFORTCALL:
- case FORTCALL:
- comperr("FORTCALL");
-
- case USTCALL:
- case STCALL:
- /*
- * Structure return. Look at the node above
- * to decide about buffer address:
- * - FUNARG, allocate space on stack, don't remove.
- * - nothing, allocate space on stack and remove.
- * - STASG, get the address of the left side as arg.
- * - FORCE, this ends up in a return, get supplied addr.
- * (this is not pretty, but what to do?)
- */
- if (prev == NULL || prev->n_op == FUNARG) {
- /* Create nodes to generate stack space */
- n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT),
- mkbinode(MINUS, mklnode(REG, 0, STKREG, INT),
- mklnode(ICON, p->n_stsize, 0, INT), INT), INT);
- //printf("stsize %d\n", p->n_stsize);
- pass2_compile(ipnode(n));
- } else if (prev->n_op == STASG) {
- n = prev->n_left;
- if (n->n_op == UMUL)
- n = nfree(n);
- else if (n->n_op == NAME) {
- n->n_op = ICON; /* Constant reference */
- n->n_type = INCREF(n->n_type);
- } else
- comperr("gencall stasg");
- } else if (prev->n_op == FORCE) {
- ; /* do nothing here */
- } else {
- comperr("gencall bad op %d", prev->n_op);
+ NODE *n = 0; /* XXX gcc */
+ static int storearg(NODE *);
+ int o = p->n_op;
+ int ty = optype(o);
+
+ if (ty == LTYPE)
+ return;
+
+ switch (o) {
+ case CALL:
+ /* Normal call, just push args and be done with it */
+ p->n_op = UCALL;
+
+ gencall(p->n_left, p);
+ p->n_rval = storearg(p->n_right);
+
+ break;
+
+ case UFORTCALL:
+ case FORTCALL:
+ comperr("FORTCALL");
+
+ case USTCALL:
+ case STCALL:
+ /*
+ * Structure return. Look at the node above
+ * to decide about buffer address:
+ * - FUNARG, allocate space on stack, don't remove.
+ * - nothing, allocate space on stack and remove.
+ * - STASG, get the address of the left side as arg.
+ * - FORCE, this ends up in a return, get supplied addr.
+ * (this is not pretty, but what to do?)
+ */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ /* Create nodes to generate stack space */
+ n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT),
+ mkbinode(MINUS, mklnode(REG, 0, STKREG, INT),
+ mklnode(ICON, p->n_stsize, 0, INT), INT), INT);
+ //printf("stsize %d\n", p->n_stsize);
+ pass2_compile(ipnode(n));
+ } else if (prev->n_op == STASG) {
+ n = prev->n_left;
+ if (n->n_op == UMUL)
+ n = nfree(n);
+ else if (n->n_op == NAME) {
+ n->n_op = ICON; /* Constant reference */
+ n->n_type = INCREF(n->n_type);
+ } else
+ comperr("gencall stasg");
+ } else if (prev->n_op == FORCE) {
+ ; /* do nothing here */
+ } else {
+ comperr("gencall bad op %d", prev->n_op);
+ }
+
+ /* Deal with standard arguments */
+ gencall(p->n_left, p);
+ if (o == STCALL) {
+ p->n_op = USTCALL;
+ p->n_rval = storearg(p->n_right);
+ } else
+ p->n_rval = 0;
+ /* push return struct address */
+ if (prev == NULL || prev->n_op == FUNARG) {
+ n = mklnode(REG, 0, STKREG, INT);
+ if (p->n_rval)
+ n = mkbinode(PLUS, n,
+ mklnode(ICON, p->n_rval, 0, INT), INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ if (prev == NULL)
+ p->n_rval += p->n_stsize / 4;
+ } else if (prev->n_op == FORCE) {
+ /* return value for this function */
+ n = mklnode(OREG, 8, FP, INT);
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ p->n_rval++;
+ } else {
+ pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
+ n = p;
+ *prev = *p;
+ nfree(n);
+ }
+ //printf("end stcall\n");
+ break;
+
+ default:
+ if (ty != UTYPE)
+ gencall(p->n_right, p);
+ gencall(p->n_left, p);
+ break;
}
-
- /* Deal with standard arguments */
- gencall(p->n_left, p);
- if (o == STCALL) {
- p->n_op = USTCALL;
- p->n_rval = storearg(p->n_right);
- } else
- p->n_rval = 0;
- /* push return struct address */
- if (prev == NULL || prev->n_op == FUNARG) {
- n = mklnode(REG, 0, STKREG, INT);
- if (p->n_rval)
- n = mkbinode(PLUS, n,
- mklnode(ICON, p->n_rval, 0, INT), INT);
- pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
- if (prev == NULL)
- p->n_rval += p->n_stsize/4;
- } else if (prev->n_op == FORCE) {
- /* return value for this function */
- n = mklnode(OREG, 8, FPREG, INT);
- pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
- p->n_rval++;
- } else {
- pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT)));
- n = p;
- *prev = *p;
- nfree(n);
- }
- //printf("end stcall\n");
- break;
-
- default:
- if (ty != UTYPE)
- gencall(p->n_right, p);
- gencall(p->n_left, p);
- break;
- }
}
/*
@@ -264,87 +287,112 @@ gencall(NODE *p, NODE *prev)
* Returns the number of registers needed to hold the argument.
*/
static int
-storearg(NODE *p)
+storearg(NODE * p)
{
- static void storecall(NODE *);
- struct interpass *ip;
- NODE *np;
- int tsz, recval;
- TWORD t;
- extern int thisline;
- static int counter = 0; /* Count number of register arguments */
-
- ip = tmpalloc(sizeof(struct interpass));
- ip->type = IP_NODE;
- ip->lineno = thisline;
-
- if (p->n_op == CM) {
- np = p->n_left;
-
- if (p->n_right->n_op == STARG) {
- NODE *op = p;
- p = p->n_right;
- nfree(op);
- tsz = (p->n_stsize + 3) / 4;
+ static void storecall(NODE *);
+ struct interpass *ip;
+ NODE *np;
+ int tsz, recval;
+ TWORD t;
+ extern int thisline;
+ static int counter = 0; /* Count number of register arguments */
+
+ ip = tmpalloc(sizeof(struct interpass));
+ ip->type = IP_NODE;
+ ip->lineno = thisline;
+
+ if (p->n_op == CM) {
+ np = p->n_left;
+
+ if (p->n_right->n_op == STARG) {
+ NODE *op = p;
+ p = p->n_right;
+ nfree(op);
+ tsz = (p->n_stsize + 3) / 4;
+ } else {
+ p->n_type = p->n_right->n_type;
+ p->n_left = p->n_right;
+
+
+ /*
+ * Process left subtree first, to get arguments in
+ * the correct order on the stack as well as in the
+ * registers.
+ */
+ recval = storearg(np);
+
+ /* Not a register argument */
+ if (!(counter < 4)) {
+ p->n_op = FUNARG;
+ ip->ip_node = p;
+ pass2_compile(ip);
+ tsz = szty(p->n_type);
+
+ } else {/* Else fetch value from stack to register */
+ t = p->n_type;
+
+ pass2_compile(ipnode(mkbinode(ASSIGN,
+ mklnode(REG, 0, A0 + counter, t),
+ p->n_right, t)));
+ tsz = 0;
+ counter++;
+
+ /* Free the comma node */
+ nfree(p);
+
+ }
+ }
+
+ return recval + tsz;
} else {
- p->n_type = p->n_right->n_type;
- p->n_left = p->n_right;
-
-
- /* Process left subtree first, to get arguments in the correct
- order on the stack as well as in the registers. */
- recval = storearg(np);
-
- /* Not a register argument */
- if (!(counter < 4)) {
- p->n_op = FUNARG;
+ if (p->n_op != STARG) {
+ /* Register argument */
+ if (counter < 4) {
+ t = p->n_type;
+
+ pass2_compile(ipnode(mkbinode(ASSIGN,
+ mklnode(REG, 0, A0 + counter, t),
+ p, t)));
+ counter++;
+
+ return 0;
+ } else {
+ np = talloc();
+
+ np->n_type = p->n_type;
+ np->n_op = FUNARG;
+ np->n_left = p;
+ p = np;
+ tsz = szty(p->n_type);
+ }
+ } else {
+ p->n_op = FUNARG;
+ tsz = (p->n_stsize + 3) / 4;
+ }
ip->ip_node = p;
pass2_compile(ip);
- tsz = szty(p->n_type);
-
- } else { /* Else fetch value from stack to register */
- t = p->n_type;
-
- pass2_compile(ipnode(mkbinode(ASSIGN,
- mklnode(REG, 0, A0+counter, t),
- p->n_right, t)));
- tsz = 0;
- counter++;
+ return tsz;
+ }
+}
+#endif
- /* Free the comma node */
- nfree(p);
+/*
+ * Set evaluation order of a binary node if it differs from default.
+ */
+int
+setorder(NODE * p)
+{
+ return 0; /* nothing differs */
+}
+/*
+ * Set registers "live" at function calls (like arguments in registers).
+ * This is for liveness analysis of registers.
+ */
+int *
+livecall(NODE *p)
+{
+ static int r[1] = { -1 }; /* Terminate with -1 */
- }
- }
-
- return recval + tsz;
- } else {
- if (p->n_op != STARG) {
- /* Register argument */
- if (counter < 4) {
- t = p->n_type;
-
- pass2_compile(ipnode(mkbinode(ASSIGN,
- mklnode(REG, 0, A0+counter, t),
- p, t)));
- counter++;
-
- return 0;
- } else {
- np = talloc();
-
- np->n_type = p->n_type;
- np->n_op = FUNARG;
- np->n_left = p;
- p = np;
- tsz = szty(p->n_type);
- }
- } else {
- p->n_op = FUNARG;
- tsz = (p->n_stsize + 3) / 4;
- }
- ip->ip_node = p;
- pass2_compile(ip);
- return tsz;
- }
+ return &r[0];
}
+
diff --git a/usr.bin/pcc/mips/table.c b/usr.bin/pcc/mips/table.c
index 78d0555c28a..20073097182 100644
--- a/usr.bin/pcc/mips/table.c
+++ b/usr.bin/pcc/mips/table.c
@@ -1,9 +1,7 @@
-/* $OpenBSD: table.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
+/* $OpenBSD: table.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */
/*
* Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
-
-
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,638 +29,797 @@
/*
* MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
* Simon Olsson (simols-1@student.ltu.se) 2005.
+ *
+ * It appears that the target machine was big endian. The original
+ * code contained many endian aspects which are now handled in
+ * machine-independent code.
+ *
+ * On MIPS, the assembler does an amazing amount of work for us.
+ * We don't have to worry about PIC, nor about finding the address
+ * of SNAMES. Whenever possible, we defer the work to the assembler.
*/
-# include "pass2.h"
+#include "pass2.h"
-# define TLL TLONGLONG|TULONGLONG
-# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
-# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
-# define ANYFIXED ANYSIGNED|ANYUSIGNED
-# define TUWORD TUNSIGNED|TULONG
-# define TSWORD TINT|TLONG
-# define TWORD TUWORD|TSWORD
+#define TLL TLONGLONG|TULONGLONG
+#define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
+#define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
+#define ANYFIXED ANYSIGNED|ANYUSIGNED
+#define TUWORD TUNSIGNED|TULONG
+#define TSWORD TINT|TLONG
+#define TWORD TUWORD|TSWORD
struct optab table[] = {
/* First entry must be an empty entry */
{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
-
/*
* A bunch conversions of integral<->integral types
*/
-
-
-
-
-
/* convert char to (u)short */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TCHAR,
- SAREG, TSHORT|TUSHORT,
+ SAREG, TWORD|SHORT|TUSHORT,
NAREG, RESC1,
- " lb A1, ZA\n nop\n", },
+ " lb A1,AL # convert oreg char to (u)short/word\n"
+ " nop\n", },
/* convert uchar to (u)short */
-{ SCONV, INTAREG,
- SOREG, TUCHAR,
- SAREG, TSHORT|TUSHORT,
- NAREG, RESC1,
- " lbu A1, ZA\n nop\n", },
-
-/* convert char to (u)long */
-{ SCONV, INTAREG,
- SOREG, TCHAR,
- SAREG, TWORD,
- NAREG, RESC1,
- " lb A1, ZA\n nop\n", },
-
-/* convert uchar to (u)long */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TUCHAR,
- SAREG, TWORD,
+ SAREG, TWORD|TSHORT|TUSHORT,
NAREG, RESC1,
- " lbu A1, ZA\n nop\n", },
+ " lbu A1,AL # convert oreg uchar to (u)short\n"
+ " nop\n", },
/* convert char to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TCHAR,
- SAREG, TLL,
- NAREG, RESC1,
- " lb U1, ZA\n"
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lb U1,AL # convert oreg char to (u)longlong\n"
" nop\n"
- " sra A1, U1, 31\n"
- " sub A1, $zero, A1\n", },
+ " sra A1,U1,31\n"
+ " sub A1,0,A1\n", },
/* convert uchar to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TUCHAR,
- SAREG, TLL,
- NAREG, RESC1,
- " lbu U1, ZA\n"
- " move A1, $zero\n", },
-
-
-
-
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lbu U1,AL # convert oreg uchar to (u)longlong\n"
+ " move A1,0\n", },
/* convert (u)short to char */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TSHORT|TUSHORT,
SAREG, TCHAR,
NAREG, RESC1,
- " lb A1, ZA\n nop\n", },
+ " lb A1,AL # convert oreg (u)short to char (endianness problem?)\n"
+ " nop\n", },
/* convert (u)short to uchar */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TSHORT|TUSHORT,
SAREG, TUCHAR,
NAREG, RESC1,
- " lbu A1, ZA\n nop\n", },
-
+ " lbu A1,AL # convert oreg (u)short to uchar (endianness problem?)\n"
+ " nop\n", },
/* convert short to (u)long */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TSHORT,
SAREG, TWORD,
NAREG, RESC1,
- " lh A1, ZA\n nop\n", },
+ " lh A1,AL # convert oreg short to (u)int\n"
+ " nop\n", },
/* convert ushort to (u)long */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TUSHORT,
SAREG, TWORD,
NAREG, RESC1,
- " lhu A1, ZA\n nop\n", },
+ " lhu A1,AL # convert oreg ushort to (u)int\n"
+ " nop\n", },
/* convert short to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TSHORT,
- SAREG, TLL,
- NAREG, RESC1,
- " lh U1, ZA\n"
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lh U1,AL # convert oreg short to (u)longlong\n"
" nop\n"
- " sra A1, U1, 31\n"
- " sub A1, $zero, A1\n", },
+ " sra A1,U1,31\n"
+ " sub A1,0,A1\n", },
/* convert ushort to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TUSHORT,
- SAREG, TLL,
- NAREG, RESC1,
- " lhu U1, ZA\n"
- " move A1, $zero\n", },
-
-
-
-
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lhu U1,AL # convert oreg (u)short to (u)longlong\n"
+ " move A1,0\n", },
/* convert (u)long to char */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TWORD,
SAREG, TCHAR,
NAREG, RESC1,
- " lb A1, ZA\n nop\n", },
+ " lb A1,AL # convert oreg word to char (endianness problem here?)\n"
+ " nop\n", },
/* convert (u)long to uchar */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TWORD,
SAREG, TUCHAR,
NAREG, RESC1,
- " lbu A1, ZA\n nop\n", },
+ " lbu AL,AR # convert oreg word to uchar (endianness problem here?)\n"
+ " nop\n", },
/* convert (u)long to short */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TWORD,
SAREG, TSHORT,
NAREG, RESC1,
- " lh A1, ZA\n nop\n", },
+ " lh AL,AR # convert oreg word to short (endianness problem here?)\n"
+ " nop\n", },
/* convert (u)long to ushort */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TWORD,
SAREG, TUSHORT,
NAREG, RESC1,
- " lhu A1, ZA\n nop\n", },
+ " lhu A1,AR # convert oreg word to ushort (endianness problem here?)\n"
+ " nop\n", },
/* convert long to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TSWORD,
- SAREG, TLL,
- NAREG, RESC1,
- " lw U1, ZA\n"
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lw A1,AL # convert oreg int/long to (u)llong (endianness problem here?)\n"
" nop\n"
- " sra A1, U1, 31\n"
- " sub A1, $zero, A1\n", },
+ " sra U1,A1,31\n"
+ " sub U1,0,U1\n", },
/* convert ulong to (u)long long */
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SOREG, TUWORD,
- SAREG, TLL,
- NAREG, RESC1,
- " lw U1, ZA\n"
- " move A1, $zero\n", },
-
-
-
-
+ SBREG, TLL,
+ NBREG, RESC1,
+ " lw A1,AL # convert oreg (u)int to (u)llong (endianness problem here?)\n"
+ " move U1,0\n", },
/* convert (u)long long to char */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TCHAR,
NAREG, RESC1,
- " lb A1, ZA\n nop\n", },
+ " lb A1,AL # convert oreg (u)llong to char (endianness problem here?)\n"
+ " nop\n", },
/* convert (u)long long to uchar */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TUCHAR,
NAREG, RESC1,
- " lbu A1, ZA\n nop\n", },
+ " lbu A1,AL # convert oreg (u)llong to uchar (endianness problem?)\n"
+ " nop\n", },
/* convert (u)long long to short */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TSHORT,
NAREG, RESC1,
- " lh A1, ZA\n nop\n", },
+ " lh A1,AL # convert oreg (u)llong to short (endianness problem?)\n"
+ " nop\n", },
/* convert (u)long long to ushort */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TUSHORT,
NAREG, RESC1,
- " lhu A1, ZA\n nop\n", },
+ " lhu A1,AL # convert oreg (u)llong to ushort (endianness problem here?)\n"
+ " nop\n", },
/* convert (u)long long to long */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TSWORD,
NAREG, RESC1,
- " lw U1, ZA\n nop\n", },
+ " lw U1,AL # convert oreg (u)llong to short (endianness problem here?)\n"
+ " nop\n", },
-/* convert (u)long long to (u)long long */
-{ SCONV, INTAREG,
+/* convert (u)long long to ulong */
+{ SCONV, INAREG,
SOREG, TLL,
SAREG, TUWORD,
NAREG, RESC1,
- " lwu U1, ZA\n nop\n", },
-
-
-
-
-
-
+ " lwu U1,AL # convert oreg (u)longlong to uint (endianness problem here?)\n"
+ " nop\n", },
/* Register to register conversion with long long */
-{ SCONV, INTAREG,
- SAREG, TLL,
- SAREG, TLL,
+{ SCONV, INBREG,
+ SBREG, TLL,
+ SBREG, TLL,
0, 0,
- "", },
+ " ; convert (u)longlong to (u)longlong", },
-{ SCONV, INTAREG,
+{ SCONV, INBREG,
SAREG, TPOINT|TWORD|SHORT|TUSHORT|TCHAR|TUCHAR,
- SAREG, TLL,
- NAREG, 0,
- "move A1, AR\n"
- "move U1, $zero\n", },
+ SBREG, TLL,
+ NBREG, 0,
+ " move A1,AR\n"
+ " move U1,0\n", },
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SAREG, TLL,
SAREG, TPOINT|TWORD|SHORT|TUSHORT|TCHAR|TUCHAR,
NAREG, 0,
- "move A1, AL\n", },
-
-
-
+ " move A1,AL\n", },
/* For register to register conversion with bit length <= 32, do nothing */
-{ SCONV, INTAREG,
+{ SCONV, INAREG,
SAREG, TPOINT|TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TPOINT|TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
0, 0,
- "", },
-
+ " ; convert reg to reg", },
-
-
-
-
/*
* Multiplication and division
*/
-{ MUL, INAREG|FOREFF,
+{ MUL, INAREG,
SAREG, TSWORD|TSHORT|TCHAR,
SAREG, TSWORD|TSHORT|TCHAR,
NAREG|NASR|NASL, RESC1,
- " mult AL, AR\n mflo A1\n nop\n nop\n", },
+ " mult AL,AR # signed multiply\n"
+ " mflo A1\n"
+ " nop\n"
+ " nop\n", },
-{ MUL, INAREG|FOREFF,
+{ MUL, INAREG,
SAREG, TUWORD|TUSHORT|TUCHAR,
SAREG, TUWORD|TUSHORT|TUCHAR,
NAREG|NASR|NASL, RESC1,
- " multu AL, AR\n mflo A1\n nop\n nop\n", },
-
-{ DIV, INAREG|FOREFF,
+ " multu AL,AR # unsigned multiply\n"
+ " mflo A1\n"
+ " nop\n"
+ " nop\n", },
+
+{ MUL, INBREG,
+ SBREG, TLL,
+ SBREG, TLL,
+ 2*NBREG|NASR|NASL, RESC1,
+ " li A2,AR\n"
+ " multu AL,A2\n"
+ " mfhi U1\n"
+ " mflo A1\n"
+ " move A2,UR\n"
+ " mult AL,A2\n"
+ " mflo U2\n"
+ " nop\n"
+ " nop\n"
+ " addu A2,U1,U2\n"
+ " li U2,AR\n"
+ " mult UL,U2\n"
+ " mflo U2\n"
+ " nop\n"
+ " nop\n"
+ " addu U1,A2,U2\n", },
+
+{ MUL, INCREG,
+ SCREG, TFLOAT,
+ SCREG, TFLOAT,
+ NCREG, RESC1,
+ " mul.s A1,Al,AR #floating-point multiply\n", },
+
+{ MUL, INCREG,
+ SCREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ NCREG, RESC1,
+ " mul.d A1,AL,AR # double-floating-point multiply\n", },
+
+{ DIV, INAREG,
SAREG, TSWORD|TSHORT|TCHAR,
SAREG, TSWORD|TSHORT|TCHAR,
NAREG|NASR|NASL, RESC1,
- " div AL, AR\n mflo A1\n nop\n nop\n", },
+ " div AL,AR # signed division\n"
+ " mflo A1\n"
+ " nop\n"
+ " nop\n", },
-{ DIV, INAREG|FOREFF,
+{ DIV, INAREG,
SAREG, TUWORD|TUSHORT|TUCHAR,
SAREG, TUWORD|TUSHORT|TUCHAR,
NAREG|NASR|NASL, RESC1,
- " divu AL, AR\n mflo A1\n nop\n nop\n", },
-
+ " divu AL,AR # unsigned division\n"
+ " mflo A1\n"
+ " nop\n"
+ " nop\n", },
+
+{ DIV, INBREG,
+ SBREG, TLL,
+ SBREG|SCON, TLL,
+ NBREG, RESC1,
+ "ZE", },
+
+{ MOD, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NAREG, RESC1,
+ " div AL,AR # signed modulo\n"
+ " mfhi A1\n"
+ " nop\n"
+ " nop\n"
+ " sub A1,A1,AL\n", },
+
+{ MOD, INAREG,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NAREG, RESC1,
+ " divu AL,AR # signed modulo\n"
+ " mfhi A1\n"
+ " nop\n"
+ " nop\n"
+ " sub A1,A1,AL\n", },
+
+{ MOD, INBREG,
+ SBREG, TLL,
+ SBREG, TLL,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
+
/*
* Templates for unsigned values needs to come before OPSIMP
*/
-{ PLUS, INAREG|FOREFF,
- SAREG, TLL,
- SAREG, TLL,
- 3*NAREG, RESC3,
- " addu A1, AL, AR\n"
- " sltu A2, A1, AR\n"
- " addu A3, UL, UR\n"
- " addu A3, A3, A2\n", },
-
-{ PLUS, INAREG|FOREFF,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SCON, TUSHORT|TSHORT|TCHAR|TUCHAR,
- NAREG|NASR|NASL, RESC1,
- " addiu A1, AL, AR\n", },
-
- /*
-{ PLUS, INAREG|FOREFF,
- SAREG, TUWORD|TUSHORT|TUCHAR,
+{ PLUS, INBREG,
+ SBREG, TULONGLONG,
+ SBREG, TULONGLONG,
+ NBREG|NAREG, RESC1,
+ " addu A1,AL,AR\n"
+ " sltu A2,A1,AR\n"
+ " addu U1,UL,UR\n"
+ " addu U1,U1,A2\n", },
+
+{ PLUS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NBREG|NAREG, RESC1,
+ " add A1,AL,AR\n", },
+
+{ PLUS, INAREG,
SAREG, TUWORD|TUSHORT|TUCHAR,
- NAREG|NASR|NASL, RESC1,
- " addu A1, AL, AR\n", },
-
-{ MINUS, INAREG|FOREFF,
SAREG, TUWORD|TUSHORT|TUCHAR,
+ NBREG|NAREG, RESC1,
+ " addu A1,AL,AR\n", },
+
+{ PLUS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SSCON, TANY,
+ NAREG|NASL, RESC1,
+ " addi A1,AL,AR\n", },
+
+{ PLUS, INAREG,
SAREG, TUWORD|TUSHORT|TUCHAR,
- NAREG|NASR|NASL, RESC1,
- " subu A1, AL, AR\n", },
- */
+ SSCON, TANY,
+ NAREG|NASL, RESC1,
+ " addui A1,AL,AR\n", },
+
+{ MINUS, INBREG,
+ SBREG, TULONGLONG,
+ SBREG, TULONGLONG,
+ NBREG|NAREG, RESC1,
+ " sltu A2,AL,AR\n"
+ " subu A1,AL,AR\n"
+ " subu U1,UL,UR\n"
+ " subu U1,U1,A2\n", },
+
+{ MINUS, INAREG,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ SAREG, TSWORD|TSHORT|TCHAR,
+ NBREG|NAREG, RESC1,
+ " sub A1,AL,AR\n", },
-{ MINUS, INAREG|FOREFF,
- SAREG, TLL,
- SAREG, TLL,
- NAREG|NASR|NASL, RESC1,
- " sltu A1, AL, AR\n"
- " subu AR, AL, AR\n"
- " subu UR, UL, UR\n"
- " subu UR, UR, A1\n", },
-
-{ MINUS, INAREG|FOREFF,
- SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SCON, TUSHORT|TSHORT|TCHAR|TUCHAR,
- NAREG|NASR|NASL, RESC1,
- " subiu A1, AL, AR\n", },
+{ MINUS, INAREG,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ SAREG, TUWORD|TUSHORT|TUCHAR,
+ NBREG|NAREG, RESC1,
+ " subu A1,AL,AR\n", },
+{ MINUS, INAREG,
+ SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SSCON, TANY,
+ NAREG|NASL, RESC1,
+ " subui A1,AL,AR\n", },
-{ UMINUS, INAREG|FOREFF|INTAREG,
+{ UMINUS, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
SANY, TANY,
NAREG|NASL, RESC1,
- " neg A1, AL\n", },
+ " neg A1,AL\n", },
+
+{ UMINUS, INBREG,
+ SBREG, TLL,
+ SANY, TANY,
+ NBREG|NAREG|NBSL, RESC1,
+ " subu A1,0,AL\n"
+ " subu U1,0,UL\n"
+ " sltu A2,0,A1\n"
+ " subu U1,U1,A2\n", },
-
/* Simple 'op rd, rs, rt' or 'op rt, rs, imm' operations */
-{ OPSIMP, INAREG|FOREFF,
- SAREG, TLL,
- SAREG, TLL,
- NAREG|NASR|NASL, RESC1,
- " O A1, AL, AR\n"
- " O U1, UL, UR\n", },
+{ OPSIMP, INBREG,
+ SBREG, TLL,
+ SBREG, TLL,
+ NBREG|NBSR|NBSL, RESC1,
+ " O A1,AL,AR\n"
+ " O U1,UL,UR\n", },
-{ OPSIMP, INAREG|FOREFF,
+{ OPSIMP, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
NAREG|NASR|NASL, RESC1,
- " O A1, AL, AR\n", },
+ " O A1,AL,AR\n", },
-{ OPSIMP, INAREG|FOREFF,
+{ OPSIMP, INAREG,
SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
- SCON, TSHORT|TUSHORT|TUCHAR|TCHAR,
- NAREG|NASR|NASL, RESC1,
- " Oi A1, AL, AR\n", },
+ SSCON, TSHORT|TUSHORT|TUCHAR|TCHAR,
+ NAREG|NASL, RESC1,
+ " Oi A1,AL,AR\n", },
/*
* Shift instructions
*/
- /* order.c SPECIAL
-{ RS, INAREG|INTAREG|FOREFF,
+{ RS, INAREG,
SAREG, TWORD|TUSHORT|TSHORT|TCHAR|TUCHAR,
SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " srl A1, AL, AR\n", },
+ " srl A1,AL,AR # shift right by constant\n", },
-{ LS, INAREG|INTAREG|FOREFF,
+{ LS, INAREG,
SAREG, TWORD|TUSHORT|TSHORT|TCHAR|TUCHAR,
SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " sll A1, AL, AR\n", },
- */
+ " sll A1,AL,AR # shift left by constant\n", },
-{ RS, INAREG|INTAREG|FOREFF,
+{ RS, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " srlv A1, AL, AR\n", },
+ " srlv A1,AL,AR # shift right by register\n", },
-{ LS, INAREG|INTAREG|FOREFF,
+{ LS, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " sllv A1, AL, AR\n", },
+ " sllv A1,AL,AR # shift left by register\n", },
+
+{ RS, INBREG,
+ SBREG, TLL,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ "ZO", },
+
+{ LS, INBREG,
+ SBREG, TLL,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ "ZO", },
+
+{ RS, INBREG,
+ SBREG, TLL,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
+
+{ LS, INBREG,
+ SBREG, TLL,
+ SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NSPECIAL|NBREG, RESC1,
+ "ZE", },
/*
* Rule for unary one's complement
*/
-{ COMPL, INTAREG,
+{ COMPL, INAREG,
SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
SANY, TANY,
NAREG|NASL, RESC1,
- " not A1, AL\n", },
+ " nor A1,AL # complement\n", },
+
+{ COMPL, INBREG,
+ SBREG, TLL,
+ SANY, TANY,
+ NBREG|NBSL, RESC1,
+ " nor A1,AL # complement\n"
+ " nor U1,UL\n", },
/*
* The next rules takes care of assignments. "=".
*/
-{ ASSIGN, INTAREG,
- SOREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
- 0, RRIGHT,
- " sw AR, AL\n", },
-
-{ ASSIGN, INTAREG,
- SOREG, TSHORT|TUSHORT,
- SAREG, TSHORT|TUSHORT,
- 0, RRIGHT,
- " sh AR, AL\n", },
-
-{ ASSIGN, INTAREG,
- SOREG, TCHAR|TUCHAR,
- SAREG, TCHAR|TUCHAR,
- 0, RRIGHT,
- " sb AR, AL\n", },
-
-{ ASSIGN, INTAREG,
- SOREG, TLL,
- SAREG, TLL,
- 0, RRIGHT,
- " sw UR, UL\n"
- " sw AR, AL\n", },
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " sw AR,AL # store (u)int/(u)long\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " sh AR,AL # store (u)short\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SOREG|SNAME, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
+ 0, RDEST,
+ " sb AR,AL # store (u)char\n"
+ " nop\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SOREG|SNAME, TLL,
+ SBREG, TLL,
+ 0, RDEST,
+ " sw UR,UL # store (u)longlong\n"
+ " nop\n"
+ " sw AR,AL\n"
+ " nop\n", },
-{ ASSIGN, INTAREG, // XXX: Funkar ej A1 == AR
+#if 0
+{ ASSIGN, FOREFF|INAREG,
SNAME, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
- NAREG, RRIGHT,
- " la A1, AL\n sw AR, 0(A1)\n", },
+ NAREG, RDEST,
+ " la A1,AL # store word into sname\n"
+ " sw AR,0(A1)\n"
+ " nop\n", },
-{ ASSIGN, INTAREG,
+{ ASSIGN, FOREFF|INAREG,
SNAME, TSHORT|TUSHORT,
SAREG, TSHORT|TUSHORT,
- NAREG, RRIGHT,
- " la A1, AL\n sh AR, 0(A1)\n", },
+ NAREG, RDEST,
+ " la A1,AL # store (u)short into sname\n"
+ " sh AR,0(A1)\n"
+ " nop\n", },
-{ ASSIGN, INTAREG,
+{ ASSIGN, FOREFF|INAREG,
SNAME, TCHAR|TUCHAR,
SAREG, TCHAR|TUCHAR,
- NAREG, RRIGHT,
- " la A1, AL\n sb AR, 0(A1)\n", },
-
-{ ASSIGN, INTAREG,
- SNAME, TLL,
- SAREG, TLL,
- 0, RRIGHT,
- " sw UR, UL\n"
- " sw AR, AL\n", },
+ NAREG, RDEST,
+ " la A1,AL # store (u)char into sname\n"
+ " sb AR,0(A1)\n"
+ " nop\n", },
+#endif
-{ ASSIGN, INTAREG,
- SAREG, TLL,
- SAREG, TLL,
- 0, RRIGHT,
- " move UR, UL\n"
- " move AR, AL\n", },
+{ ASSIGN, FOREFF|INBREG,
+ SBREG, TLL,
+ SBREG, TLL,
+ 0, RDEST,
+ " move UL,UR # register move\n"
+ " move AL,AR\n", },
-{ ASSIGN, INTAREG|FOREFF,
+{ ASSIGN, FOREFF|INAREG,
SAREG, TANY,
SAREG, TANY,
- 0, RLEFT,
- " move AL, AR\n", },
+ 0, RDEST,
+ " move AL,AR # register move\n", },
-#if 0
-/* XXX - Stupid rule, shouldn't exist */
-{ ASSIGN, INTAREG,
- SANY, TANY,
- SAREG, TANY,
- 0, RLEFT,
- " move AL, AR\n", },
-#endif
-
-/*
- * Compare instructions
- */
-
-{ EQ, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- 0, RESCC,
- " ZQ\n", },
+{ ASSIGN, FOREFF|INCREG,
+ SNAME|OREG, TFLOAT,
+ SCREG, TFLOAT,
+ 0, RDEST,
+ " s.s AR,AL # store floating-point reg to sname\n", },
-{ NE, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- 0, RESCC,
- " ZQ\n", },
+{ ASSIGN, FOREFF|INCREG,
+ SNAME|OREG, TDOUBLE,
+ SCREG, TDOUBLE,
+ 0, RDEST,
+ " s.d AR,AL # store double-floating-point reg to sname\n", },
-{ LE, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- NAREG|NASL, RESCC,
- " sub A1, AL, AR\n ZQ\n", },
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
-{ LT, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- NAREG|NASL, RESCC,
- " sub A1, AL, AR\n ZQ\n", },
-{ GE, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- NAREG|NASL, RESCC,
- " sub A1, AL, AR\n ZQ\n", },
+/*
+ * Compare instructions
+ */
-{ GT, FORCC,
- SAREG, TANY,
- SAREG, TANY,
- NAREG|NASL, RESCC,
- " sub A1, AL, AR\n ZQ\n", },
+{ EQ, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " beq AL,AR,LC\n", },
+
+{ NE, FORCC,
+ SAREG, TANY,
+ SAREG, TANY,
+ 0, RESCC,
+ " bne AL,AR,LC\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SZERO, TANY,
+ 0, RESCC,
+ " O AL,LC\n", },
+
+{ OPLOG, FORCC,
+ SAREG, TANY,
+ SAREG|SCON, TANY,
+ NAREG|NBSL, RESCC,
+ " sub A1,AL,AR\n"
+ " O A1,LC\n", },
-
/*
* Convert LTYPE to reg.
*/
-
-/* from OREG to REG */
-
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TCHAR,
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TCHAR,
NAREG, RESC1,
- " lb A1,AR\n nop\n", },
+ " lb A1,AR # load char to reg\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TUCHAR,
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TUCHAR,
NAREG, RESC1,
- " lbu A1,AR\n nop\n", },
+ " lbu A1,AR # load uchar to reg\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TSHORT,
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TSHORT,
NAREG, RESC1,
- " lh A1,AR\n nop\n", },
+ " lh A1,AR # load short to reg\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TUSHORT,
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TUSHORT,
NAREG, RESC1,
- " lhu A1,AR\n nop\n", },
+ " lhu A1,AR # load ushort to reg\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TWORD|TPOINT,
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SOREG|SNAME, TWORD|TPOINT,
NAREG, RESC1,
- " lw A1, AR\n nop\n", },
+ " lw A1,AR # load (u)int/(u)long to reg\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
- SANY, TANY,
- SOREG, TLL,
- NAREG, RESC1,
- " lw U1, UR\n"
- " lw A1, AR\n"
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SOREG|SNAME, TLL,
+ NBREG, RESC1,
+ " lw U1,UR # load (u)longlong to reg\n"
+ " nop\n"
+ " lw A1,AR\n"
" nop\n", },
-/* from NAME to REG */
+#if 0
+
+// don't need these with the gas assembler
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TCHAR,
2*NAREG, RESC1,
- " la A2, AR\n lb A1, 0(A2)\n nop\n", },
+ " la A2,AL # load char sname to reg\n"
+ " lb A1,0(A2)\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TUCHAR,
2*NAREG, RESC1,
- " la A2, AR\n lbu A1, 0(A2)\n nop\n", },
+ " la A2,AR # load uchar sname to reg\n"
+ " lbu A1,0(A2)\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TSHORT,
2*NAREG, RESC1,
- " la A2, AR\n lh A1, 0(A2)\n nop\n", },
+ " la A2,AR # load short sname to reg\n"
+ " lh A1,0(A2)\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TUSHORT,
2*NAREG, RESC1,
- " la A2, AR\n lhu A1, 0(A2)\n nop\n", },
+ " la A2,AR # load ushort sname to reg\n"
+ " lhu A1,0(A2)\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TWORD|TPOINT,
2*NAREG, RESC1,
- " la A2, AR\n lw A1, 0(A2)\n nop\n", },
+ " la A2,AR # load (u)int/(u)long to reg\n"
+ " lw A1,0(A2)\n"
+ " nop\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INBREG,
SANY, TANY,
SNAME, TLL,
- 2*NAREG, RESC1,
- " la A2, UR\n"
- " lw U1, 0(A2)\n"
- " la A2, AR\n"
- " lw A1, 0(A2)\n"
+ 2*NBREG, RESC1,
+ " la A2,UR # load (u)longlong to reg (endiannes problems?)\n"
+ " lw U1,0(A2)\n"
+ " nop\n"
+ " la A2,AR\n"
+ " lw A1,0(A2)\n"
" nop\n", },
-/* from CON to REG */
-{ OPLTYPE, INTAREG,
+#endif
+
+{ OPLTYPE, INAREG,
SANY, TANY,
SCON, TPOINT,
NAREG, RESC1,
- " la A1, AR\n", },
+ " la A1,AR # load constant address to reg\n", },
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SCON, TANY,
NAREG, RESC1,
- " li A1, AR\n", },
+ " li A1,AR # load constant to reg\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NAREG, RESC1,
+ " move A1,0 # load 0 to reg\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SCON, TANY,
+ NBREG, RESC1,
+ " li A1,AR # load constant to reg\n"
+ " li U1,UR\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NBREG, RESC1,
+ " move A1,0 # load 0 to reg\n"
+ " move U1,0\n", },
#if 0
/* Matches REG nodes. XXX - shouldn't be necessary? */
-{ OPLTYPE, INTAREG,
+{ OPLTYPE, INAREG,
SANY, TANY,
SANY, TANY,
NAREG, RESC1,
- " move A1, AR\n", },
+ " move A1,AR\n", },
#endif
+
+{ OPLTYPE, INCREG,
+ SANY, TANY,
+ SOREG|SNAME, TFLOAT,
+ NCREG, RESC1,
+ " l.s A1,AR # load into floating-point reg\n", },
+
+{ OPLTYPE, INCREG,
+ SANY, TANY,
+ OREG|SNAME, TDOUBLE,
+ NCREG, RESC1,
+ " l.d A1,AR # load into double-floating-point reg\n", },
/*
* Jumps.
@@ -671,104 +828,150 @@ struct optab table[] = {
SCON, TANY,
SANY, TANY,
0, RNOP,
- " j LL\n nop\n", },
+ " j LL # goto label\n"
+ " nop\n", },
/*
* Subroutine calls.
*/
-{ UCALL, INTAREG|FOREFF,
- SCON, TANY,
- SANY, TANY,
- NAREG, RESC1,
- " addi $sp, $sp, -16\n jal AL\n nop\nZC\n", },
+{ CALL, FOREFF,
+ SCON|SNAME, TANY,
+ SANY, TANY,
+ 0, 0,
+ " addi $sp,$sp,-16 # call (args, no result) to scon/sname\n"
+ " jal CL\n"
+ " nop\n"
+ "ZC", },
+
+{ UCALL, FOREFF,
+ SCON|SNAME, TANY,
+ SANY, TANY,
+ 0, 0,
+ " jal CL # call (no args, no result) to scon/sname\n"
+ " nop\n", },
+
+{ CALL, INAREG,
+ SCON|SNAME, TANY,
+ SAREG, TANY,
+ NAREG, RESC1, /* should be 0 */
+ " addi $sp,$sp,-16 # call (args, result in v0) to scon/sname\n"
+ " jal CL\n"
+ " nop\n"
+ "ZC", },
+
+{ UCALL, INAREG,
+ SCON|SNAME, TANY,
+ SAREG, TANY,
+ NAREG, RESC1, /* should be 0 */
+ " jal CL ; call (no args, result in v0) to scon/sname\n"
+ " nop\n",
+ },
/* struct return */
-{ USTCALL, INTAREG|FOREFF,
- SCON, TANY,
+{ USTCALL, FOREFF,
+ SCON|SNAME, TANY,
SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- " call CL\nZC", },
+ 0, 0,
+ " call CL\n"
+ " ZC", },
/*
* Function arguments
*/
-
-
+
{ FUNARG, FOREFF,
- SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
SANY, TWORD|TPOINT,
- 0, RNULL,
- " addi $sp, $sp, -4\n sw AL, 0($sp)\n", },
+ 0, 0,
+ " addi $sp,$sp,-4 # save function arg to stack\n"
+ " sw AL,0($sp)\n"
+ " #nop\n", },
{ FUNARG, FOREFF,
- SAREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
SANY, TSHORT|TUSHORT,
- 0, RNULL,
- " addi $sp, $sp, -4\n sh AL, 0($sp)\n", },
+ 0, 0,
+ " addi $sp,$sp,-4 # save function arg to stack\n"
+ " sh AL,0($sp)\n"
+ " #nop\n", },
+
{ FUNARG, FOREFF,
- SAREG, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
SANY, TCHAR|TUCHAR,
- 0, RNULL,
- " addi $sp, $sp, -4\n sb AL, 0($sp)\n", },
-
+ 0, 0,
+ " addi $sp,$sp,-4 # save function arg to stack\n"
+ " sb AL,0($sp)\n"
+ " #nop\n", },
/*
* Indirection operators.
*/
-{ UMUL, INTAREG,
- SOREG, TPOINT|TWORD|TPTRTO,
+{ UMUL, INAREG,
SANY, TPOINT|TWORD,
- NAREG|NASL, RESC1,
- " lw A1, AL\n nop\n", },
+ SOREG, TPOINT|TWORD,
+ NAREG, RESC1,
+ " lw A1,AL # word load\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SOREG, TSHORT|TUSHORT|TPTRTO,
+{ UMUL, INAREG,
SANY, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- " lh A1, AL\n nop\n", },
+ SOREG, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " lh A1,AL # (u)short load\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SOREG, TCHAR|TUCHAR|TPTRTO,
+{ UMUL, INAREG,
SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
- " lb A1, AL\n nop\n", },
+ SOREG, TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " lb A1,AL # (u)char load\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SNAME, TPOINT|TWORD|TPTRTO,
+{ UMUL, INAREG,
SANY, TPOINT|TWORD,
- NAREG|NASL, RESC1,
- " la A1, AL\n lw A1, 0(A1)\n nop\n", },
+ SNAME, TPOINT|TWORD,
+ NAREG, RESC1,
+ " la A1,AL # sname word load\n"
+ " lw A1,0(A1)\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SNAME, TSHORT|TUSHORT|TPTRTO,
+{ UMUL, INAREG,
SANY, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- " la A1, AL\n lh A1, 0(A1)\n nop\n", },
+ SNAME, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " la A1,AL # sname (u)short load\n"
+ " lh A1,0(A1)\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SNAME, TCHAR|TUCHAR|TPTRTO,
+{ UMUL, INAREG,
SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
- " la A1, AL\n lb A1, 0(A1)\n nop\n", },
+ SNAME, TCHAR|TUCHAR,
+ NAREG, RESC1,
+ " la A1,AL # sname (u)char load\n"
+ " lb A1,0(A1)\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SAREG, TPOINT|TWORD|TPTRTO,
+{ UMUL, INAREG,
SANY, TPOINT|TWORD,
- NAREG|NASL, RESC1,
- " lw A1, 0(AL)\n nop\n", },
+ SAREG, TPOINT|TWORD,
+ NAREG, RESC1,
+ " lw A1,0(AL) # word load\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SAREG, TSHORT|TUSHORT|TPTRTO,
+{ UMUL, INAREG,
SANY, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- " lh A1, 0(AL)\n nop\n", },
+ SAREG, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " lh A1,0(AL) # (u)short load\n"
+ " nop\n", },
-{ UMUL, INTAREG,
- SAREG, TCHAR|TUCHAR|TPTRTO,
+{ UMUL, INAREG,
SANY, TCHAR|TUCHAR,
+ SAREG, TCHAR|TUCHAR,
NAREG|NASL, RESC1,
- " lb A1, 0(AL)\n nop\n", },
+ " lb A1,0(AL) # (u)char load\n"
+ " nop\n", },
{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
};