xref: /inferno-os/utils/kl/span.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
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 			if(instoffset == 0)
186 				return C_ZCON;
187 			if(instoffset >= -0x1000 && instoffset <= 0xfff)
188 				return C_SCON;
189 			if((instoffset & 0x3ff) == 0)
190 				return C_UCON;
191 			return C_LCON;
192 
193 		case D_AUTO:
194 			instoffset = autosize + a->offset;
195 			if(instoffset >= -BIG && instoffset < BIG)
196 				return C_SACON;
197 			return C_LACON;
198 
199 		case D_PARAM:
200 			instoffset = autosize + a->offset + 4L;
201 			if(instoffset >= -BIG && instoffset < BIG)
202 				return C_SACON;
203 			return C_LACON;
204 		}
205 		return C_GOK;
206 
207 	case D_BRANCH:
208 		return C_SBRA;
209 	}
210 	return C_GOK;
211 }
212 
213 Optab*
214 oplook(Prog *p)
215 {
216 	int a1, a2, a3, r;
217 	char *c1, *c3;
218 	Optab *o, *e;
219 
220 	a1 = p->optab;
221 	if(a1)
222 		return optab+(a1-1);
223 	a1 = p->from.class;
224 	if(a1 == 0) {
225 		a1 = aclass(&p->from) + 1;
226 		p->from.class = a1;
227 	}
228 	a1--;
229 	a3 = p->to.class;
230 	if(a3 == 0) {
231 		a3 = aclass(&p->to) + 1;
232 		p->to.class = a3;
233 	}
234 	a3--;
235 	a2 = C_NONE;
236 	if(p->reg != NREG)
237 		a2 = C_REG;
238 	r = p->as;
239 	o = oprange[r].start;
240 	if(o == 0)
241 		o = oprange[r].stop; /* just generate an error */
242 	e = oprange[r].stop;
243 	c1 = xcmp[a1];
244 	c3 = xcmp[a3];
245 	for(; o<e; o++)
246 		if(o->a2 == a2)
247 		if(c1[o->a1])
248 		if(c3[o->a3]) {
249 			p->optab = (o-optab)+1;
250 			return o;
251 		}
252 	diag("illegal combination %A %d %d %d",
253 		p->as, a1, a2, a3);
254 	if(1||!debug['a'])
255 		prasm(p);
256 	if(o == 0)
257 		errorexit();
258 	return o;
259 }
260 
261 int
262 cmp(int a, int b)
263 {
264 
265 	if(a == b)
266 		return 1;
267 	switch(a) {
268 	case C_LCON:
269 		if(b == C_ZCON || b == C_SCON || b == C_UCON)
270 			return 1;
271 		break;
272 	case C_UCON:
273 		if(b == C_ZCON)
274 			return 1;
275 		break;
276 	case C_SCON:
277 		if(b == C_ZCON)
278 			return 1;
279 		break;
280 	case C_LACON:
281 		if(b == C_SACON)
282 			return 1;
283 		break;
284 	case C_LBRA:
285 		if(b == C_SBRA)
286 			return 1;
287 		break;
288 	case C_ELEXT:
289 		if(b == C_ESEXT)
290 			return 1;
291 		break;
292 	case C_LEXT:
293 		if(b == C_SEXT ||
294 		   b == C_ESEXT || b == C_OSEXT ||
295 		   b == C_ELEXT || b == C_OLEXT)
296 			return 1;
297 		break;
298 	case C_SEXT:
299 		if(b == C_ESEXT || b == C_OSEXT)
300 			return 1;
301 		break;
302 	case C_ELAUTO:
303 		if(b == C_ESAUTO)
304 			return 1;
305 		break;
306 	case C_LAUTO:
307 		if(b == C_SAUTO ||
308 		   b == C_ESAUTO || b == C_OSAUTO ||
309 		   b == C_ELAUTO || b == C_OLAUTO)
310 			return 1;
311 		break;
312 	case C_SAUTO:
313 		if(b == C_ESAUTO || b == C_OSAUTO)
314 			return 1;
315 		break;
316 	case C_REG:
317 		if(b == C_ZCON)
318 			return 1;
319 		break;
320 	case C_LOREG:
321 		if(b == C_ZOREG || b == C_SOREG)
322 			return 1;
323 		break;
324 	case C_SOREG:
325 		if(b == C_ZOREG)
326 			return 1;
327 		break;
328 
329 	case C_ANY:
330 		return 1;
331 	}
332 	return 0;
333 }
334 
335 int
336 ocmp(const void *a1, const void *a2)
337 {
338 	Optab *p1, *p2;
339 	int n;
340 
341 	p1 = (Optab*)a1;
342 	p2 = (Optab*)a2;
343 	n = p1->as - p2->as;
344 	if(n)
345 		return n;
346 	n = p1->a1 - p2->a1;
347 	if(n)
348 		return n;
349 	n = p1->a2 - p2->a2;
350 	if(n)
351 		return n;
352 	n = p1->a3 - p2->a3;
353 	if(n)
354 		return n;
355 	return 0;
356 }
357 
358 void
359 buildop(void)
360 {
361 	int i, n, r;
362 
363 	for(i=0; i<C_NCLASS; i++)
364 		for(n=0; n<C_NCLASS; n++)
365 			xcmp[i][n] = cmp(n, i);
366 	for(n=0; optab[n].as != AXXX; n++)
367 		;
368 	qsort(optab, n, sizeof(optab[0]), ocmp);
369 	for(i=0; i<n; i++) {
370 		r = optab[i].as;
371 		oprange[r].start = optab+i;
372 		while(optab[i].as == r)
373 			i++;
374 		oprange[r].stop = optab+i;
375 		i--;
376 
377 		switch(r)
378 		{
379 		default:
380 			diag("unknown op in build: %A", r);
381 			errorexit();
382 		case AADD:
383 			oprange[AADDX] = oprange[r];
384 			oprange[ASUB] = oprange[r];
385 			oprange[ASUBX] = oprange[r];
386 			oprange[AMUL] = oprange[r];
387 			oprange[AXOR] = oprange[r];
388 			oprange[AXNOR] = oprange[r];
389 			oprange[AAND] = oprange[r];
390 			oprange[AANDN] = oprange[r];
391 			oprange[AOR] = oprange[r];
392 			oprange[AORN] = oprange[r];
393 			oprange[ASLL] = oprange[r];
394 			oprange[ASRL] = oprange[r];
395 			oprange[ASRA] = oprange[r];
396 			oprange[AADDCC] = oprange[r];
397 			oprange[AADDXCC] = oprange[r];
398 			oprange[ATADDCC] = oprange[r];
399 			oprange[ATADDCCTV] = oprange[r];
400 			oprange[ASUBCC] = oprange[r];
401 			oprange[ASUBXCC] = oprange[r];
402 			oprange[ATSUBCC] = oprange[r];
403 			oprange[ATSUBCCTV] = oprange[r];
404 			oprange[AXORCC] = oprange[r];
405 			oprange[AXNORCC] = oprange[r];
406 			oprange[AANDCC] = oprange[r];
407 			oprange[AANDNCC] = oprange[r];
408 			oprange[AORCC] = oprange[r];
409 			oprange[AORNCC] = oprange[r];
410 			oprange[AMULSCC] = oprange[r];
411 			oprange[ASAVE] = oprange[r];
412 			oprange[ARESTORE] = oprange[r];
413 			break;
414 		case AMOVB:
415 			oprange[AMOVH] = oprange[r];
416 			oprange[AMOVHU] = oprange[r];
417 			oprange[AMOVBU] = oprange[r];
418 			oprange[ASWAP] = oprange[r];
419 			oprange[ATAS] = oprange[r];
420 			break;
421 		case ABA:
422 			oprange[ABN] = oprange[r];
423 			oprange[AFBA] = oprange[r];
424 			oprange[AFBN] = oprange[r];
425 			break;
426 		case ABE:
427 			oprange[ABCC] = oprange[r];
428 			oprange[ABCS] = oprange[r];
429 			oprange[ABGE] = oprange[r];
430 			oprange[ABGU] = oprange[r];
431 			oprange[ABG] = oprange[r];
432 			oprange[ABLEU] = oprange[r];
433 			oprange[ABLE] = oprange[r];
434 			oprange[ABL] = oprange[r];
435 			oprange[ABNEG] = oprange[r];
436 			oprange[ABNE] = oprange[r];
437 			oprange[ABPOS] = oprange[r];
438 			oprange[ABVC] = oprange[r];
439 			oprange[ABVS] = oprange[r];
440 
441 			oprange[AFBE] = oprange[r];
442 			oprange[AFBG] = oprange[r];
443 			oprange[AFBGE] = oprange[r];
444 			oprange[AFBL] = oprange[r];
445 			oprange[AFBLE] = oprange[r];
446 			oprange[AFBLG] = oprange[r];
447 			oprange[AFBNE] = oprange[r];
448 			oprange[AFBO] = oprange[r];
449 			oprange[AFBU] = oprange[r];
450 			oprange[AFBUE] = oprange[r];
451 			oprange[AFBUG] = oprange[r];
452 			oprange[AFBUGE] = oprange[r];
453 			oprange[AFBUL] = oprange[r];
454 			oprange[AFBULE] = oprange[r];
455 			break;
456 		case ATA:
457 			oprange[ATCC] = oprange[r];
458 			oprange[ATCS] = oprange[r];
459 			oprange[ATE] = oprange[r];
460 			oprange[ATGE] = oprange[r];
461 			oprange[ATGU] = oprange[r];
462 			oprange[ATG] = oprange[r];
463 			oprange[ATLEU] = oprange[r];
464 			oprange[ATLE] = oprange[r];
465 			oprange[ATL] = oprange[r];
466 			oprange[ATNEG] = oprange[r];
467 			oprange[ATNE] = oprange[r];
468 			oprange[ATN] = oprange[r];
469 			oprange[ATPOS] = oprange[r];
470 			oprange[ATVC] = oprange[r];
471 			oprange[ATVS] = oprange[r];
472 			break;
473 		case AFADDD:
474 			oprange[AFADDF] = oprange[r];
475 			oprange[AFADDX] = oprange[r];
476 			oprange[AFDIVD] = oprange[r];
477 			oprange[AFDIVF] = oprange[r];
478 			oprange[AFDIVX] = oprange[r];
479 			oprange[AFMULD] = oprange[r];
480 			oprange[AFMULF] = oprange[r];
481 			oprange[AFMULX] = oprange[r];
482 			oprange[AFSUBD] = oprange[r];
483 			oprange[AFSUBF] = oprange[r];
484 			oprange[AFSUBX] = oprange[r];
485 			break;
486 		case AFCMPD:
487 			oprange[AFCMPF] = oprange[r];
488 			oprange[AFCMPX] = oprange[r];
489 			oprange[AFCMPED] = oprange[r];
490 			oprange[AFCMPEF] = oprange[r];
491 			oprange[AFCMPEX] = oprange[r];
492 			break;
493 		case AFABSF:
494 			oprange[AFMOVDF] = oprange[r];
495 			oprange[AFMOVDW] = oprange[r];
496 			oprange[AFMOVFD] = oprange[r];
497 			oprange[AFMOVFW] = oprange[r];
498 			oprange[AFMOVWD] = oprange[r];
499 			oprange[AFMOVWF] = oprange[r];
500 			oprange[AFNEGF] = oprange[r];
501 			oprange[AFSQRTD] = oprange[r];
502 			oprange[AFSQRTF] = oprange[r];
503 			break;
504 		case AFMOVF:
505 		case AFMOVD:
506 		case AMOVW:
507 		case AMOVD:
508 		case AWORD:
509 		case ARETT:
510 		case AJMPL:
511 		case AJMP:
512 		case ACMP:
513 		case ANOP:
514 		case ATEXT:
515 		case ADIV:
516 		case ADIVL:
517 		case AMOD:
518 		case AMODL:
519 			break;
520 		}
521 	}
522 }
523