summary refs log tree commit diff
path: root/gas.c
blob: c1fd6df4a631108cde2eee2600952fc6e7388f37 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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);
	}
}