xref: /inferno-os/utils/kl/span.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
1  #include	"l.h"
2  
3  void
4  span(void)
5  {
6  	Prog *p;
7  	Sym *setext;
8  	Optab *o;
9  	int m;
10  	long c;
11  
12  	if(debug['v'])
13  		Bprint(&bso, "%5.2f span\n", cputime());
14  	Bflush(&bso);
15  	c = INITTEXT;
16  	for(p = firstp; p != P; p = p->link) {
17  		p->pc = c;
18  		o = oplook(p);
19  		m = o->size;
20  		if(m == 0) {
21  			if(p->as == ATEXT) {
22  				curtext = p;
23  				autosize = p->to.offset + 4;
24  				if(p->from.sym != S)
25  					p->from.sym->value = c;
26  				continue;
27  			}
28  			if(p->as != ANOP)
29  				diag("zero-width instruction\n%P", p);
30  			continue;
31  		}
32  		c += m;
33  	}
34  	c = rnd(c, 8);
35  
36  	setext = lookup("etext", 0);
37  	if(setext != S) {
38  		setext->value = c;
39  		textsize = c - INITTEXT;
40  	}
41  	if(INITRND)
42  		INITDAT = rnd(c, INITRND);
43  	if(debug['v'])
44  		Bprint(&bso, "tsize = %lux\n", textsize);
45  	Bflush(&bso);
46  }
47  
48  void
49  xdefine(char *p, int t, long v)
50  {
51  	Sym *s;
52  
53  	s = lookup(p, 0);
54  	if(s->type == 0 || s->type == SXREF) {
55  		s->type = t;
56  		s->value = v;
57  	}
58  }
59  
60  long
61  regoff(Adr *a)
62  {
63  
64  	instoffset = 0;
65  	aclass(a);
66  	return instoffset;
67  }
68  
69  int
70  aclass(Adr *a)
71  {
72  	Sym *s;
73  	int t;
74  
75  	switch(a->type) {
76  	case D_NONE:
77  		return C_NONE;
78  
79  	case D_REG:
80  		return C_REG;
81  
82  	case D_FREG:
83  		return C_FREG;
84  
85  	case D_CREG:
86  		return C_CREG;
87  
88  	case D_PREG:
89  		if(a->reg == D_FSR)
90  			return C_FSR;
91  		if(a->reg == D_FPQ)
92  			return C_FQ;
93  		return C_PREG;
94  
95  	case D_OREG:
96  		switch(a->name) {
97  		case D_EXTERN:
98  		case D_STATIC:
99  			if(a->sym == S)
100  				break;
101  			t = a->sym->type;
102  			if(t == 0 || t == SXREF) {
103  				diag("undefined external: %s in %s",
104  					a->sym->name, TNAME);
105  				a->sym->type = SDATA;
106  			}
107  			instoffset = a->sym->value + a->offset - BIG;
108  			if(instoffset >= -BIG && instoffset < BIG) {
109  				if(instoffset & 7)
110  					return C_OSEXT;
111  				return C_ESEXT;
112  			}
113  			if(instoffset & 7)
114  				return C_OLEXT;
115  			return C_ELEXT;
116  		case D_AUTO:
117  			instoffset = autosize + a->offset;
118  			goto dauto;
119  
120  		case D_PARAM:
121  			instoffset = autosize + a->offset + 4L;
122  		dauto:
123  			if(instoffset >= -BIG && instoffset < BIG) {
124  				if(instoffset & 7)
125  					return C_OSAUTO;
126  				return C_ESAUTO;
127  			}
128  			if(instoffset & 7)
129  				return C_OLAUTO;
130  			return C_ELAUTO;
131  		case D_NONE:
132  			instoffset = a->offset;
133  			if(instoffset == 0)
134  				return C_ZOREG;
135  			if(instoffset >= -BIG && instoffset < BIG)
136  				return C_SOREG;
137  			return C_LOREG;
138  		}
139  		return C_GOK;
140  
141  	case D_ASI:
142  		if(a->name == D_NONE)
143  			return C_ASI;
144  		return C_GOK;
145  
146  	case D_CONST:
147  		switch(a->name) {
148  
149  		case D_NONE:
150  			instoffset = a->offset;
151  		consize:
152  			if(instoffset == 0)
153  				return C_ZCON;
154  			if(instoffset >= -0x1000 && instoffset <= 0xfff)
155  				return C_SCON;
156  			if((instoffset & 0x3ff) == 0)
157  				return C_UCON;
158  			return C_LCON;
159  
160  		case D_EXTERN:
161  		case D_STATIC:
162  			s = a->sym;
163  			if(s == S)
164  				break;
165  			t = s->type;
166  			if(t == 0 || t == SXREF) {
167  				diag("undefined external: %s in %s",
168  					s->name, TNAME);
169  				s->type = SDATA;
170  			}
171  			if(s->type == STEXT || s->type == SLEAF) {
172  				instoffset = s->value + a->offset;
173  				return C_LCON;
174  			}
175  			if(s->type == SCONST) {
176  				instoffset = s->value + a->offset;
177  				goto consize;
178  			}
179  			instoffset = s->value + a->offset - BIG;
180  			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0)
181  				return C_SECON;
182  			instoffset = s->value + a->offset + INITDAT;
183  /* not sure why this barfs */
184  return C_LCON;
185  /*
186  			if(instoffset == 0)
187  				return C_ZCON;
188  			if(instoffset >= -0x1000 && instoffset <= 0xfff)
189  				return C_SCON;
190  			if((instoffset & 0x3ff) == 0)
191  				return C_UCON;
192  			return C_LCON;
193  */
194  
195  		case D_AUTO:
196  			instoffset = autosize + a->offset;
197  			if(instoffset >= -BIG && instoffset < BIG)
198  				return C_SACON;
199  			return C_LACON;
200  
201  		case D_PARAM:
202  			instoffset = autosize + a->offset + 4L;
203  			if(instoffset >= -BIG && instoffset < BIG)
204  				return C_SACON;
205  			return C_LACON;
206  		}
207  		return C_GOK;
208  
209  	case D_BRANCH:
210  		return C_SBRA;
211  	}
212  	return C_GOK;
213  }
214  
215  Optab*
216  oplook(Prog *p)
217  {
218  	int a1, a2, a3, r;
219  	char *c1, *c3;
220  	Optab *o, *e;
221  
222  	a1 = p->optab;
223  	if(a1)
224  		return optab+(a1-1);
225  	a1 = p->from.class;
226  	if(a1 == 0) {
227  		a1 = aclass(&p->from) + 1;
228  		p->from.class = a1;
229  	}
230  	a1--;
231  	a3 = p->to.class;
232  	if(a3 == 0) {
233  		a3 = aclass(&p->to) + 1;
234  		p->to.class = a3;
235  	}
236  	a3--;
237  	a2 = C_NONE;
238  	if(p->reg != NREG)
239  		a2 = C_REG;
240  	r = p->as;
241  	o = oprange[r].start;
242  	if(o == 0)
243  		o = oprange[r].stop; /* just generate an error */
244  	e = oprange[r].stop;
245  	c1 = xcmp[a1];
246  	c3 = xcmp[a3];
247  	for(; o<e; o++)
248  		if(o->a2 == a2)
249  		if(c1[o->a1])
250  		if(c3[o->a3]) {
251  			p->optab = (o-optab)+1;
252  			return o;
253  		}
254  	diag("illegal combination %A %d %d %d",
255  		p->as, a1, a2, a3);
256  	if(1||!debug['a'])
257  		prasm(p);
258  	if(o == 0)
259  		errorexit();
260  	return o;
261  }
262  
263  int
264  cmp(int a, int b)
265  {
266  
267  	if(a == b)
268  		return 1;
269  	switch(a) {
270  	case C_LCON:
271  		if(b == C_ZCON || b == C_SCON || b == C_UCON)
272  			return 1;
273  		break;
274  	case C_UCON:
275  		if(b == C_ZCON)
276  			return 1;
277  		break;
278  	case C_SCON:
279  		if(b == C_ZCON)
280  			return 1;
281  		break;
282  	case C_LACON:
283  		if(b == C_SACON)
284  			return 1;
285  		break;
286  	case C_LBRA:
287  		if(b == C_SBRA)
288  			return 1;
289  		break;
290  	case C_ELEXT:
291  		if(b == C_ESEXT)
292  			return 1;
293  		break;
294  	case C_LEXT:
295  		if(b == C_SEXT ||
296  		   b == C_ESEXT || b == C_OSEXT ||
297  		   b == C_ELEXT || b == C_OLEXT)
298  			return 1;
299  		break;
300  	case C_SEXT:
301  		if(b == C_ESEXT || b == C_OSEXT)
302  			return 1;
303  		break;
304  	case C_ELAUTO:
305  		if(b == C_ESAUTO)
306  			return 1;
307  		break;
308  	case C_LAUTO:
309  		if(b == C_SAUTO ||
310  		   b == C_ESAUTO || b == C_OSAUTO ||
311  		   b == C_ELAUTO || b == C_OLAUTO)
312  			return 1;
313  		break;
314  	case C_SAUTO:
315  		if(b == C_ESAUTO || b == C_OSAUTO)
316  			return 1;
317  		break;
318  	case C_REG:
319  		if(b == C_ZCON)
320  			return 1;
321  		break;
322  	case C_LOREG:
323  		if(b == C_ZOREG || b == C_SOREG)
324  			return 1;
325  		break;
326  	case C_SOREG:
327  		if(b == C_ZOREG)
328  			return 1;
329  		break;
330  
331  	case C_ANY:
332  		return 1;
333  	}
334  	return 0;
335  }
336  
337  int
338  ocmp(void *a1, void *a2)
339  {
340  	Optab *p1, *p2;
341  	int n;
342  
343  	p1 = (Optab*)a1;
344  	p2 = (Optab*)a2;
345  	n = p1->as - p2->as;
346  	if(n)
347  		return n;
348  	n = p1->a1 - p2->a1;
349  	if(n)
350  		return n;
351  	n = p1->a2 - p2->a2;
352  	if(n)
353  		return n;
354  	n = p1->a3 - p2->a3;
355  	if(n)
356  		return n;
357  	return 0;
358  }
359  
360  void
361  buildop(void)
362  {
363  	int i, n, r;
364  
365  	for(i=0; i<C_NCLASS; i++)
366  		for(n=0; n<C_NCLASS; n++)
367  			xcmp[i][n] = cmp(n, i);
368  	for(n=0; optab[n].as != AXXX; n++)
369  		;
370  	qsort(optab, n, sizeof(optab[0]), ocmp);
371  	for(i=0; i<n; i++) {
372  		r = optab[i].as;
373  		oprange[r].start = optab+i;
374  		while(optab[i].as == r)
375  			i++;
376  		oprange[r].stop = optab+i;
377  		i--;
378  
379  		switch(r)
380  		{
381  		default:
382  			diag("unknown op in build: %A", r);
383  			errorexit();
384  		case AADD:
385  			oprange[AADDX] = oprange[r];
386  			oprange[ASUB] = oprange[r];
387  			oprange[ASUBX] = oprange[r];
388  			oprange[AMUL] = oprange[r];
389  			oprange[AXOR] = oprange[r];
390  			oprange[AXNOR] = oprange[r];
391  			oprange[AAND] = oprange[r];
392  			oprange[AANDN] = oprange[r];
393  			oprange[AOR] = oprange[r];
394  			oprange[AORN] = oprange[r];
395  			oprange[ASLL] = oprange[r];
396  			oprange[ASRL] = oprange[r];
397  			oprange[ASRA] = oprange[r];
398  			oprange[AADDCC] = oprange[r];
399  			oprange[AADDXCC] = oprange[r];
400  			oprange[ATADDCC] = oprange[r];
401  			oprange[ATADDCCTV] = oprange[r];
402  			oprange[ASUBCC] = oprange[r];
403  			oprange[ASUBXCC] = oprange[r];
404  			oprange[ATSUBCC] = oprange[r];
405  			oprange[ATSUBCCTV] = oprange[r];
406  			oprange[AXORCC] = oprange[r];
407  			oprange[AXNORCC] = oprange[r];
408  			oprange[AANDCC] = oprange[r];
409  			oprange[AANDNCC] = oprange[r];
410  			oprange[AORCC] = oprange[r];
411  			oprange[AORNCC] = oprange[r];
412  			oprange[AMULSCC] = oprange[r];
413  			oprange[ASAVE] = oprange[r];
414  			oprange[ARESTORE] = oprange[r];
415  			break;
416  		case AMOVB:
417  			oprange[AMOVH] = oprange[r];
418  			oprange[AMOVHU] = oprange[r];
419  			oprange[AMOVBU] = oprange[r];
420  			oprange[ASWAP] = oprange[r];
421  			oprange[ATAS] = oprange[r];
422  			break;
423  		case ABA:
424  			oprange[ABN] = oprange[r];
425  			oprange[AFBA] = oprange[r];
426  			oprange[AFBN] = oprange[r];
427  			break;
428  		case ABE:
429  			oprange[ABCC] = oprange[r];
430  			oprange[ABCS] = oprange[r];
431  			oprange[ABGE] = oprange[r];
432  			oprange[ABGU] = oprange[r];
433  			oprange[ABG] = oprange[r];
434  			oprange[ABLEU] = oprange[r];
435  			oprange[ABLE] = oprange[r];
436  			oprange[ABL] = oprange[r];
437  			oprange[ABNEG] = oprange[r];
438  			oprange[ABNE] = oprange[r];
439  			oprange[ABPOS] = oprange[r];
440  			oprange[ABVC] = oprange[r];
441  			oprange[ABVS] = oprange[r];
442  
443  			oprange[AFBE] = oprange[r];
444  			oprange[AFBG] = oprange[r];
445  			oprange[AFBGE] = oprange[r];
446  			oprange[AFBL] = oprange[r];
447  			oprange[AFBLE] = oprange[r];
448  			oprange[AFBLG] = oprange[r];
449  			oprange[AFBNE] = oprange[r];
450  			oprange[AFBO] = oprange[r];
451  			oprange[AFBU] = oprange[r];
452  			oprange[AFBUE] = oprange[r];
453  			oprange[AFBUG] = oprange[r];
454  			oprange[AFBUGE] = oprange[r];
455  			oprange[AFBUL] = oprange[r];
456  			oprange[AFBULE] = oprange[r];
457  			break;
458  		case ATA:
459  			oprange[ATCC] = oprange[r];
460  			oprange[ATCS] = oprange[r];
461  			oprange[ATE] = oprange[r];
462  			oprange[ATGE] = oprange[r];
463  			oprange[ATGU] = oprange[r];
464  			oprange[ATG] = oprange[r];
465  			oprange[ATLEU] = oprange[r];
466  			oprange[ATLE] = oprange[r];
467  			oprange[ATL] = oprange[r];
468  			oprange[ATNEG] = oprange[r];
469  			oprange[ATNE] = oprange[r];
470  			oprange[ATN] = oprange[r];
471  			oprange[ATPOS] = oprange[r];
472  			oprange[ATVC] = oprange[r];
473  			oprange[ATVS] = oprange[r];
474  			break;
475  		case AFADDD:
476  			oprange[AFADDF] = oprange[r];
477  			oprange[AFADDX] = oprange[r];
478  			oprange[AFDIVD] = oprange[r];
479  			oprange[AFDIVF] = oprange[r];
480  			oprange[AFDIVX] = oprange[r];
481  			oprange[AFMULD] = oprange[r];
482  			oprange[AFMULF] = oprange[r];
483  			oprange[AFMULX] = oprange[r];
484  			oprange[AFSUBD] = oprange[r];
485  			oprange[AFSUBF] = oprange[r];
486  			oprange[AFSUBX] = oprange[r];
487  			break;
488  		case AFCMPD:
489  			oprange[AFCMPF] = oprange[r];
490  			oprange[AFCMPX] = oprange[r];
491  			oprange[AFCMPED] = oprange[r];
492  			oprange[AFCMPEF] = oprange[r];
493  			oprange[AFCMPEX] = oprange[r];
494  			break;
495  		case AFABSF:
496  			oprange[AFMOVDF] = oprange[r];
497  			oprange[AFMOVDW] = oprange[r];
498  			oprange[AFMOVFD] = oprange[r];
499  			oprange[AFMOVFW] = oprange[r];
500  			oprange[AFMOVWD] = oprange[r];
501  			oprange[AFMOVWF] = oprange[r];
502  			oprange[AFNEGF] = oprange[r];
503  			oprange[AFSQRTD] = oprange[r];
504  			oprange[AFSQRTF] = oprange[r];
505  			break;
506  		case AFMOVF:
507  		case AFMOVD:
508  		case AMOVW:
509  		case AMOVD:
510  		case AWORD:
511  		case ARETT:
512  		case AJMPL:
513  		case AJMP:
514  		case ACMP:
515  		case ANOP:
516  		case ATEXT:
517  		case ADIV:
518  		case ADIVL:
519  		case AMOD:
520  		case AMODL:
521  			break;
522  		}
523  	}
524  }
525