1 #include "gc.h"
2
3 void
swit1(C1 * q,int nc,long def,Node * n)4 swit1(C1 *q, int nc, long def, Node *n)
5 {
6 C1 *r;
7 int i;
8 Prog *sp;
9
10 if(nc < 5) {
11 for(i=0; i<nc; i++) {
12 if(debug['K'])
13 print("case = %.8llux\n", q->val);
14 gopcode(OEQ, n->type, n, nodconst(q->val));
15 patch(p, q->label);
16 q++;
17 }
18 gbranch(OGOTO);
19 patch(p, def);
20 return;
21 }
22 i = nc / 2;
23 r = q+i;
24 if(debug['K'])
25 print("case > %.8llux\n", r->val);
26 gopcode(OGT, n->type, n, nodconst(r->val));
27 sp = p;
28 gbranch(OGOTO);
29 p->as = AJEQ;
30 patch(p, r->label);
31 swit1(q, i, def, n);
32
33 if(debug['K'])
34 print("case < %.8llux\n", r->val);
35 patch(sp, pc);
36 swit1(r+1, nc-i-1, def, n);
37 }
38
39 void
bitload(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)40 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
41 {
42 int sh;
43 long v;
44 Node *l;
45
46 /*
47 * n1 gets adjusted/masked value
48 * n2 gets address of cell
49 * n3 gets contents of cell
50 */
51 l = b->left;
52 if(n2 != Z) {
53 regalloc(n1, l, nn);
54 reglcgen(n2, l, Z);
55 regalloc(n3, l, Z);
56 gmove(n2, n3);
57 gmove(n3, n1);
58 } else {
59 regalloc(n1, l, nn);
60 cgen(l, n1);
61 }
62 if(b->type->shift == 0 && typeu[b->type->etype]) {
63 v = ~0 + (1L << b->type->nbits);
64 gopcode(OAND, types[TLONG], nodconst(v), n1);
65 } else {
66 sh = 32 - b->type->shift - b->type->nbits;
67 if(sh > 0)
68 gopcode(OASHL, types[TLONG], nodconst(sh), n1);
69 sh += b->type->shift;
70 if(sh > 0)
71 if(typeu[b->type->etype])
72 gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
73 else
74 gopcode(OASHR, types[TLONG], nodconst(sh), n1);
75 }
76 }
77
78 void
bitstore(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)79 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
80 {
81 long v;
82 Node nod;
83 int sh;
84
85 regalloc(&nod, b->left, Z);
86 v = ~0 + (1L << b->type->nbits);
87 gopcode(OAND, types[TLONG], nodconst(v), n1);
88 gmove(n1, &nod);
89 if(nn != Z)
90 gmove(n1, nn);
91 sh = b->type->shift;
92 if(sh > 0)
93 gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
94 v <<= sh;
95 gopcode(OAND, types[TLONG], nodconst(~v), n3);
96 gopcode(OOR, types[TLONG], n3, &nod);
97 gmove(&nod, n2);
98
99 regfree(&nod);
100 regfree(n1);
101 regfree(n2);
102 regfree(n3);
103 }
104
105 long
outstring(char * s,long n)106 outstring(char *s, long n)
107 {
108 long r;
109
110 if(suppress)
111 return nstring;
112 r = nstring;
113 while(n) {
114 string[mnstring] = *s++;
115 mnstring++;
116 nstring++;
117 if(mnstring >= NSNAME) {
118 gpseudo(ADATA, symstring, nodconst(0L));
119 p->from.offset += nstring - NSNAME;
120 p->from.scale = NSNAME;
121 p->to.type = D_SCONST;
122 memmove(p->to.sval, string, NSNAME);
123 mnstring = 0;
124 }
125 n--;
126 }
127 return r;
128 }
129
130 void
gextern(Sym * s,Node * a,long o,long w)131 gextern(Sym *s, Node *a, long o, long w)
132 {
133 if(a->op == OCONST && typev[a->type->etype]) {
134 gpseudo(ADATA, s, lo64(a));
135 p->from.offset += o;
136 p->from.scale = 4;
137 gpseudo(ADATA, s, hi64(a));
138 p->from.offset += o + 4;
139 p->from.scale = 4;
140 return;
141 }
142 gpseudo(ADATA, s, a);
143 p->from.offset += o;
144 p->from.scale = w;
145 switch(p->to.type) {
146 default:
147 p->to.index = p->to.type;
148 p->to.type = D_ADDR;
149 case D_CONST:
150 case D_FCONST:
151 case D_ADDR:
152 break;
153 }
154 }
155
156 void zname(Biobuf*, Sym*, int);
157 void zaddr(Biobuf*, Adr*, int);
158 void outhist(Biobuf*);
159
160 void
outcode(void)161 outcode(void)
162 {
163 struct { Sym *sym; short type; } h[NSYM];
164 Prog *p;
165 Sym *s;
166 int f, sf, st, t, sym;
167 Biobuf b;
168
169 if(debug['S']) {
170 for(p = firstp; p != P; p = p->link)
171 if(p->as != ADATA && p->as != AGLOBL)
172 pc--;
173 for(p = firstp; p != P; p = p->link) {
174 print("%P\n", p);
175 if(p->as != ADATA && p->as != AGLOBL)
176 pc++;
177 }
178 }
179 f = open(outfile, OWRITE);
180 if(f < 0) {
181 diag(Z, "cannot open %s", outfile);
182 return;
183 }
184 Binit(&b, f, OWRITE);
185 Bseek(&b, 0L, 2);
186 outhist(&b);
187 for(sym=0; sym<NSYM; sym++) {
188 h[sym].sym = S;
189 h[sym].type = 0;
190 }
191 sym = 1;
192 for(p = firstp; p != P; p = p->link) {
193 jackpot:
194 sf = 0;
195 s = p->from.sym;
196 while(s != S) {
197 sf = s->sym;
198 if(sf < 0 || sf >= NSYM)
199 sf = 0;
200 t = p->from.type;
201 if(t == D_ADDR)
202 t = p->from.index;
203 if(h[sf].type == t)
204 if(h[sf].sym == s)
205 break;
206 s->sym = sym;
207 zname(&b, s, t);
208 h[sym].sym = s;
209 h[sym].type = t;
210 sf = sym;
211 sym++;
212 if(sym >= NSYM)
213 sym = 1;
214 break;
215 }
216 st = 0;
217 s = p->to.sym;
218 while(s != S) {
219 st = s->sym;
220 if(st < 0 || st >= NSYM)
221 st = 0;
222 t = p->to.type;
223 if(t == D_ADDR)
224 t = p->to.index;
225 if(h[st].type == t)
226 if(h[st].sym == s)
227 break;
228 s->sym = sym;
229 zname(&b, s, t);
230 h[sym].sym = s;
231 h[sym].type = t;
232 st = sym;
233 sym++;
234 if(sym >= NSYM)
235 sym = 1;
236 if(st == sf)
237 goto jackpot;
238 break;
239 }
240 Bputc(&b, p->as);
241 Bputc(&b, p->as>>8);
242 Bputc(&b, p->lineno);
243 Bputc(&b, p->lineno>>8);
244 Bputc(&b, p->lineno>>16);
245 Bputc(&b, p->lineno>>24);
246 zaddr(&b, &p->from, sf);
247 zaddr(&b, &p->to, st);
248 }
249 Bflush(&b);
250 close(f);
251 firstp = P;
252 lastp = P;
253 }
254
255 void
outhist(Biobuf * b)256 outhist(Biobuf *b)
257 {
258 Hist *h;
259 char *p, *q, *op, c;
260 Prog pg;
261 int n;
262
263 pg = zprog;
264 pg.as = AHISTORY;
265 c = pathchar();
266 for(h = hist; h != H; h = h->link) {
267 p = h->name;
268 op = 0;
269 /* on windows skip drive specifier in pathname */
270 if(systemtype(Windows) && p && p[1] == ':'){
271 p += 2;
272 c = *p;
273 }
274 if(p && p[0] != c && h->offset == 0 && pathname){
275 /* on windows skip drive specifier in pathname */
276 if(systemtype(Windows) && pathname[1] == ':') {
277 op = p;
278 p = pathname+2;
279 c = *p;
280 } else if(pathname[0] == c){
281 op = p;
282 p = pathname;
283 }
284 }
285 while(p) {
286 q = utfrune(p, c);
287 if(q) {
288 n = q-p;
289 if(n == 0){
290 n = 1; /* leading "/" */
291 *p = '/'; /* don't emit "\" on windows */
292 }
293 q++;
294 } else {
295 n = strlen(p);
296 q = 0;
297 }
298 if(n) {
299 Bputc(b, ANAME);
300 Bputc(b, ANAME>>8);
301 Bputc(b, D_FILE);
302 Bputc(b, 1);
303 Bputc(b, '<');
304 Bwrite(b, p, n);
305 Bputc(b, 0);
306 }
307 p = q;
308 if(p == 0 && op) {
309 p = op;
310 op = 0;
311 }
312 }
313 pg.lineno = h->line;
314 pg.to.type = zprog.to.type;
315 pg.to.offset = h->offset;
316 if(h->offset)
317 pg.to.type = D_CONST;
318
319 Bputc(b, pg.as);
320 Bputc(b, pg.as>>8);
321 Bputc(b, pg.lineno);
322 Bputc(b, pg.lineno>>8);
323 Bputc(b, pg.lineno>>16);
324 Bputc(b, pg.lineno>>24);
325 zaddr(b, &pg.from, 0);
326 zaddr(b, &pg.to, 0);
327 }
328 }
329
330 void
zname(Biobuf * b,Sym * s,int t)331 zname(Biobuf *b, Sym *s, int t)
332 {
333 char *n;
334 ulong sig;
335
336 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
337 sig = sign(s);
338 Bputc(b, ASIGNAME);
339 Bputc(b, ASIGNAME>>8);
340 Bputc(b, sig);
341 Bputc(b, sig>>8);
342 Bputc(b, sig>>16);
343 Bputc(b, sig>>24);
344 s->sig = SIGDONE;
345 }
346 else{
347 Bputc(b, ANAME); /* as */
348 Bputc(b, ANAME>>8); /* as */
349 }
350 Bputc(b, t); /* type */
351 Bputc(b, s->sym); /* sym */
352 n = s->name;
353 while(*n) {
354 Bputc(b, *n);
355 n++;
356 }
357 Bputc(b, 0);
358 }
359
360 void
zaddr(Biobuf * b,Adr * a,int s)361 zaddr(Biobuf *b, Adr *a, int s)
362 {
363 long l;
364 int i, t;
365 char *n;
366 Ieee e;
367
368 t = 0;
369 if(a->index != D_NONE || a->scale != 0)
370 t |= T_INDEX;
371 if(s != 0)
372 t |= T_SYM;
373
374 switch(a->type) {
375 default:
376 t |= T_TYPE;
377 case D_NONE:
378 if(a->offset != 0)
379 t |= T_OFFSET;
380 break;
381 case D_FCONST:
382 t |= T_FCONST;
383 break;
384 case D_SCONST:
385 t |= T_SCONST;
386 break;
387 }
388 Bputc(b, t);
389
390 if(t & T_INDEX) { /* implies index, scale */
391 Bputc(b, a->index);
392 Bputc(b, a->scale);
393 }
394 if(t & T_OFFSET) { /* implies offset */
395 l = a->offset;
396 Bputc(b, l);
397 Bputc(b, l>>8);
398 Bputc(b, l>>16);
399 Bputc(b, l>>24);
400 }
401 if(t & T_SYM) /* implies sym */
402 Bputc(b, s);
403 if(t & T_FCONST) {
404 ieeedtod(&e, a->dval);
405 l = e.l;
406 Bputc(b, l);
407 Bputc(b, l>>8);
408 Bputc(b, l>>16);
409 Bputc(b, l>>24);
410 l = e.h;
411 Bputc(b, l);
412 Bputc(b, l>>8);
413 Bputc(b, l>>16);
414 Bputc(b, l>>24);
415 return;
416 }
417 if(t & T_SCONST) {
418 n = a->sval;
419 for(i=0; i<NSNAME; i++) {
420 Bputc(b, *n);
421 n++;
422 }
423 return;
424 }
425 if(t & T_TYPE)
426 Bputc(b, a->type);
427 }
428
429 long
align(long i,Type * t,int op)430 align(long i, Type *t, int op)
431 {
432 long o;
433 Type *v;
434 int w;
435
436 o = i;
437 w = 1;
438 switch(op) {
439 default:
440 diag(Z, "unknown align opcode %d", op);
441 break;
442
443 case Asu2: /* padding at end of a struct */
444 w = SZ_LONG;
445 if(packflg)
446 w = packflg;
447 break;
448
449 case Ael1: /* initial allign of struct element */
450 for(v=t; v->etype==TARRAY; v=v->link)
451 ;
452 w = ewidth[v->etype];
453 if(w <= 0 || w >= SZ_LONG)
454 w = SZ_LONG;
455 if(packflg)
456 w = packflg;
457 break;
458
459 case Ael2: /* width of a struct element */
460 o += t->width;
461 break;
462
463 case Aarg0: /* initial passbyptr argument in arg list */
464 if(typesuv[t->etype]) {
465 o = align(o, types[TIND], Aarg1);
466 o = align(o, types[TIND], Aarg2);
467 }
468 break;
469
470 case Aarg1: /* initial allign of parameter */
471 w = ewidth[t->etype];
472 if(w <= 0 || w >= SZ_LONG) {
473 w = SZ_LONG;
474 break;
475 }
476 w = 1; /* little endian no adjustment */
477 break;
478
479 case Aarg2: /* width of a parameter */
480 o += t->width;
481 w = SZ_LONG;
482 break;
483
484 case Aaut3: /* total allign of automatic */
485 o = align(o, t, Ael1);
486 o = align(o, t, Ael2);
487 break;
488 }
489 o = round(o, w);
490 if(debug['A'])
491 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
492 return o;
493 }
494
495 long
maxround(long max,long v)496 maxround(long max, long v)
497 {
498 v = round(v, SZ_LONG);
499 if(v > max)
500 return v;
501 return max;
502 }
503