summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/emit.c5
-rw-r--r--lisc/isel.c77
-rw-r--r--lisc/lisc.h1
-rw-r--r--lisc/parse.c6
4 files changed, 45 insertions, 44 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index 8f370d9..691dc25 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -249,10 +249,7 @@ eins(Ins i, Fn *fn, FILE *f)
 				1, TMP(RSP), i.to);
 		break;
 	case OXPush:
-		emitf(fn, f, "\tpush%w %R\n", 1, i.arg[0]);
-		break;
-	case OXMovs:
-		emitf(fn, f, "\trep movsb\n");
+		emitf(fn, f, "\tpush%w %R\n", i.wide, i.arg[0]);
 		break;
 	case OXDiv:
 		emitf(fn, f, "\tidiv%w %R\n", i.wide, i.arg[0]);
diff --git a/lisc/isel.c b/lisc/isel.c
index 6efbd70..a018cd5 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -155,7 +155,6 @@ sel(Ins i, Fn *fn)
 		n = 1;
 		goto Emit;
 	case OCall:
-	case OXMovs:
 	case OSAlloc:
 	case OCopy:
 	case OSext:
@@ -446,23 +445,22 @@ classify(AInfo *a, Typ *t)
 static void
 selcall(Fn *fn, Ins *i0, Ins *i1)
 {
-	static int ireg[8] = { RDI, RSI, RDX, RCX, R8, R9, R10, R11 };
+	static int ireg[6] = {RDI, RSI, RDX, RCX, R8, R9};
 	Ins *i;
 	AInfo *ai, *a;
 	int nint, nsse, ni, ns, n;
 	uint stk, sz;
-	Ref r;
+	Ref r, r1;
 
 	ai = alloc((i1-i0) * sizeof ai[0]);
 
 	nint = 6;
 	nsse = 8;
-	stk = 0;
 	for (i=i0, a=ai; i<i1; i++, a++) {
 		if (i->op == OArgc) {
 			classify(a, &typ[i->arg[0].val]);
 			if (a->inmem)
-				goto Mem;
+				continue;
 			ni = ns = 0;
 			for (n=0; n<2; n++)
 				switch (a->rty[n]) {
@@ -476,73 +474,80 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 			if (nint > ni && nsse > ns) {
 				nint -= ni;
 				nsse -= ns;
-			} else {
+			} else
 				a->inmem = 1;
-			Mem:
-				stk += a->size;
-				if (a->align == 4 && stk % 16)
-					stk += 8;
-			}
 		} else {
 			if (nint > 0) {
 				nint--;
 				a->inmem = 0;
-			} else {
-				stk += 8;
+			} else
 				a->inmem = 1;
-			}
 			a->align = 3;
 			a->size = 8;
 			a->rty[0] = RInt;
 		}
 	}
 
-	if (!req(i1->arg[1], R))
+	for (stk=0, a=&ai[i1-i0]; a>ai;)
+		if ((--a)->inmem) {
+			assert(a->align <= 4);
+			stk += a->size;
+			if (a->align == 4)
+				stk += stk & 15;
+		}
+	stk += stk & 15;
+
+	if (rtype(i1->arg[1]) == RTyp)
 		diag("struct-returning function not implemented");
-	if (stk)
-		emit(OSAlloc, 0, R, newcon(-(int64_t)stk, fn), R);
-	for (n=0; n<2; n++) {
-		r = TMP(ireg[n]);
-		emit(OCopy, 0, R, r, R);
-	}
+
 	emit(OCopy, i1->wide, i1->to, TMP(RAX), R);
-	emit(OCall, 0, R, i->arg[0], R);
-	emit(OCopy, 0, TMP(RAX), CON_Z, R);
-	if (stk % 16)
-		emit(OXPush, 1, R, TMP(RAX), R);
+#if 1
+	for (n=0; n<6; n++) {
+		emit(OCopy, 0, R, TMP(ireg[n]), R);
+	}
+#endif
+	r = newcon(-(int64_t)stk, fn);
+	emit(OSAlloc, 0, R, r, R);
+	emit(OCall, 0, TMP(RAX), i->arg[0], R);
 
 	for (i=i0, a=ai, ni=0; i<i1; i++, a++) {
 		if (a->inmem)
 			continue;
 		if (i->op == OArgc) {
-			diag("aggregate in registers not implemented");
+			if (a->size > 8) {
+				r = TMP(ireg[ni+1]);
+				r1 = newtmp(fn);
+				emit(OLoad, 1, r, r1, R);
+				r = newcon(8, fn);
+				emit(OAdd, 1, r1, i->arg[1], r);
+				r = TMP(ireg[ni]);
+				ni += 2;
+			} else
+				r = TMP(ireg[ni++]);
+			emit(OLoad, 1, r, i->arg[1], R);
 		} else {
 			r = TMP(ireg[ni++]);
 			emit(OCopy, i->wide, r, i->arg[0], R);
 		}
 	}
 
-	stk = 0;
 	for (i=i0, a=ai; i<i1; i++, a++) {
 		if (!a->inmem)
 			continue;
 		sz = a->size;
 		if (a->align == 4 && stk % 16)
 			sz += 8;
-		stk += sz;
+		stk -= sz;
 		if (i->op == OArgc) {
-			emit(OCopy, 0, R, TMP(RCX), R);
-			emit(OCopy, 0, R, TMP(RDI), R);
-			emit(OCopy, 0, R, TMP(RSI), R);
-			emit(OXMovs, 0, R, R, R);
-			emit(OCopy, 1, TMP(RCX), newcon(a->size, fn), R);
-			emit(OCopy, 1, TMP(RDI), TMP(RSP), R);
-			emit(OCopy, 1, TMP(RSI), i->arg[1], R);
-			emit(OSAlloc, 0, R, newcon(sz, fn), R);
+			assert(!"argc todo 2");
 		} else {
 			emit(OXPush, 1, R, i->arg[0], R);
 		}
 	}
+	if (stk) {
+		assert(stk == 8);
+		emit(OXPush, 1, R, CON_Z, R);
+	}
 
 	free(ai);
 }
diff --git a/lisc/lisc.h b/lisc/lisc.h
index a33b649..1a8b4cc 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -147,7 +147,6 @@ enum Op {
 	OSign,
 	OSAlloc,
 	OXPush,
-	OXMovs,
 	OXDiv,
 	OXCmp,
 	OXSet,
diff --git a/lisc/parse.c b/lisc/parse.c
index b0e480a..25dde22 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -33,7 +33,6 @@ OpDesc opdesc[NOp] = {
 	[ONop]    = { "nop",    0, 0 },
 	[OSwap]   = { "swap",   2, 2 },
 	[OSign]   = { "sign",   1, 0 },
-	[OXMovs]  = { "xmovs",  0, 0 },
 	[OXPush]  = { "xpush",  1, 1 },
 	[OSAlloc] = { "salloc", 1, 0 },
 	[OXDiv]   = { "xdiv",   1, 1 },
@@ -684,7 +683,7 @@ parsetyp()
 			}
 			if (a > al)
 				al = a;
-			if ((a = sz & s-1)) {
+			if ((a = sz & (s-1))) {
 				a = s - a;
 				if (++n < NSeg) {
 					/* padding segment */
@@ -830,7 +829,8 @@ printfn(Fn *fn, FILE *f)
 			assert(opdesc[i->op].name);
 			fprintf(f, "%s", opdesc[i->op].name);
 			if (req(i->to, R))
-			if (i->op == OXCmp || i->op == OXTest)
+			if (i->op == OXCmp || i->op == OXTest
+			||  i->op == OXPush)
 				fprintf(f, i->wide ? "l" : "w");
 			if (!req(i->arg[0], R)) {
 				fprintf(f, " ");