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 }