summary refs log tree commit diff
path: root/lisc
diff options
context:
space:
mode:
Diffstat (limited to 'lisc')
-rw-r--r--lisc/emit.c63
-rw-r--r--lisc/isel.c6
-rw-r--r--lisc/lisc.h5
-rw-r--r--lisc/main.c2
4 files changed, 71 insertions, 5 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index 3b916c4..aaac1b3 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -552,3 +552,66 @@ emitdat(Dat *d, FILE *f)
 		break;
 	}
 }
+
+typedef struct FBits FBits;
+
+struct FBits {
+	int64_t bits;
+	int wide;
+	FBits *link;
+};
+
+static FBits *stash;
+
+int
+stashfp(int64_t n, int w)
+{
+	FBits **pb, *b;
+	int i;
+
+	/* does a dumb de-dup of fp constants
+	 * this should be the linker's job */
+	for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
+		if (n == b->bits && w == b->wide)
+			return i;
+	b = emalloc(sizeof *b);
+	b->bits = n;
+	b->wide = w;
+	b->link = 0;
+	*pb = b;
+	return i;
+}
+
+void
+emitfin(FILE *f)
+{
+	FBits *b;
+	int i;
+
+	if (!stash)
+		return;
+	fprintf(f, "/* floating point constants */\n");
+	fprintf(f, ".data\n.align 8\n");
+	for (b=stash, i=0; b; b=b->link, i++)
+		if (b->wide)
+			fprintf(f,
+				".Lfp%d:\n"
+				"\t.quad %"PRId64
+				" /* %f */\n",
+				i, b->bits,
+				*(double *)&b->bits
+			);
+	for (b=stash, i=0; b; b=b->link, i++)
+		if (!b->wide)
+			fprintf(f,
+				".Lfp%d:\n"
+				"\t.long %"PRId64
+				" /* %lf */\n",
+				i, b->bits & 0xffffffff,
+				*(float *)&b->bits
+			);
+	while ((b=stash)) {
+		stash = b->link;
+		free(b);
+	}
+}
diff --git a/lisc/isel.c b/lisc/isel.c
index 578eec7..d5ccdd7 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -114,7 +114,7 @@ fixarg(Ref *r, int k, int phi, Fn *fn)
 {
 	Addr a;
 	Ref r0, r1;
-	int s;
+	int s, n;
 
 	r1 = r0 = *r;
 	s = rslot(r0, fn);
@@ -127,8 +127,8 @@ fixarg(Ref *r, int k, int phi, Fn *fn)
 		vgrow(&fn->mem, ++fn->nmem);
 		memset(&a, 0, sizeof a);
 		a.offset.type = CAddr;
-		sprintf(a.offset.label, ".fp%d", r0.val);
-		fn->con[r0.val].emit = 1;
+		n = stashfp(fn->con[r0.val].bits.i, KWIDE(k));
+		sprintf(a.offset.label, ".Lfp%d", n);
 		fn->mem[fn->nmem-1] = a;
 	}
 	else if (!phi && rtype(r0) == RCon && noimm(r0, fn)) {
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 05c1977..e857fcf 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -386,8 +386,7 @@ struct Con {
 		double d;
 		float s;
 	} bits;
-	char flt; /* 1 for single precision, 2 for double */
-	char emit;
+	char flt; /* for printing, see parse.c */
 };
 
 typedef struct Addr Addr;
@@ -511,3 +510,5 @@ void rega(Fn *);
 /* emit.c */
 void emitfn(Fn *, FILE *);
 void emitdat(Dat *, FILE *);
+int stashfp(int64_t, int);
+void emitfin(FILE *);
diff --git a/lisc/main.c b/lisc/main.c
index a393a69..25165ff 100644
--- a/lisc/main.c
+++ b/lisc/main.c
@@ -114,6 +114,8 @@ main(int ac, char *av[])
 	}
 
 	parse(inf, data, func);
+	if (!dbg)
+		emitfin(stdout);
 	fclose(inf);
 	exit(0);