summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/emit.c9
-rw-r--r--lisc/lisc.h6
-rw-r--r--lisc/parse.c23
-rw-r--r--lisc/rega.c4
-rw-r--r--lisc/spill.c2
5 files changed, 28 insertions, 16 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index 141c3f2..6a485a7 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -57,6 +57,15 @@ eins(Ins i, Fn *fn, FILE *f)
 	switch (i.op) {
 	case OAdd:
 	case OSub:
+		if (req(i.to, i.arg[1]))
+			switch (opdesc[i.op].comm) {
+			case T:
+				i.arg[1] = i.arg[0];
+				i.arg[0] = i.to;
+				break;
+			default:
+				diag("emit: instruction can't be encoded");
+			}
 		if (!req(i.to, i.arg[0]))
 			eop("mov", i.arg[0], i.to, fn, f);
 		eop(opi[i.op], i.arg[1], i.to, fn, f);
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 7f558b0..2f00e09 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -16,6 +16,8 @@ typedef struct Sym Sym;
 typedef struct Const Const;
 typedef struct Fn Fn;
 
+typedef enum { U, F, T } B3;
+
 enum {
 	RAX = 1,
 	RCX,
@@ -105,9 +107,9 @@ enum {
 };
 
 struct OpDesc {
-	int arity;
-	uint commut:1;
 	char *name;
+	int arity;
+	B3 comm;
 };
 
 struct Ins {
diff --git a/lisc/parse.c b/lisc/parse.c
index 4bb30fb..e303561 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -13,17 +13,18 @@ enum {
 Ins insb[NIns], *curi;
 
 OpDesc opdesc[OLast] = {
-	[OAdd]    = { 2, 1, "add" },
-	[OSub]    = { 2, 0, "sub" },
-	[ODiv]    = { 2, 0, "div" },
-	[ORem]    = { 2, 0, "rem" },
-	[OStore]  = { 2, 0, "store" },
-	[OLoad]   = { 1, 0, "load" },
-	[ONop]    = { 0, 0, "nop" },
-	[OCopy]   = { 1, 0, "copy" },
-	[OSwap]   = { 2, 1, "swap" },
-	[OIADiv]  = { 1, 0, "iadiv" },
-	[OIACltd] = { 0, 0, "iacltd" },
+	/*            NAME  ARTY  C */
+	[OAdd]    = { "add",   2, T },
+	[OSub]    = { "sub",   2, F },
+	[ODiv]    = { "div",   2, U },
+	[ORem]    = { "rem",   2, U },
+	[OStore]  = { "store", 2, U },
+	[OLoad]   = { "load",  1, U },
+	[ONop]    = { "nop",   0, U },
+	[OCopy]   = { "copy",  1, U },
+	[OSwap]   = { "swap",  2, T },
+	[OIADiv]  = { "iadiv", 1, U },
+	[OIACltd] = { "iacltd", 0, U },
 };
 
 typedef enum {
diff --git a/lisc/rega.c b/lisc/rega.c
index a003563..27d61ee 100644
--- a/lisc/rega.c
+++ b/lisc/rega.c
@@ -350,11 +350,11 @@ rega(Fn *fn)
 				 *   situation
 				 *   eax = sub ebx, eax
 				 */
-				if (!opdesc[i->op].commut && r)
+				if (opdesc[i->op].comm == F && r)
 					BSET(cur.br, r);
 				t = i->arg[1].val;
 				i->arg[1] = ralloc(&cur, t);
-				if (!opdesc[i->op].commut && r)
+				if (opdesc[i->op].comm == F && r)
 					BCLR(cur.br, r);
 			}
 		}
diff --git a/lisc/spill.c b/lisc/spill.c
index 1181bc1..921a81c 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -355,7 +355,7 @@ spill(Fn *fn)
 			w = (Bits){{0}};
 			if (rtype(i->arg[1]) == RSym
 			&& !req(i->to, R)
-			&& !opdesc[i->op].commut) {
+			&& opdesc[i->op].comm == F) {
 				/* <arch>
 				 *   here we make sure that we
 				 *   will never have to compile