summary refs log tree commit diff
path: root/gas.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas.c')
-rw-r--r--gas.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/gas.c b/gas.c
new file mode 100644
index 0000000..c1fd6df
--- /dev/null
+++ b/gas.c
@@ -0,0 +1,122 @@
+#include "all.h"
+
+
+char *gasloc, *gassym;
+
+void
+gasemitdat(Dat *d, FILE *f)
+{
+	static int align;
+	static char *dtoa[] = {
+		[DAlign] = ".align",
+		[DB] = "\t.byte",
+		[DH] = "\t.short",
+		[DW] = "\t.int",
+		[DL] = "\t.quad"
+	};
+
+	switch (d->type) {
+	case DStart:
+		align = 0;
+		fprintf(f, ".data\n");
+		break;
+	case DEnd:
+		break;
+	case DName:
+		if (!align)
+			fprintf(f, ".align 8\n");
+		if (d->export)
+			fprintf(f, ".globl %s%s\n", gassym, d->u.str);
+		fprintf(f, "%s%s:\n", gassym, d->u.str);
+		break;
+	case DZ:
+		fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
+		break;
+	default:
+		if (d->type == DAlign)
+			align = 1;
+
+		if (d->isstr) {
+			if (d->type != DB)
+				err("strings only supported for 'b' currently");
+			fprintf(f, "\t.ascii \"%s\"\n", d->u.str);
+		}
+		else if (d->isref) {
+			fprintf(f, "%s %s%+"PRId64"\n",
+				dtoa[d->type], d->u.ref.nam,
+				d->u.ref.off);
+		}
+		else {
+			fprintf(f, "%s %"PRId64"\n",
+				dtoa[d->type], d->u.num);
+		}
+		break;
+	}
+}
+
+typedef struct FBits FBits;
+
+struct FBits {
+	union {
+		int64_t n;
+		float f;
+		double d;
+	} bits;
+	int wide;
+	FBits *link;
+};
+
+static FBits *stash;
+
+int
+gasstashfp(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.n && w == b->wide)
+			return i;
+	b = emalloc(sizeof *b);
+	b->bits.n = n;
+	b->wide = w;
+	b->link = 0;
+	*pb = b;
+	return i;
+}
+
+void
+gasemitfin(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,
+				"%sfp%d:\n"
+				"\t.quad %"PRId64
+				" /* %f */\n",
+				gasloc, i, b->bits.n,
+				b->bits.d
+			);
+	for (b=stash, i=0; b; b=b->link, i++)
+		if (!b->wide)
+			fprintf(f,
+				"%sfp%d:\n"
+				"\t.long %"PRId64
+				" /* %lf */\n",
+				gasloc, i, b->bits.n & 0xffffffff,
+				b->bits.f
+			);
+	while ((b=stash)) {
+		stash = b->link;
+		free(b);
+	}
+}