changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/7l/asm.c

changeset 7144: d0b9ab522e8b
child: 34f64dcbbc25
author: cinap_lenrek@felloff.net
date: Mon, 08 Apr 2019 14:05:27 +0200
permissions: -rw-r--r--
description: 7l: add arm64 linker (initial sync)
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, 4096);
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, 4096);
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 }