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;
 					}
 				}