]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8l/asm.c
merge
[plan9front.git] / sys / src / cmd / 8l / asm.c
1 #include        "l.h"
2
3 #define Dbufslop        100
4
5 #define PADDR(a)        ((ulong)(a) & ~0xF0000000)
6
7 long
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                 break;
22         case SDATA:
23                 if(dlm)
24                         return s->value+INITDAT;
25         default:
26                 diag("entry not text: %s", s->name);
27         }
28         return s->value;
29 }
30
31 void
32 wputl(ushort w)
33 {
34         cput(w);
35         cput(w>>8);
36 }
37
38 void
39 wput(ushort w)
40 {
41         cput(w>>8);
42         cput(w);
43 }
44
45 void
46 lput(long l)
47 {
48         cput(l>>24);
49         cput(l>>16);
50         cput(l>>8);
51         cput(l);
52 }
53
54 void
55 lputl(long l)
56 {
57         cput(l);
58         cput(l>>8);
59         cput(l>>16);
60         cput(l>>24);
61 }
62
63 void
64 strnput(char *s, int n)
65 {
66         for(; *s && n > 0; s++){
67                 cput(*s);
68                 n--;
69         }
70         while(n > 0){
71                 cput(0);
72                 n--;
73         }
74 }
75
76 void
77 asmb(void)
78 {
79         Prog *p;
80         long v, magic;
81         int a;
82         uchar *op1;
83
84         if(debug['v'])
85                 Bprint(&bso, "%5.2f asmb\n", cputime());
86         Bflush(&bso);
87
88         seek(cout, HEADR, 0);
89         pc = INITTEXT;
90         curp = firstp;
91         for(p = firstp; p != P; p = p->link) {
92                 if(p->as == ATEXT)
93                         curtext = p;
94                 if(p->pc != pc) {
95                         if(!debug['a'])
96                                 print("%P\n", curp);
97                         diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
98                         pc = p->pc;
99                 }
100                 curp = p;
101                 asmins(p);
102                 if(cbc < sizeof(and))
103                         cflush();
104                 a = (andptr - and);
105                 if(debug['a']) {
106                         Bprint(&bso, pcstr, pc);
107                         for(op1 = and; op1 < andptr; op1++)
108                                 Bprint(&bso, "%.2ux", *op1 & 0xff);
109                         Bprint(&bso, "\t%P\n", curp);
110                 }
111                 if(dlm) {
112                         if(p->as == ATEXT)
113                                 reloca = nil;
114                         else if(reloca != nil)
115                                 diag("reloc failure: %P", curp);
116                 }
117                 memmove(cbp, and, a);
118                 cbp += a;
119                 pc += a;
120                 cbc -= a;
121         }
122         cflush();
123         switch(HEADTYPE) {
124         default:
125                 diag("unknown header type %ld", HEADTYPE);
126         case 0:
127                 seek(cout, rnd(HEADR+textsize, 8192), 0);
128                 break;
129         case 1:
130                 textsize = rnd(HEADR+textsize, 4096)-HEADR;
131                 seek(cout, textsize+HEADR, 0);
132                 break;
133         case 2:
134         case 5:
135                 seek(cout, HEADR+textsize, 0);
136                 break;
137         case 3:
138         case 4:
139                 seek(cout, HEADR+rnd(textsize, INITRND), 0);
140                 break;
141         }
142
143         if(debug['v'])
144                 Bprint(&bso, "%5.2f datblk\n", cputime());
145         Bflush(&bso);
146
147         if(dlm){
148                 char buf[8];
149
150                 write(cout, buf, INITDAT-textsize);
151                 textsize = INITDAT;
152         }
153
154         for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
155                 if(datsize-v > sizeof(buf)-Dbufslop)
156                         datblk(v, sizeof(buf)-Dbufslop);
157                 else
158                         datblk(v, datsize-v);
159         }
160
161         symsize = 0;
162         spsize = 0;
163         lcsize = 0;
164         if(!debug['s']) {
165                 if(debug['v'])
166                         Bprint(&bso, "%5.2f sym\n", cputime());
167                 Bflush(&bso);
168                 switch(HEADTYPE) {
169                 default:
170                 case 0:
171                         seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
172                         break;
173                 case 1:
174                         seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
175                         break;
176                 case 2:
177                 case 5:
178                         seek(cout, HEADR+textsize+datsize, 0);
179                         break;
180                 case 3:
181                 case 4:
182                         debug['s'] = 1;
183                         break;
184                 }
185                 if(!debug['s'])
186                         asmsym();
187                 if(debug['v'])
188                         Bprint(&bso, "%5.2f sp\n", cputime());
189                 Bflush(&bso);
190                 if(debug['v'])
191                         Bprint(&bso, "%5.2f pc\n", cputime());
192                 Bflush(&bso);
193                 if(!debug['s'])
194                         asmlc();
195                 if(dlm)
196                         asmdyn();
197                 cflush();
198         }
199         else if(dlm){
200                 seek(cout, HEADR+textsize+datsize, 0);
201                 asmdyn();
202                 cflush();
203         }
204         if(debug['v'])
205                 Bprint(&bso, "%5.2f headr\n", cputime());
206         Bflush(&bso);
207         seek(cout, 0L, 0);
208         switch(HEADTYPE) {
209         default:
210         case 0: /* garbage */
211                 lput(0x160L<<16);               /* magic and sections */
212                 lput(0L);                       /* time and date */
213                 lput(rnd(HEADR+textsize, 4096)+datsize);
214                 lput(symsize);                  /* nsyms */
215                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
216                 lput((0413<<16)|0437L);         /* magic and version */
217                 lput(rnd(HEADR+textsize, 4096));/* sizes */
218                 lput(datsize);
219                 lput(bsssize);
220                 lput(entryvalue());             /* va of entry */
221                 lput(INITTEXT-HEADR);           /* va of base of text */
222                 lput(INITDAT);                  /* va of base of data */
223                 lput(INITDAT+datsize);          /* va of base of bss */
224                 lput(~0L);                      /* gp reg mask */
225                 lput(0L);
226                 lput(0L);
227                 lput(0L);
228                 lput(0L);
229                 lput(~0L);                      /* gp value ?? */
230                 break;
231         case 1: /* unix coff */
232                 /*
233                  * file header
234                  */
235                 lputl(0x0004014c);              /* 4 sections, magic */
236                 lputl(0);                       /* unix time stamp */
237                 lputl(0);                       /* symbol table */
238                 lputl(0);                       /* nsyms */
239                 lputl(0x0003001c);              /* flags, sizeof a.out header */
240                 /*
241                  * a.out header
242                  */
243                 lputl(0x10b);                   /* magic, version stamp */
244                 lputl(rnd(textsize, INITRND));  /* text sizes */
245                 lputl(datsize);                 /* data sizes */
246                 lputl(bsssize);                 /* bss sizes */
247                 lput(entryvalue());             /* va of entry */
248                 lputl(INITTEXT);                /* text start */
249                 lputl(INITDAT);                 /* data start */
250                 /*
251                  * text section header
252                  */
253                 strnput(".text", 8);
254                 lputl(HEADR);                   /* pa */
255                 lputl(HEADR);                   /* va */
256                 lputl(textsize);                /* text size */
257                 lputl(HEADR);                   /* file offset */
258                 lputl(0);                       /* relocation */
259                 lputl(0);                       /* line numbers */
260                 lputl(0);                       /* relocation, line numbers */
261                 lputl(0x20);                    /* flags text only */
262                 /*
263                  * data section header
264                  */
265                 strnput(".data", 8);
266                 lputl(INITDAT);                 /* pa */
267                 lputl(INITDAT);                 /* va */
268                 lputl(datsize);                 /* data size */
269                 lputl(HEADR+textsize);          /* file offset */
270                 lputl(0);                       /* relocation */
271                 lputl(0);                       /* line numbers */
272                 lputl(0);                       /* relocation, line numbers */
273                 lputl(0x40);                    /* flags data only */
274                 /*
275                  * bss section header
276                  */
277                 strnput(".bss", 8);
278                 lputl(INITDAT+datsize);         /* pa */
279                 lputl(INITDAT+datsize);         /* va */
280                 lputl(bsssize);                 /* bss size */
281                 lputl(0);                       /* file offset */
282                 lputl(0);                       /* relocation */
283                 lputl(0);                       /* line numbers */
284                 lputl(0);                       /* relocation, line numbers */
285                 lputl(0x80);                    /* flags bss only */
286                 /*
287                  * comment section header
288                  */
289                 strnput(".comment", 8);
290                 lputl(0);                       /* pa */
291                 lputl(0);                       /* va */
292                 lputl(symsize+lcsize);          /* comment size */
293                 lputl(HEADR+textsize+datsize);  /* file offset */
294                 lputl(HEADR+textsize+datsize);  /* offset of syms */
295                 lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
296                 lputl(0);                       /* relocation, line numbers */
297                 lputl(0x200);                   /* flags comment only */
298                 break;
299         case 2: /* plan9 */
300                 magic = 4*11*11+7;
301                 if(dlm)
302                         magic |= 0x80000000;
303                 lput(magic);                    /* magic */
304                 lput(textsize);                 /* sizes */
305                 lput(datsize);
306                 lput(bsssize);
307                 lput(symsize);                  /* nsyms */
308                 lput(entryvalue());             /* va of entry */
309                 lput(spsize);                   /* sp offsets */
310                 lput(lcsize);                   /* line offsets */
311                 break;
312         case 3:
313                 /* MS-DOS .COM */
314                 break;
315         case 4:
316                 /* fake MS-DOS .EXE */
317                 v = rnd(HEADR+textsize, INITRND)+datsize;
318                 wputl(0x5A4D);                  /* 'MZ' */
319                 wputl(v % 512);                 /* bytes in last page */
320                 wputl(rnd(v, 512)/512);         /* total number of pages */
321                 wputl(0x0000);                  /* number of reloc items */
322                 v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
323                 wputl(v/16);                    /* size of header */
324                 wputl(0x0000);                  /* minimum allocation */
325                 wputl(0xFFFF);                  /* maximum allocation */
326                 wputl(0x0000);                  /* initial ss value */
327                 wputl(0x0100);                  /* initial sp value */
328                 wputl(0x0000);                  /* complemented checksum */
329                 v = entryvalue();
330                 wputl(v);                       /* initial ip value (!) */
331                 wputl(0x0000);                  /* initial cs value */
332                 wputl(0x0000);
333                 wputl(0x0000);
334                 wputl(0x003E);                  /* reloc table offset */
335                 wputl(0x0000);                  /* overlay number */
336                 break;
337         case 5:
338                 strnput("\177ELF", 4);          /* e_ident */
339                 cput(1);                        /* class = 32 bit */
340                 cput(1);                        /* data = LSB */
341                 cput(1);                        /* version = CURRENT */
342                 strnput("", 9);
343                 wputl(2);                       /* type = EXEC */
344                 wputl(3);                       /* machine = 386 */
345                 lputl(1L);                      /* version = CURRENT */
346                 lputl(PADDR(entryvalue()));     /* entry vaddr */
347                 lputl(52L);                     /* offset to first phdr */
348                 lputl(0L);                      /* offset to first shdr */
349                 lputl(0L);                      /* flags = 386 */
350                 wputl(52);                      /* Ehdr size */
351                 wputl(32);                      /* Phdr size */
352                 wputl(3);                       /* # of Phdrs */
353                 wputl(0);                       /* Shdr size */
354                 wputl(0);                       /* # of Shdrs */
355                 wputl(0);                       /* Shdr string size */
356
357                 lputl(1L);                      /* text - type = PT_LOAD */
358                 lputl(HEADR);                   /* file offset */
359                 lputl(INITTEXT);                /* vaddr */
360                 lputl(PADDR(INITTEXT));         /* paddr */
361                 lputl(textsize);                /* file size */
362                 lputl(textsize);                /* memory size */
363                 lputl(0x05L);                   /* protections = RX */
364                 lputl(INITRND);                 /* alignment */
365
366                 lputl(1L);                      /* data - type = PT_LOAD */
367                 lputl(HEADR+textsize);          /* file offset */
368                 lputl(INITDAT);                 /* vaddr */
369                 lputl(PADDR(INITDAT));          /* paddr */
370                 lputl(datsize);                 /* file size */
371                 lputl(datsize+bsssize);         /* memory size */
372                 lputl(0x06L);                   /* protections = RW */
373                 lputl(INITRND);                 /* alignment */
374
375                 lputl(0L);                      /* data - type = PT_NULL */
376                 lputl(HEADR+textsize+datsize);  /* file offset */
377                 lputl(0L);
378                 lputl(0L);
379                 lputl(symsize);                 /* symbol table size */
380                 lputl(lcsize);                  /* line number size */
381                 lputl(0x04L);                   /* protections = R */
382                 lputl(0x04L);                   /* alignment */
383                 break;
384         }
385         cflush();
386 }
387
388 void
389 cflush(void)
390 {
391         int n;
392
393         n = sizeof(buf.cbuf) - cbc;
394         if(n)
395                 write(cout, buf.cbuf, n);
396         cbp = buf.cbuf;
397         cbc = sizeof(buf.cbuf);
398 }
399
400 void
401 datblk(long s, long n)
402 {
403         Prog *p;
404         char *cast;
405         long l, fl, j;
406         int i, c;
407
408         memset(buf.dbuf, 0, n+Dbufslop);
409         for(p = datap; p != P; p = p->link) {
410                 curp = p;
411                 l = p->from.sym->value + p->from.offset - s;
412                 c = p->from.scale;
413                 i = 0;
414                 if(l < 0) {
415                         if(l+c <= 0)
416                                 continue;
417                         while(l < 0) {
418                                 l++;
419                                 i++;
420                         }
421                 }
422                 if(l >= n)
423                         continue;
424                 if(p->as != AINIT && p->as != ADYNT) {
425                         for(j=l+(c-i)-1; j>=l; j--)
426                                 if(buf.dbuf[j]) {
427                                         print("%P\n", p);
428                                         diag("multiple initialization");
429                                         break;
430                                 }
431                 }
432                 switch(p->to.type) {
433                 case D_FCONST:
434                         switch(c) {
435                         default:
436                         case 4:
437                                 fl = ieeedtof(&p->to.ieee);
438                                 cast = (char*)&fl;
439                                 if(debug['a'] && i == 0) {
440                                         Bprint(&bso, pcstr, l+s+INITDAT);
441                                         for(j=0; j<c; j++)
442                                                 Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
443                                         Bprint(&bso, "\t%P\n", curp);
444                                 }
445                                 for(; i<c; i++) {
446                                         buf.dbuf[l] = cast[fnuxi4[i]];
447                                         l++;
448                                 }
449                                 break;
450                         case 8:
451                                 cast = (char*)&p->to.ieee;
452                                 if(debug['a'] && i == 0) {
453                                         Bprint(&bso, pcstr, l+s+INITDAT);
454                                         for(j=0; j<c; j++)
455                                                 Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
456                                         Bprint(&bso, "\t%P\n", curp);
457                                 }
458                                 for(; i<c; i++) {
459                                         buf.dbuf[l] = cast[fnuxi8[i]];
460                                         l++;
461                                 }
462                                 break;
463                         }
464                         break;
465
466                 case D_SCONST:
467                         if(debug['a'] && i == 0) {
468                                 Bprint(&bso, pcstr, l+s+INITDAT);
469                                 for(j=0; j<c; j++)
470                                         Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
471                                 Bprint(&bso, "\t%P\n", curp);
472                         }
473                         for(; i<c; i++) {
474                                 buf.dbuf[l] = p->to.scon[i];
475                                 l++;
476                         }
477                         break;
478                 default:
479                         fl = p->to.offset;
480                         if(p->to.type == D_ADDR) {
481                                 if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
482                                         diag("DADDR type%P", p);
483                                 if(p->to.sym) {
484                                         if(p->to.sym->type == SUNDEF)
485                                                 ckoff(p->to.sym, fl);
486                                         fl += p->to.sym->value;
487                                         if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
488                                                 fl += INITDAT;
489                                         if(dlm)
490                                                 dynreloc(p->to.sym, l+s+INITDAT, 1);
491                                 }
492                         }
493                         cast = (char*)&fl;
494                         switch(c) {
495                         default:
496                                 diag("bad nuxi %d %d\n%P", c, i, curp);
497                                 break;
498                         case 1:
499                                 if(debug['a'] && i == 0) {
500                                         Bprint(&bso, pcstr, l+s+INITDAT);
501                                         for(j=0; j<c; j++)
502                                                 Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
503                                         Bprint(&bso, "\t%P\n", curp);
504                                 }
505                                 for(; i<c; i++) {
506                                         buf.dbuf[l] = cast[inuxi1[i]];
507                                         l++;
508                                 }
509                                 break;
510                         case 2:
511                                 if(debug['a'] && i == 0) {
512                                         Bprint(&bso, pcstr, l+s+INITDAT);
513                                         for(j=0; j<c; j++)
514                                                 Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
515                                         Bprint(&bso, "\t%P\n", curp);
516                                 }
517                                 for(; i<c; i++) {
518                                         buf.dbuf[l] = cast[inuxi2[i]];
519                                         l++;
520                                 }
521                                 break;
522                         case 4:
523                                 if(debug['a'] && i == 0) {
524                                         Bprint(&bso, pcstr, l+s+INITDAT);
525                                         for(j=0; j<c; j++)
526                                                 Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
527                                         Bprint(&bso, "\t%P\n", curp);
528                                 }
529                                 for(; i<c; i++) {
530                                         buf.dbuf[l] = cast[inuxi4[i]];
531                                         l++;
532                                 }
533                                 break;
534                         }
535                         break;
536                 }
537         }
538         write(cout, buf.dbuf, n);
539 }
540
541 long
542 rnd(long v, long r)
543 {
544         long c;
545
546         if(r <= 0)
547                 return v;
548         v += r - 1;
549         c = v % r;
550         if(c < 0)
551                 c += r;
552         v -= c;
553         return v;
554 }