]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/6l/asm.c
import updated compilers from sources
[plan9front.git] / sys / src / cmd / 6l / asm.c
1 #include        "l.h"
2
3 #define Dbufslop        100
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                 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 llput(vlong v)
56 {
57         lput(v>>32);
58         lput(v);
59 }
60
61 void
62 lputl(long l)
63 {
64         cput(l);
65         cput(l>>8);
66         cput(l>>16);
67         cput(l>>24);
68 }
69
70 void
71 strnput(char *s, int n)
72 {
73         for(; *s && n > 0; s++){
74                 cput(*s);
75                 n--;
76         }
77         while(n > 0){
78                 cput(0);
79                 n--;
80         }
81 }
82
83 void
84 asmb(void)
85 {
86         Prog *p;
87         long v, magic;
88         int a;
89         uchar *op1;
90         vlong vl;
91
92         if(debug['v'])
93                 Bprint(&bso, "%5.2f asmb\n", cputime());
94         Bflush(&bso);
95
96         seek(cout, HEADR, 0);
97         pc = INITTEXT;
98         curp = firstp;
99         for(p = firstp; p != P; p = p->link) {
100                 if(p->as == ATEXT)
101                         curtext = p;
102                 if(p->pc != pc) {
103                         if(!debug['a'])
104                                 print("%P\n", curp);
105                         diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
106                         pc = p->pc;
107                 }
108                 curp = p;
109                 asmins(p);
110                 a = (andptr - and);
111                 if(cbc < a)
112                         cflush();
113                 if(debug['a']) {
114                         Bprint(&bso, pcstr, pc);
115                         for(op1 = and; op1 < andptr; op1++)
116                                 Bprint(&bso, "%.2ux", *op1 & 0xff);
117                         Bprint(&bso, "\t%P\n", curp);
118                 }
119                 if(dlm) {
120                         if(p->as == ATEXT)
121                                 reloca = nil;
122                         else if(reloca != nil)
123                                 diag("reloc failure: %P", curp);
124                 }
125                 memmove(cbp, and, a);
126                 cbp += a;
127                 pc += a;
128                 cbc -= a;
129         }
130         cflush();
131         switch(HEADTYPE) {
132         default:
133                 diag("unknown header type %ld", HEADTYPE);
134         case 2:
135         case 5:
136                 seek(cout, HEADR+textsize, 0);
137                 break;
138         }
139
140         if(debug['v'])
141                 Bprint(&bso, "%5.2f datblk\n", cputime());
142         Bflush(&bso);
143
144         if(dlm){
145                 char buf[8];
146
147                 write(cout, buf, INITDAT-textsize);
148                 textsize = INITDAT;
149         }
150
151         for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
152                 if(datsize-v > sizeof(buf)-Dbufslop)
153                         datblk(v, sizeof(buf)-Dbufslop);
154                 else
155                         datblk(v, datsize-v);
156         }
157
158         symsize = 0;
159         spsize = 0;
160         lcsize = 0;
161         if(!debug['s']) {
162                 if(debug['v'])
163                         Bprint(&bso, "%5.2f sym\n", cputime());
164                 Bflush(&bso);
165                 switch(HEADTYPE) {
166                 default:
167                 case 2:
168                 case 5:
169                         seek(cout, HEADR+textsize+datsize, 0);
170                         break;
171                 }
172                 if(!debug['s'])
173                         asmsym();
174                 if(debug['v'])
175                         Bprint(&bso, "%5.2f sp\n", cputime());
176                 Bflush(&bso);
177                 if(debug['v'])
178                         Bprint(&bso, "%5.2f pc\n", cputime());
179                 Bflush(&bso);
180                 if(!debug['s'])
181                         asmlc();
182                 if(dlm)
183                         asmdyn();
184                 cflush();
185         }
186         else if(dlm){
187                 seek(cout, HEADR+textsize+datsize, 0);
188                 asmdyn();
189                 cflush();
190         }
191         if(debug['v'])
192                 Bprint(&bso, "%5.2f headr\n", cputime());
193         Bflush(&bso);
194         seek(cout, 0L, 0);
195         switch(HEADTYPE) {
196         default:
197         case 2: /* plan9 */
198                 magic = 4*26*26+7;
199                 magic |= 0x00008000;            /* fat header */
200                 if(dlm)
201                         magic |= 0x80000000;    /* dlm */
202                 lput(magic);                    /* magic */
203                 lput(textsize);                 /* sizes */
204                 lput(datsize);
205                 lput(bsssize);
206                 lput(symsize);                  /* nsyms */
207                 vl = entryvalue();
208                 lput(PADDR(vl));                /* va of entry */
209                 lput(spsize);                   /* sp offsets */
210                 lput(lcsize);                   /* line offsets */
211                 llput(vl);                      /* va of entry */
212                 break;
213         case 3: /* plan9 */
214                 magic = 4*26*26+7;
215                 if(dlm)
216                         magic |= 0x80000000;
217                 lput(magic);                    /* magic */
218                 lput(textsize);                 /* sizes */
219                 lput(datsize);
220                 lput(bsssize);
221                 lput(symsize);                  /* nsyms */
222                 lput(entryvalue());             /* va of entry */
223                 lput(spsize);                   /* sp offsets */
224                 lput(lcsize);                   /* line offsets */
225                 break;
226         case 5:
227                 strnput("\177ELF", 4);          /* e_ident */
228                 cput(1);                        /* class = 32 bit */
229                 cput(1);                        /* data = LSB */
230                 cput(1);                        /* version = CURRENT */
231                 strnput("", 9);
232                 wputl(2);                       /* type = EXEC */
233                 if(debug['8'])
234                         wputl(3);               /* machine = 386 */
235                 else
236                         wputl(62);              /* machine = AMD64 */
237                 lputl(1L);                      /* version = CURRENT */
238                 lputl(PADDR(entryvalue()));     /* entry vaddr */
239                 lputl(52L);                     /* offset to first phdr */
240                 lputl(0L);                      /* offset to first shdr */
241                 lputl(0L);                      /* processor specific flags */
242                 wputl(52);                      /* Ehdr size */
243                 wputl(32);                      /* Phdr size */
244                 wputl(3);                       /* # of Phdrs */
245                 wputl(0);                       /* Shdr size */
246                 wputl(0);                       /* # of Shdrs */
247                 wputl(0);                       /* Shdr string size */
248
249                 lputl(1L);                      /* text - type = PT_LOAD */
250                 lputl(HEADR);                   /* file offset */
251                 lputl(INITTEXT);                /* vaddr */
252                 lputl(PADDR(INITTEXT));         /* paddr */
253                 lputl(textsize);                /* file size */
254                 lputl(textsize);                /* memory size */
255                 lputl(0x05L);                   /* protections = RX */
256                 lputl(INITRND);                 /* alignment */
257
258                 lputl(1L);                      /* data - type = PT_LOAD */
259                 lputl(HEADR+textsize);          /* file offset */
260                 lputl(INITDAT);                 /* vaddr */
261                 lputl(PADDR(INITDAT));          /* paddr */
262                 lputl(datsize);                 /* file size */
263                 lputl(datsize+bsssize);         /* memory size */
264                 lputl(0x06L);                   /* protections = RW */
265                 lputl(INITRND);                 /* alignment */
266
267                 lputl(0L);                      /* symbols - type = PT_NULL */
268                 lputl(HEADR+textsize+datsize);  /* file offset */
269                 lputl(0L);
270                 lputl(0L);
271                 lputl(symsize);                 /* symbol table size */
272                 lputl(lcsize);                  /* line number size */
273                 lputl(0x04L);                   /* protections = R */
274                 lputl(0x04L);                   /* alignment */
275                 break;
276         }
277         cflush();
278 }
279
280 void
281 cflush(void)
282 {
283         int n;
284
285         n = sizeof(buf.cbuf) - cbc;
286         if(n)
287                 write(cout, buf.cbuf, n);
288         cbp = buf.cbuf;
289         cbc = sizeof(buf.cbuf);
290 }
291
292 void
293 datblk(long s, long n)
294 {
295         Prog *p;
296         uchar *cast;
297         long l, fl, j;
298         vlong o;
299         int i, c;
300
301         memset(buf.dbuf, 0, n+Dbufslop);
302         for(p = datap; p != P; p = p->link) {
303                 curp = p;
304                 l = p->from.sym->value + p->from.offset - s;
305                 c = p->from.scale;
306                 i = 0;
307                 if(l < 0) {
308                         if(l+c <= 0)
309                                 continue;
310                         while(l < 0) {
311                                 l++;
312                                 i++;
313                         }
314                 }
315                 if(l >= n)
316                         continue;
317                 if(p->as != AINIT && p->as != ADYNT) {
318                         for(j=l+(c-i)-1; j>=l; j--)
319                                 if(buf.dbuf[j]) {
320                                         print("%P\n", p);
321                                         diag("multiple initialization");
322                                         break;
323                                 }
324                 }
325                 switch(p->to.type) {
326                 case D_FCONST:
327                         switch(c) {
328                         default:
329                         case 4:
330                                 fl = ieeedtof(&p->to.ieee);
331                                 cast = (uchar*)&fl;
332                                 if(debug['a'] && i == 0) {
333                                         Bprint(&bso, pcstr, l+s+INITDAT);
334                                         for(j=0; j<c; j++)
335                                                 Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
336                                         Bprint(&bso, "\t%P\n", curp);
337                                 }
338                                 for(; i<c; i++) {
339                                         buf.dbuf[l] = cast[fnuxi4[i]];
340                                         l++;
341                                 }
342                                 break;
343                         case 8:
344                                 cast = (uchar*)&p->to.ieee;
345                                 if(debug['a'] && i == 0) {
346                                         Bprint(&bso, pcstr, l+s+INITDAT);
347                                         for(j=0; j<c; j++)
348                                                 Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
349                                         Bprint(&bso, "\t%P\n", curp);
350                                 }
351                                 for(; i<c; i++) {
352                                         buf.dbuf[l] = cast[fnuxi8[i]];
353                                         l++;
354                                 }
355                                 break;
356                         }
357                         break;
358
359                 case D_SCONST:
360                         if(debug['a'] && i == 0) {
361                                 Bprint(&bso, pcstr, l+s+INITDAT);
362                                 for(j=0; j<c; j++)
363                                         Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
364                                 Bprint(&bso, "\t%P\n", curp);
365                         }
366                         for(; i<c; i++) {
367                                 buf.dbuf[l] = p->to.scon[i];
368                                 l++;
369                         }
370                         break;
371                 default:
372                         o = p->to.offset;
373                         if(p->to.type == D_ADDR) {
374                                 if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
375                                         diag("DADDR type%P", p);
376                                 if(p->to.sym) {
377                                         if(p->to.sym->type == SUNDEF)
378                                                 ckoff(p->to.sym, o);
379                                         o += p->to.sym->value;
380                                         if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
381                                                 o += INITDAT;
382                                         if(dlm)
383                                                 dynreloc(p->to.sym, l+s+INITDAT, 1);
384                                 }
385                         }
386                         fl = o;
387                         cast = (uchar*)&fl;
388                         switch(c) {
389                         default:
390                                 diag("bad nuxi %d %d\n%P", c, i, curp);
391                                 break;
392                         case 1:
393                                 if(debug['a'] && i == 0) {
394                                         Bprint(&bso, pcstr, l+s+INITDAT);
395                                         for(j=0; j<c; j++)
396                                                 Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
397                                         Bprint(&bso, "\t%P\n", curp);
398                                 }
399                                 for(; i<c; i++) {
400                                         buf.dbuf[l] = cast[inuxi1[i]];
401                                         l++;
402                                 }
403                                 break;
404                         case 2:
405                                 if(debug['a'] && i == 0) {
406                                         Bprint(&bso, pcstr, l+s+INITDAT);
407                                         for(j=0; j<c; j++)
408                                                 Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
409                                         Bprint(&bso, "\t%P\n", curp);
410                                 }
411                                 for(; i<c; i++) {
412                                         buf.dbuf[l] = cast[inuxi2[i]];
413                                         l++;
414                                 }
415                                 break;
416                         case 4:
417                                 if(debug['a'] && i == 0) {
418                                         Bprint(&bso, pcstr, l+s+INITDAT);
419                                         for(j=0; j<c; j++)
420                                                 Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
421                                         Bprint(&bso, "\t%P\n", curp);
422                                 }
423                                 for(; i<c; i++) {
424                                         buf.dbuf[l] = cast[inuxi4[i]];
425                                         l++;
426                                 }
427                                 break;
428                         case 8:
429                                 cast = (uchar*)&o;
430                                 if(debug['a'] && i == 0) {
431                                         Bprint(&bso, pcstr, l+s+INITDAT);
432                                         for(j=0; j<c; j++)
433                                                 Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
434                                         Bprint(&bso, "\t%P\n", curp);
435                                 }
436                                 for(; i<c; i++) {
437                                         buf.dbuf[l] = cast[inuxi8[i]];
438                                         l++;
439                                 }
440                                 break;
441                         }
442                         break;
443                 }
444         }
445         write(cout, buf.dbuf, n);
446 }
447
448 vlong
449 rnd(vlong v, vlong r)
450 {
451         vlong c;
452
453         if(r <= 0)
454                 return v;
455         v += r - 1;
456         c = v % r;
457         if(c < 0)
458                 c += r;
459         v -= c;
460         return v;
461 }