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 gcmp(OEQ, n, 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 gcmp(OGT, n, 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, tfield, nodconst(v), n1);
65 } else {
66 sh = 32 - b->type->shift - b->type->nbits;
67 if(sh > 0)
68 gopcode(OASHL, tfield, nodconst(sh), n1);
69 sh += b->type->shift;
70 if(sh > 0)
71 if(typeu[b->type->etype])
72 gopcode(OLSHR, tfield, nodconst(sh), n1);
73 else
74 gopcode(OASHR, tfield, 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(0 && 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 l = a->offset;
381 if((vlong)l != a->offset)
382 t |= T_64;
383 }
384 break;
385 case D_FCONST:
386 t |= T_FCONST;
387 break;
388 case D_SCONST:
389 t |= T_SCONST;
390 break;
391 }
392 Bputc(b, t);
393
394 if(t & T_INDEX) { /* implies index, scale */
395 Bputc(b, a->index);
396 Bputc(b, a->scale);
397 }
398 if(t & T_OFFSET) { /* implies offset */
399 l = a->offset;
400 Bputc(b, l);
401 Bputc(b, l>>8);
402 Bputc(b, l>>16);
403 Bputc(b, l>>24);
404 if(t & T_64) {
405 l = a->offset>>32;
406 Bputc(b, l);
407 Bputc(b, l>>8);
408 Bputc(b, l>>16);
409 Bputc(b, l>>24);
410 }
411 }
412 if(t & T_SYM) /* implies sym */
413 Bputc(b, s);
414 if(t & T_FCONST) {
415 ieeedtod(&e, a->dval);
416 l = e.l;
417 Bputc(b, l);
418 Bputc(b, l>>8);
419 Bputc(b, l>>16);
420 Bputc(b, l>>24);
421 l = e.h;
422 Bputc(b, l);
423 Bputc(b, l>>8);
424 Bputc(b, l>>16);
425 Bputc(b, l>>24);
426 return;
427 }
428 if(t & T_SCONST) {
429 n = a->sval;
430 for(i=0; i<NSNAME; i++) {
431 Bputc(b, *n);
432 n++;
433 }
434 return;
435 }
436 if(t & T_TYPE)
437 Bputc(b, a->type);
438 }
439
440 long
align(long i,Type * t,int op)441 align(long i, Type *t, int op)
442 {
443 long o;
444 Type *v;
445 int w;
446
447 o = i;
448 w = 1;
449 switch(op) {
450 default:
451 diag(Z, "unknown align opcode %d", op);
452 break;
453
454 case Asu2: /* padding at end of a struct */
455 w = SZ_VLONG;
456 if(packflg)
457 w = packflg;
458 break;
459
460 case Ael1: /* initial align of struct element */
461 for(v=t; v->etype==TARRAY; v=v->link)
462 ;
463 w = ewidth[v->etype];
464 if(w <= 0 || w >= SZ_VLONG)
465 w = SZ_VLONG;
466 if(packflg)
467 w = packflg;
468 break;
469
470 case Ael2: /* width of a struct element */
471 o += t->width;
472 break;
473
474 case Aarg0: /* initial passbyptr argument in arg list */
475 if(typesu[t->etype]) {
476 o = align(o, types[TIND], Aarg1);
477 o = align(o, types[TIND], Aarg2);
478 }
479 break;
480
481 case Aarg1: /* initial align of parameter */
482 w = ewidth[t->etype];
483 if(w <= 0 || w >= SZ_VLONG) {
484 w = SZ_VLONG;
485 break;
486 }
487 w = 1; /* little endian no adjustment */
488 break;
489
490 case Aarg2: /* width of a parameter */
491 o += t->width;
492 w = SZ_VLONG;
493 break;
494
495 case Aaut3: /* total allign of automatic */
496 o = align(o, t, Ael1);
497 o = align(o, t, Ael2);
498 break;
499 }
500 o = round(o, w);
501 if(debug['A'])
502 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
503 return o;
504 }
505
506 long
maxround(long max,long v)507 maxround(long max, long v)
508 {
509 v = round(v, SZ_VLONG);
510 if(v > max)
511 return v;
512 return max;
513 }
514