qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

gas.c (3040B)


      1 #include "all.h"
      2 
      3 
      4 char *gasloc, *gassym;
      5 static int gasasm;
      6 
      7 void
      8 gasinit(enum Asm asmmode)
      9 {
     10 	gasasm = asmmode;
     11 	switch (gasasm) {
     12 	case Gaself:
     13 		gasloc = ".L";
     14 		gassym = "";
     15 		break;
     16 	case Gasmacho:
     17 		gasloc = "L";
     18 		gassym = "_";
     19 		break;
     20 	}
     21 }
     22 
     23 void
     24 gasemitlnk(char *n, Lnk *l, char *s, FILE *f)
     25 {
     26 	char *p;
     27 
     28 	if (l->sec) {
     29 		fprintf(f, ".section %s", l->sec);
     30 		if (l->secf)
     31 			fprintf(f, ", %s", l->secf);
     32 	} else {
     33 		fputs(s, f);
     34 	}
     35 	fputc('\n', f);
     36 	if (l->align)
     37 		fprintf(f, ".balign %d\n", l->align);
     38 	p = n[0] == '"' ? "" : gassym;
     39 	if (l->export)
     40 		fprintf(f, ".globl %s%s\n", p, n);
     41 	fprintf(f, "%s%s:\n", p, n);
     42 }
     43 
     44 void
     45 gasemitfntail(char *fn, FILE *f)
     46 {
     47 	if (gasasm == Gaself) {
     48 		fprintf(f, ".type %s, @function\n", fn);
     49 		fprintf(f, ".size %s, .-%s\n", fn, fn);
     50 	}
     51 }
     52 
     53 void
     54 gasemitdat(Dat *d, FILE *f)
     55 {
     56 	static char *dtoa[] = {
     57 		[DB] = "\t.byte",
     58 		[DH] = "\t.short",
     59 		[DW] = "\t.int",
     60 		[DL] = "\t.quad"
     61 	};
     62 	static int64_t zero;
     63 	char *p;
     64 
     65 	switch (d->type) {
     66 	case DStart:
     67 		zero = 0;
     68 		break;
     69 	case DEnd:
     70 		if (zero != -1) {
     71 			gasemitlnk(d->name, d->lnk, ".bss", f);
     72 			fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
     73 		}
     74 		break;
     75 	case DZ:
     76 		if (zero != -1)
     77 			zero += d->u.num;
     78 		else
     79 			fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
     80 		break;
     81 	default:
     82 		if (zero != -1) {
     83 			gasemitlnk(d->name, d->lnk, ".data", f);
     84 			if (zero > 0)
     85 				fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
     86 			zero = -1;
     87 		}
     88 		if (d->isstr) {
     89 			if (d->type != DB)
     90 				err("strings only supported for 'b' currently");
     91 			fprintf(f, "\t.ascii %s\n", d->u.str);
     92 		}
     93 		else if (d->isref) {
     94 			p = d->u.ref.name[0] == '"' ? "" : gassym;
     95 			fprintf(f, "%s %s%s%+"PRId64"\n",
     96 				dtoa[d->type], p, d->u.ref.name,
     97 				d->u.ref.off);
     98 		}
     99 		else {
    100 			fprintf(f, "%s %"PRId64"\n",
    101 				dtoa[d->type], d->u.num);
    102 		}
    103 		break;
    104 	}
    105 }
    106 
    107 typedef struct Asmbits Asmbits;
    108 
    109 struct Asmbits {
    110 	char bits[16];
    111 	int size;
    112 	Asmbits *link;
    113 };
    114 
    115 static Asmbits *stash;
    116 
    117 int
    118 gasstash(void *bits, int size)
    119 {
    120 	Asmbits **pb, *b;
    121 	int i;
    122 
    123 	assert(size == 4 || size == 8 || size == 16);
    124 	for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
    125 		if (size <= b->size)
    126 		if (memcmp(bits, b->bits, size) == 0)
    127 			return i;
    128 	b = emalloc(sizeof *b);
    129 	memcpy(b->bits, bits, size);
    130 	b->size = size;
    131 	b->link = 0;
    132 	*pb = b;
    133 	return i;
    134 }
    135 
    136 void
    137 gasemitfin(FILE *f)
    138 {
    139 	Asmbits *b;
    140 	char *p;
    141 	int sz, i;
    142 	double d;
    143 
    144 	if (gasasm == Gaself)
    145 		fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n\n");
    146 	if (!stash)
    147 		return;
    148 	fprintf(f, "/* floating point constants */\n.data\n");
    149 	for (sz=16; sz>=4; sz/=2)
    150 		for (b=stash, i=0; b; b=b->link, i++) {
    151 			if (b->size == sz) {
    152 				fprintf(f,
    153 					".balign %d\n"
    154 					"%sfp%d:",
    155 					sz, gasloc, i
    156 				);
    157 				for (p=b->bits; p<&b->bits[sz]; p+=4)
    158 					fprintf(f, "\n\t.int %"PRId32,
    159 						*(int32_t *)p);
    160 				if (sz <= 8) {
    161 					if (sz == 4)
    162 						d = *(float *)b->bits;
    163 					else
    164 						d = *(double *)b->bits;
    165 					fprintf(f, " /* %f */\n", d);
    166 				} else
    167 					fprintf(f, "\n");
    168 			}
    169 		}
    170 	while ((b=stash)) {
    171 		stash = b->link;
    172 		free(b);
    173 	}
    174 }