Fix enough things to build Contiki
Now I need a C libraryto link it. And probably a lot of fixes for
runtime.
diff --git a/machines/unsp/machine.c b/machines/unsp/machine.c
index 40e56cc..1a1cec1 100644
--- a/machines/unsp/machine.c
+++ b/machines/unsp/machine.c
@@ -581,10 +581,10 @@
else
emit(f, "\tLD\t%s, %s\n", regnames[p->z.reg], regnames[p->q1.reg]);
}
- } else if (p->q1.flags & DREFOBJ) {
- emit(f, "\tLD\t%s, (_%s)\n", regnames[p->z.reg], p->q1.v->identifier);
} else {
- emit(f, "\tLD\t%s, (BP+%d)\n", regnames[p->z.reg], localslot(offset, p->q1.v->offset));
+ emit(f, "\tLD\t%s, ", regnames[p->z.reg]);
+ emitvar(f, p, &p->q1, offset, false, 0);
+ emit(f, "\n");
}
emit(f, "\t%s\t%s, ", op, regnames[p->z.reg]);
@@ -928,7 +928,9 @@
// Constant to external variable
int tmpreg = cg_getreg(f, p);
emit(f, "\tLD\t%s, ", regnames[tmpreg]); emitval(f, &p->q1.val, q1typ(p)); emit(f, " # ASSIGNT8\n");
- emit(f, "\tST\t%s, (_%s)\n", regnames[tmpreg], p->z.v->identifier);
+ emit(f, "\tST\t%s, ", regnames[tmpreg]);
+ emitvar(f, p, &p->z, offset, true, 0);
+ emit(f, "\n");
cg_freereg(f, tmpreg);
continue;
}
@@ -999,23 +1001,87 @@
continue;
}
}
+
+ if ((p->q1.flags & REG) && (p->z.flags & REG)) {
+ int shift = p->q2.val.vint;
+ if ((p->q1.reg == p->z.reg)) {
+ while (shift > 4) {
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[p->z.reg], regnames[p->z.reg], 4);
+ shift -= 4;
+ }
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[p->z.reg], regnames[p->z.reg], shift);
+ } else {
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[p->q1.reg], regnames[p->z.reg], shift > 4 ? 4 : shift);
+ if (shift > 4) {
+ shift -= 4;
+ while (shift > 4) {
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[p->z.reg], regnames[p->z.reg], 4);
+ shift -= 4;
+ }
+ if (shift > 0)
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[p->z.reg], regnames[p->z.reg], shift);
+ }
+ }
+ continue;
+ }
+
+ if (!(p->q1.flags & REG)) {
+ int tmpreg;
+ if (p->z.flags & REG) {
+ tmpreg = p->z.reg;
+ } else {
+ tmpreg = cg_getreg(f, p);
+ }
+ int shift = p->q2.val.vint;
+
+ emit(f, "\tLD\t%s, ", regnames[tmpreg]);
+ emitvar(f, p, &p->q1, offset, false, 0);
+ emit(f, "\n");
+
+ while (shift > 0) {
+ emit(f, "\tLD\t%s, %s LSL %d\n", regnames[tmpreg], regnames[tmpreg], (shift >= 4) ? 4 : shift);
+ shift -= 4;
+ }
+
+ if (!(p->z.flags & REG)) {
+ emit(f, "# LSHIFT\n");
+ emit(f, "\tST\t%s, ", regnames[tmpreg]);
+ emitvar(f, p, &p->z, offset, true, 0);
+ emit(f, "\n");
+ cg_freereg(f, tmpreg);
+ }
+ continue;
+ }
}
break;
}
case RSHIFT:
{
if ((p->q1.flags & VAR) && (p->q2.flags & KONST) && (p->z.flags & VAR)) {
- if ((p->q1.flags & REG) && (p->z.flags & REG) && (p->q1.reg == p->z.reg)) {
+ if ((p->q1.flags & REG) && (p->z.flags & REG)) {
int shift = p->q2.val.vint;
- while (shift > 4) {
- emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], 4);
- shift -= 4;
+ if ((p->q1.reg == p->z.reg)) {
+ while (shift > 4) {
+ emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], 4);
+ shift -= 4;
+ }
+ emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], shift);
+ } else {
+ emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->q1.reg], regnames[p->z.reg], shift > 4 ? 4 : shift);
+ if (shift > 4) {
+ shift -= 4;
+ while (shift > 4) {
+ emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], 4);
+ shift -= 4;
+ }
+ if (shift > 0)
+ emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], shift);
+ }
}
- emit(f, "\tLD\t%s, %s LSR %d\n", regnames[p->z.reg], regnames[p->z.reg], shift);
-
continue;
}
+
if (!(p->q1.flags & REG)) {
int tmpreg;
if (p->z.flags & REG) {
@@ -1115,6 +1181,7 @@
}
case MULT:
{
+ // FIXME properly handle long-to-long multiplication (do the 3 crossed multiplications and add them up)
if ((p->q2.flags & KONST) && (p->z.flags & VAR) && isauto(p->z.v->storage_class)) {
int mult = p->q2.val.vuint;
if ((mult == 64) || (mult == 4)) {
@@ -1155,11 +1222,36 @@
emit(f, "\tMUL\tR3, R4\n");
if (p->z.flags & REG) {
emit(f, "\tLD\t%s, R4\n", regnames[p->z.reg]);
+ } else {
+ break;
}
emit(f, "\tPOP R3,R4,\t(SP)\n"); // FIXME check if R3 and R4 are allocated
continue;
}
+ // (REG|VAR|SCRATCH * VAR|SCRATCH -> REG|VAR|SCRATCH (Q1 and Z samereg)
+ if (((p->q1.flags & ~(REG|SCRATCH)) == VAR) && ((p->q2.flags & ~SCRATCH) == VAR))
+ {
+ // FIXME make sure the source or dest isn't already in R3 or R4
+ emit(f, "\tPUSH R3,R4,\t(SP)\n"); // FIXME check if R3 and R4 are allocated
+ emit(f, "\tLD\tR3, ");
+ emitvar(f, p, &p->q1, offset, false, 0);
+ emit(f, "\n");
+ emit(f, "\tLD\tR4, ");
+ emitvar(f, p, &p->q2, offset, false, 0);
+ emit(f, "\n");
+ emit(f, "\tPOP R3,R4,\t(SP)\n"); // FIXME check if R3 and R4 are allocated
+ emit(f, "\tMUL\tR3, R4\n");
+ if (p->z.flags & REG)
+ emit(f, "\tLD\t%s, R4\n", regnames[p->z.reg]);
+ else {
+ emit(f, "\tST\tR4, ");
+ emitvar(f, p, &p->z, offset, true, 0);
+ emit(f, "\n");
+ }
+ continue;
+ }
+
emit(f, "# ??MUL %d %d -> %d\n", p->q1.flags, p->q2.flags, p->z.flags);
break;
}
@@ -1192,7 +1284,7 @@
if (p->q1.flags & REG) {
emit(f, "\tPUSH\tSR, PC, (SP)\n");
emit(f, "\tLD\tPC, %s\n", regnames[p->q1.reg]);
- } else if (p->q1.flags == VAR|DREFOBJ|SCRATCH) {
+ } else if (p->q1.flags == (VAR|DREFOBJ|SCRATCH)) {
if (isauto(p->q1.v->storage_class)) {
// LD PC, (BP+Imm6) is not allowed, so we need an intermediate register
// FIXME we're not allowed to spill registers to the stack here!
@@ -1211,7 +1303,7 @@
emit(f, "\n");
}
} else {
- emit(f, "\tCALL\t%s ; Q1: %d\n", p->q1.v->identifier, p->q1.flags);
+ emit(f, "\tCALL\t_%s ; Q1: %d\n", p->q1.v->identifier, p->q1.flags);
}
emit(f, "\tADD\tSP, ");
emitval(f, &p->q2.val, INT);
@@ -1341,7 +1433,8 @@
continue;
}
- if ((p->q1.flags == VAR) && (p->q2.flags == (VAR|REG))) {
+
+ if (((p->q1.flags & ~SCRATCH) == VAR) && ((p->q2.flags & ~SCRATCH) == (VAR|REG))) {
int tmpreg = cg_getreg(f, p);
emit(f, "\tLD\t%s, ", regnames[tmpreg]);
emitvar(f, p, &p->q1, offset, false, 0);
@@ -1351,7 +1444,7 @@
continue;
}
- if ((p->q1.flags == VAR) && (p->q2.flags & VAR)) {
+ if (((p->q1.flags & ~(VARADR|DREFOBJ|SCRATCH)) == VAR) && (p->q2.flags & VAR)) {
int tmpreg = cg_getreg(f, p);
emit(f, "\tLD\t%s, ", regnames[tmpreg]);
emitvar(f, p, &p->q1, offset, false, 0);
@@ -1377,6 +1470,14 @@
emit(f, "\tCMP\t%s, %s\n", regnames[p->q1.reg], regnames[p->q2.reg]);
continue;
}
+
+ if (p->q1.flags & REG) {
+ emit(f, "\tCMP\t%s, ", regnames[p->q1.reg]);
+ emitvar(f, p, &p->q2, offset, false, 0);
+ emit(f, "\n");
+ continue;
+ }
+
emit(f, "; CMP %d %d\n", p->q1.flags, p->q2.flags);
break;
}
@@ -1536,7 +1637,9 @@
// Transfer return code into memory
if (p->z.flags & VAR) {
emit(f, "; GETRETURN\n");
- emit(f, "\tST\t%s, (BP+%d)\n", regnames[p->q1.reg], localslot(offset, p->z.v->offset));
+ emit(f, "\tST\t%s, ", regnames[p->q1.reg]);
+ emitvar(f, p, &p->z, offset, true, 0);
+ emit(f, "\n");
continue;
}
}