]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/7l/asm.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / 7l / asm.c
1 #include        "l.h"
2
3 long    OFFSET;
4
5 #define PADDR(a)        ((a) & ~0xfffffffff0000000ull)
6
7 vlong
8 entryvalue(void)
9 {
10         char *a;
11         Sym *s;
12
13         a = INITENTRY;
14         if(*a >= '0' && *a <= '9')
15                 return atolwhex(a);
16         s = lookup(a, 0);
17         if(s->type == 0)
18                 return INITTEXT;
19         switch(s->type) {
20         case STEXT:
21         case SLEAF:
22                 break;
23         case SDATA:
24                 if(dlm)
25                         return s->value+INITDAT;
26         default:
27                 diag("entry not text: %s", s->name);
28         }
29         return s->value;
30 }
31
32 void
33 cflush(void)
34 {
35         int n;
36
37         n = sizeof(buf.cbuf) - cbc;
38         if(n)
39                 write(cout, buf.cbuf, n);
40         cbp = buf.cbuf;
41         cbc = sizeof(buf.cbuf);
42 }
43
44 void
45 asmb(void)
46 {
47         Prog *p;
48         long magic, t, etext;
49         vlong vl;
50         Optab *o;
51
52         if(debug['v'])
53                 Bprint(&bso, "%5.2f asm\n", cputime());
54         Bflush(&bso);
55         OFFSET = HEADR;
56         seek(cout, OFFSET, 0);
57         pc = INITTEXT;
58         for(p = firstp; p != P; p = p->link) {
59                 if(p->as == ATEXT) {
60                         curtext = p;
61                         autosize = p->to.offset + PCSZ;
62                 }
63                 if(p->as == ADWORD && (pc & 7) != 0) {
64                         lputl(0);
65                         pc += 4;
66                 }
67                 if(p->pc != pc) {
68                         diag("phase error %llux sb %llux",
69                                 p->pc, pc);
70                         if(!debug['a'])
71                                 prasm(curp);
72                         pc = p->pc;
73                 }
74                 curp = p;
75                 o = oplook(p);  /* could probably avoid this call */
76                 asmout(p, o);
77                 pc += o->size;
78         }
79
80         if(debug['a'])
81                 Bprint(&bso, "\n");
82         Bflush(&bso);
83         cflush();
84
85         /* output strings in text segment */
86         etext = INITTEXT + textsize;
87         for(t = pc; t < etext; t += sizeof(buf)-100) {
88                 if(etext-t > sizeof(buf)-100)
89                         datblk(t, sizeof(buf)-100, 1);
90                 else
91                         datblk(t, etext-t, 1);
92         }
93
94         curtext = P;
95         switch(HEADTYPE) {
96         case 0:
97         case 2:
98         case 7:
99                 OFFSET = HEADR+textsize;
100                 seek(cout, OFFSET, 0);
101                 break;
102         case 6: /* no header, padded segments */
103                 OFFSET = rnd(HEADR+textsize, INITRND);
104                 seek(cout, OFFSET, 0);
105                 break;
106         }
107         if(dlm){
108                 char buf[8];
109
110                 write(cout, buf, INITDAT-textsize);
111                 textsize = INITDAT;
112         }
113         for(t = 0; t < datsize; t += sizeof(buf)-100) {
114                 if(datsize-t > sizeof(buf)-100)
115                         datblk(t, sizeof(buf)-100, 0);
116                 else
117                         datblk(t, datsize-t, 0);
118         }
119
120         symsize = 0;
121         lcsize = 0;
122         if(!debug['s']) {
123                 if(debug['v'])
124                         Bprint(&bso, "%5.2f sym\n", cputime());
125                 Bflush(&bso);
126                 switch(HEADTYPE) {
127                 case 0:
128                         debug['s'] = 1;
129                         break;
130                 case 2:
131                         OFFSET = HEADR+textsize+datsize;
132                         seek(cout, OFFSET, 0);
133                         break;
134                 case 6: /* no header, padded segments */
135                         OFFSET += rnd(datsize, INITRND);
136                         seek(cout, OFFSET, 0);
137                         break;
138                 case 7:
139                         break;
140                 }
141                 if(!debug['s'])
142                         asmsym();
143                 if(debug['v'])
144                         Bprint(&bso, "%5.2f pc\n", cputime());
145                 Bflush(&bso);
146                 if(!debug['s'])
147                         asmlc();
148                 if(dlm)
149                         asmdyn();
150                 cflush();
151         }
152         else if(dlm){
153                 seek(cout, HEADR+textsize+datsize, 0);
154                 asmdyn();
155                 cflush();
156         }
157
158         if(debug['v'])
159                 Bprint(&bso, "%5.2f header\n", cputime());
160         Bflush(&bso);
161         OFFSET = 0;
162         seek(cout, OFFSET, 0);
163         switch(HEADTYPE) {
164         case 0: /* no header */
165         case 6: /* no header, padded segments */
166                 break;
167         case 2: /* plan 9 */
168                 magic = 4*28*28+7;
169                 magic |= 0x00008000;            /* fat header */
170                 if(dlm)
171                         magic |= 0x80000000;    /* dlm */
172                 lput(magic);                    /* magic */
173                 lput(textsize);                 /* sizes */
174                 lput(datsize);
175                 lput(bsssize);
176                 lput(symsize);                  /* nsyms */
177                 vl = entryvalue();
178                 lput(PADDR(vl));                /* va of entry */
179                 lput(0L);
180                 lput(lcsize);
181                 llput(vl);                      /* va of entry */
182                 break;
183         }
184         cflush();
185 }
186
187 void
188 cput(int c)
189 {
190         cbp[0] = c;
191         cbp++;
192         cbc--;
193         if(cbc <= 0)
194                 cflush();
195 }
196
197 void
198 wput(long l)
199 {
200
201         cbp[0] = l>>8;
202         cbp[1] = l;
203         cbp += 2;
204         cbc -= 2;
205         if(cbc <= 0)
206                 cflush();
207 }
208
209 void
210 wputl(long l)
211 {
212
213         cbp[0] = l;
214         cbp[1] = l>>8;
215         cbp += 2;
216         cbc -= 2;
217         if(cbc <= 0)
218                 cflush();
219 }
220
221 void
222 lput(long l)
223 {
224
225         cbp[0] = l>>24;
226         cbp[1] = l>>16;
227         cbp[2] = l>>8;
228         cbp[3] = l;
229         cbp += 4;
230         cbc -= 4;
231         if(cbc <= 0)
232                 cflush();
233 }
234
235 void
236 lputl(long l)
237 {
238
239         cbp[3] = l>>24;
240         cbp[2] = l>>16;
241         cbp[1] = l>>8;
242         cbp[0] = l;
243         cbp += 4;
244         cbc -= 4;
245         if(cbc <= 0)
246                 cflush();
247 }
248
249 void
250 llput(vlong v)
251 {
252         lput(v>>32);
253         lput(v);
254 }
255
256 void
257 llputl(vlong v)
258 {
259         lputl(v);
260         lputl(v>>32);
261 }
262
263 void
264 asmsym(void)
265 {
266         Prog *p;
267         Auto *a;
268         Sym *s;
269         int h;
270
271         s = lookup("etext", 0);
272         if(s->type == STEXT)
273                 putsymb(s->name, 'T', s->value, s->version);
274
275         for(h=0; h<NHASH; h++)
276                 for(s=hash[h]; s!=S; s=s->link)
277                         switch(s->type) {
278                         case SCONST:
279                                 putsymb(s->name, 'D', s->value, s->version);
280                                 continue;
281
282                         case SDATA:
283                                 putsymb(s->name, 'D', s->value+INITDAT, s->version);
284                                 continue;
285
286                         case SBSS:
287                                 putsymb(s->name, 'B', s->value+INITDAT, s->version);
288                                 continue;
289
290                         case SSTRING:
291                                 putsymb(s->name, 'T', s->value, s->version);
292                                 continue;
293
294                         case SFILE:
295                                 putsymb(s->name, 'f', s->value, s->version);
296                                 continue;
297                         }
298
299         for(p=textp; p!=P; p=p->cond) {
300                 s = p->from.sym;
301                 if(s->type != STEXT && s->type != SLEAF)
302                         continue;
303
304                 /* filenames first */
305                 for(a=p->to.autom; a; a=a->link)
306                         if(a->type == D_FILE)
307                                 putsymb(a->asym->name, 'z', a->aoffset, 0);
308                         else
309                         if(a->type == D_FILE1)
310                                 putsymb(a->asym->name, 'Z', a->aoffset, 0);
311
312                 if(s->type == STEXT)
313                         putsymb(s->name, 'T', s->value, s->version);
314                 else
315                         putsymb(s->name, 'L', s->value, s->version);
316
317                 /* frame, auto and param after */
318                 putsymb(".frame", 'm', p->to.offset+PCSZ, 0);
319                 for(a=p->to.autom; a; a=a->link)
320                         if(a->type == D_AUTO)
321                                 putsymb(a->asym->name, 'a', -a->aoffset, 0);
322                         else
323                         if(a->type == D_PARAM)
324                                 putsymb(a->asym->name, 'p', a->aoffset, 0);
325         }
326         if(debug['v'] || debug['n'])
327                 Bprint(&bso, "symsize = %lud\n", symsize);
328         Bflush(&bso);
329 }
330
331 void
332 putsymb(char *s, int t, vlong v, int ver)
333 {
334         int i, f, l;
335
336         if(t == 'f')
337                 s++;
338         l = 4;
339         switch(HEADTYPE){
340         default:
341                 break;
342         case 2:
343                 lput(v>>32);
344                 l = 8;
345                 break;
346         }
347         lput(v);
348         if(ver)
349                 t += 'a' - 'A';
350         cput(t+0x80);                   /* 0x80 is variable length */
351
352         if(t == 'Z' || t == 'z') {
353                 cput(s[0]);
354                 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
355                         cput(s[i]);
356                         cput(s[i+1]);
357                 }
358                 cput(0);
359                 cput(0);
360                 i++;
361         }
362         else {
363                 for(i=0; s[i]; i++)
364                         cput(s[i]);
365                 cput(0);
366         }
367         symsize += l + 1 + i + 1;
368
369         if(debug['n']) {
370                 if(t == 'z' || t == 'Z') {
371                         Bprint(&bso, "%c %.8llux ", t, v);
372                         for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
373                                 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
374                                 Bprint(&bso, "/%x", f);
375                         }
376                         Bprint(&bso, "\n");
377                         return;
378                 }
379                 if(ver)
380                         Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
381                 else
382                         Bprint(&bso, "%c %.8llux %s\n", t, v, s);
383         }
384 }
385
386 #define MINLC   4
387 void
388 asmlc(void)
389 {
390         long oldpc, oldlc;
391         Prog *p;
392         long v, s;
393
394         oldpc = INITTEXT;
395         oldlc = 0;
396         for(p = firstp; p != P; p = p->link) {
397                 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
398                         if(p->as == ATEXT)
399                                 curtext = p;
400                         if(debug['V'])
401                                 Bprint(&bso, "%6llux %P\n",
402                                         p->pc, p);
403                         continue;
404                 }
405                 if(debug['V'])
406                         Bprint(&bso, "\t\t%6ld", lcsize);
407                 v = (p->pc - oldpc) / MINLC;
408                 while(v) {
409                         s = 127;
410                         if(v < 127)
411                                 s = v;
412                         cput(s+128);    /* 129-255 +pc */
413                         if(debug['V'])
414                                 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
415                         v -= s;
416                         lcsize++;
417                 }
418                 s = p->line - oldlc;
419                 oldlc = p->line;
420                 oldpc = p->pc + MINLC;
421                 if(s > 64 || s < -64) {
422                         cput(0);        /* 0 vv +lc */
423                         cput(s>>24);
424                         cput(s>>16);
425                         cput(s>>8);
426                         cput(s);
427                         if(debug['V']) {
428                                 if(s > 0)
429                                         Bprint(&bso, " lc+%ld(%d,%ld)\n",
430                                                 s, 0, s);
431                                 else
432                                         Bprint(&bso, " lc%ld(%d,%ld)\n",
433                                                 s, 0, s);
434                                 Bprint(&bso, "%6llux %P\n",
435                                         p->pc, p);
436                         }
437                         lcsize += 5;
438                         continue;
439                 }
440                 if(s > 0) {
441                         cput(0+s);      /* 1-64 +lc */
442                         if(debug['V']) {
443                                 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
444                                 Bprint(&bso, "%6llux %P\n",
445                                         p->pc, p);
446                         }
447                 } else {
448                         cput(64-s);     /* 65-128 -lc */
449                         if(debug['V']) {
450                                 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
451                                 Bprint(&bso, "%6llux %P\n",
452                                         p->pc, p);
453                         }
454                 }
455                 lcsize++;
456         }
457         while(lcsize & 1) {
458                 s = 129;
459                 cput(s);
460                 lcsize++;
461         }
462         if(debug['v'] || debug['V'])
463                 Bprint(&bso, "lcsize = %ld\n", lcsize);
464         Bflush(&bso);
465 }
466
467 void
468 datblk(long s, long n, int str)
469 {
470         Sym *v;
471         Prog *p;
472         char *cast;
473         long a, l, fl, j;
474         vlong d;
475         int i, c;
476
477         memset(buf.dbuf, 0, n+100);
478         for(p = datap; p != P; p = p->link) {
479                 if(str != (p->from.sym->type == SSTRING))
480                         continue;
481                 curp = p;
482                 a = p->from.sym->value + p->from.offset;
483                 l = a - s;
484                 c = p->reg;
485                 i = 0;
486                 if(l < 0) {
487                         if(l+c <= 0)
488                                 continue;
489                         while(l < 0) {
490                                 l++;
491                                 i++;
492                         }
493                 }
494                 if(l >= n)
495                         continue;
496                 if(p->as != AINIT && p->as != ADYNT) {
497                         for(j=l+(c-i)-1; j>=l; j--)
498                                 if(buf.dbuf[j]) {
499                                         print("%P\n", p);
500                                         diag("multiple initialization");
501                                         break;
502                                 }
503                 }
504                 switch(p->to.type) {
505                 default:
506                         diag("unknown mode in initialization%P", p);
507                         break;
508
509                 case D_FCONST:
510                         switch(c) {
511                         default:
512                         case 4:
513                                 fl = ieeedtof(p->to.ieee);
514                                 cast = (char*)&fl;
515                                 for(; i<c; i++) {
516                                         buf.dbuf[l] = cast[fnuxi4[i]];
517                                         l++;
518                                 }
519                                 break;
520                         case 8:
521                                 cast = (char*)p->to.ieee;
522                                 for(; i<c; i++) {
523                                         buf.dbuf[l] = cast[fnuxi8[i]];
524                                         l++;
525                                 }
526                                 break;
527                         }
528                         break;
529
530                 case D_SCONST:
531                         for(; i<c; i++) {
532                                 buf.dbuf[l] = p->to.sval[i];
533                                 l++;
534                         }
535                         break;
536
537                 case D_CONST:
538                         d = p->to.offset;
539                         v = p->to.sym;
540                         if(v) {
541                                 switch(v->type) {
542                                 case SUNDEF:
543                                         ckoff(v, d);
544                                 case STEXT:
545                                 case SLEAF:
546                                 case SSTRING:
547                                         d += p->to.sym->value;
548                                         break;
549                                 case SDATA:
550                                 case SBSS:
551                                         d += p->to.sym->value + INITDAT;
552                                 }
553                                 if(dlm)
554                                         dynreloc(v, a+INITDAT, 1);
555                         }
556                         cast = (char*)&d;
557                         switch(c) {
558                         default:
559                                 diag("bad nuxi %d %d%P", c, i, curp);
560                                 break;
561                         case 1:
562                                 for(; i<c; i++) {
563                                         buf.dbuf[l] = cast[inuxi1[i]];
564                                         l++;
565                                 }
566                                 break;
567                         case 2:
568                                 for(; i<c; i++) {
569                                         buf.dbuf[l] = cast[inuxi2[i]];
570                                         l++;
571                                 }
572                                 break;
573                         case 4:
574                                 for(; i<c; i++) {
575                                         buf.dbuf[l] = cast[inuxi4[i]];
576                                         l++;
577                                 }
578                                 break;
579                         case 8:
580                                 for(; i<c; i++) {
581                                         buf.dbuf[l] = cast[inuxi8[i]];
582                                         l++;
583                                 }
584                                 break;
585                         }
586                         break;
587                 }
588         }
589         write(cout, buf.dbuf, n);
590 }
591
592 static Ieee chipfloats[] = {
593         {0x00000000, 0x00000000}, /* 0 */
594         {0x00000000, 0x3ff00000}, /* 1 */
595         {0x00000000, 0x40000000}, /* 2 */
596         {0x00000000, 0x40080000}, /* 3 */
597         {0x00000000, 0x40100000}, /* 4 */
598         {0x00000000, 0x40140000}, /* 5 */
599         {0x00000000, 0x3fe00000}, /* .5 */
600         {0x00000000, 0x40240000}, /* 10 */
601 };
602
603 int
604 chipfloat(Ieee *e)
605 {
606         Ieee *p;
607         int n;
608
609         for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
610                 p = &chipfloats[n];
611                 if(p->l == e->l && p->h == e->h && 0)
612                         return n;               /* TO DO: return imm8 encoding */
613         }
614         return -1;
615 }