xref: /plan9-contrib/sys/src/cmd/9l/span.c (revision fbadb1c4d4463e58337ffb1ed396c9caee5d1889)
1 #include	"l.h"
2 
3 void
span(void)4 span(void)
5 {
6 	Prog *p, *q;
7 	Sym *setext;
8 	Optab *o;
9 	int m, bflag;
10 	vlong c, otxt;
11 
12 	if(debug['v'])
13 		Bprint(&bso, "%5.2f span\n", cputime());
14 	Bflush(&bso);
15 
16 	bflag = 0;
17 	c = INITTEXT;
18 	otxt = c;
19 	for(p = firstp; p != P; p = p->link) {
20 		p->pc = c;
21 		o = oplook(p);
22 		m = o->size;
23 		if(m == 0) {
24 			if(p->as == ATEXT) {
25 				curtext = p;
26 				autosize = p->to.offset + 8;
27 				if(p->from3.type == D_CONST) {
28 					if(p->from3.offset & 3)
29 						diag("illegal origin\n%P", p);
30 					if(c > p->from3.offset)
31 						diag("passed origin (#%llux)\n%P", c, p);
32 					else
33 						c = p->from3.offset;
34 					p->pc = c;
35 				}
36 				if(p->from.sym != S)
37 					p->from.sym->value = c;
38 				/* need passes to resolve branches? */
39 				if(c-otxt >= (1L<<15))
40 					bflag = c;
41 				otxt = c;
42 				continue;
43 			}
44 			if(p->as != ANOP)
45 				diag("zero-width instruction\n%P", p);
46 			continue;
47 		}
48 		c += m;
49 	}
50 
51 	/*
52 	 * if any procedure is large enough to
53 	 * generate a large SBRA branch, then
54 	 * generate extra passes putting branches
55 	 * around jmps to fix. this is rare.
56 	 */
57 	while(bflag) {
58 		if(debug['v'])
59 			Bprint(&bso, "%5.2f span1\n", cputime());
60 		bflag = 0;
61 		c = INITTEXT;
62 		for(p = firstp; p != P; p = p->link) {
63 			p->pc = c;
64 			o = oplook(p);
65 			if((o->type == 16 || o->type == 17) && p->cond) {
66 				otxt = p->cond->pc - c;
67 				if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) {
68 					q = prg();
69 					q->link = p->link;
70 					p->link = q;
71 					q->as = ABR;
72 					q->to.type = D_BRANCH;
73 					q->cond = p->cond;
74 					p->cond = q;
75 					q = prg();
76 					q->link = p->link;
77 					p->link = q;
78 					q->as = ABR;
79 					q->to.type = D_BRANCH;
80 					q->cond = q->link->link;
81 					addnop(p->link);
82 					addnop(p);
83 					bflag = 1;
84 				}
85 			}
86 			m = o->size;
87 			if(m == 0) {
88 				if(p->as == ATEXT) {
89 					curtext = p;
90 					autosize = p->to.offset + 8;
91 					if(p->from.sym != S)
92 						p->from.sym->value = c;
93 					continue;
94 				}
95 				if(p->as != ANOP)
96 					diag("zero-width instruction\n%P", p);
97 				continue;
98 			}
99 			c += m;
100 		}
101 	}
102 
103 	c = rnd(c, 8);
104 
105 	setext = lookup("etext", 0);
106 	if(setext != S) {
107 		setext->value = c;
108 		textsize = c - INITTEXT;
109 	}
110 	if(INITRND)
111 		INITDAT = rnd(c, INITRND);
112 	if(debug['v'])
113 		Bprint(&bso, "tsize = %llux\n", textsize);
114 	Bflush(&bso);
115 }
116 
117 void
xdefine(char * p,int t,vlong v)118 xdefine(char *p, int t, vlong v)
119 {
120 	Sym *s;
121 
122 	s = lookup(p, 0);
123 	if(s->type == 0 || s->type == SXREF) {
124 		s->type = t;
125 		s->value = v;
126 	}
127 }
128 
129 vlong
vregoff(Adr * a)130 vregoff(Adr *a)
131 {
132 
133 	instoffset = 0;
134 	aclass(a);
135 	return instoffset;
136 }
137 
138 long
regoff(Adr * a)139 regoff(Adr *a)
140 {
141 	return vregoff(a);
142 }
143 
144 int
isint32(vlong v)145 isint32(vlong v)
146 {
147 	long l;
148 
149 	l = v;
150 	return (vlong)l == v;
151 }
152 
153 int
isuint32(uvlong v)154 isuint32(uvlong v)
155 {
156 	ulong l;
157 
158 	l = v;
159 	return (uvlong)l == v;
160 }
161 
162 int
aclass(Adr * a)163 aclass(Adr *a)
164 {
165 	Sym *s;
166 	int t;
167 
168 	switch(a->type) {
169 	case D_NONE:
170 		return C_NONE;
171 
172 	case D_REG:
173 		return C_REG;
174 
175 	case D_FREG:
176 		return C_FREG;
177 
178 	case D_CREG:
179 		return C_CREG;
180 
181 	case D_SPR:
182 		if(a->offset == D_LR)
183 			return C_LR;
184 		if(a->offset == D_XER)
185 			return C_XER;
186 		if(a->offset == D_CTR)
187 			return C_CTR;
188 		return C_SPR;
189 
190 	case D_DCR:
191 		return C_SPR;
192 
193 	case D_FPSCR:
194 		return C_FPSCR;
195 
196 	case D_MSR:
197 		return C_MSR;
198 
199 	case D_OREG:
200 		switch(a->name) {
201 		case D_EXTERN:
202 		case D_STATIC:
203 			if(a->sym == S)
204 				break;
205 			t = a->sym->type;
206 			if(t == 0 || t == SXREF) {
207 				diag("undefined external: %s in %s",
208 					a->sym->name, TNAME);
209 				a->sym->type = SDATA;
210 			}
211 			if(dlm){
212 				instoffset = a->sym->value + a->offset;
213 				switch(a->sym->type){
214 				case STEXT:
215 				case SLEAF:
216 				case SCONST:
217 				case SUNDEF:
218 					break;
219 				default:
220 					instoffset += INITDAT;
221 				}
222 				return C_ADDR;
223 			}
224 			instoffset = a->sym->value + a->offset - BIG;
225 			if(instoffset >= -BIG && instoffset < BIG)
226 				return C_SEXT;
227 			return C_LEXT;
228 		case D_AUTO:
229 			instoffset = autosize + a->offset;
230 			if(instoffset >= -BIG && instoffset < BIG)
231 				return C_SAUTO;
232 			return C_LAUTO;
233 		case D_PARAM:
234 			instoffset = autosize + a->offset + 8L;
235 			if(instoffset >= -BIG && instoffset < BIG)
236 				return C_SAUTO;
237 			return C_LAUTO;
238 		case D_NONE:
239 			instoffset = a->offset;
240 			if(instoffset == 0)
241 				return C_ZOREG;
242 			if(instoffset >= -BIG && instoffset < BIG)
243 				return C_SOREG;
244 			return C_LOREG;
245 		}
246 		return C_GOK;
247 
248 	case D_OPT:
249 		instoffset = a->offset & 31L;
250 		if(a->name == D_NONE)
251 			return C_SCON;
252 		return C_GOK;
253 
254 	case D_CONST:
255 		switch(a->name) {
256 
257 		case D_NONE:
258 			instoffset = a->offset;
259 		consize:
260 			if(instoffset >= 0) {
261 				if(instoffset == 0)
262 					return C_ZCON;
263 				if(instoffset <= 0x7fff)
264 					return C_SCON;
265 				if(instoffset <= 0xffff)
266 					return C_ANDCON;
267 				if((instoffset & 0xffff) == 0 && isuint32(instoffset))	/* && (instoffset & (1<<31)) == 0) */
268 					return C_UCON;
269 				if(isint32(instoffset) || isuint32(instoffset))
270 					return C_LCON;
271 				return C_DCON;
272 			}
273 			if(instoffset >= -0x8000)
274 				return C_ADDCON;
275 			if((instoffset & 0xffff) == 0 && isint32(instoffset))
276 				return C_UCON;
277 			if(isint32(instoffset))
278 				return C_LCON;
279 			return C_DCON;
280 
281 		case D_EXTERN:
282 		case D_STATIC:
283 			s = a->sym;
284 			if(s == S)
285 				break;
286 			t = s->type;
287 			if(t == 0 || t == SXREF) {
288 				diag("undefined external: %s in %s",
289 					s->name, TNAME);
290 				s->type = SDATA;
291 			}
292 			if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) {
293 				instoffset = s->value + a->offset;
294 				return C_LCON;
295 			}
296 			if(s->type == SCONST) {
297 				instoffset = s->value + a->offset;
298 				if(dlm)
299 					return C_LCON;
300 				goto consize;
301 			}
302 			if(!dlm){
303 				instoffset = s->value + a->offset - BIG;
304 				if(instoffset >= -BIG && instoffset < BIG && instoffset != 0)
305 					return C_SECON;
306 			}
307 			instoffset = s->value + a->offset + INITDAT;
308 			if(dlm)
309 				return C_LCON;
310 			/* not sure why this barfs */
311 			return C_LCON;
312 		/*
313 			if(instoffset == 0)
314 				return C_ZCON;
315 			if(instoffset >= -0x8000 && instoffset <= 0xffff)
316 				return C_SCON;
317 			if((instoffset & 0xffff) == 0)
318 				return C_UCON;
319 			return C_LCON;
320 		*/
321 
322 		case D_AUTO:
323 			instoffset = autosize + a->offset;
324 			if(instoffset >= -BIG && instoffset < BIG)
325 				return C_SACON;
326 			return C_LACON;
327 
328 		case D_PARAM:
329 			instoffset = autosize + a->offset + 8L;
330 			if(instoffset >= -BIG && instoffset < BIG)
331 				return C_SACON;
332 			return C_LACON;
333 		}
334 		return C_GOK;
335 
336 	case D_BRANCH:
337 		return C_SBRA;
338 	}
339 	return C_GOK;
340 }
341 
342 Optab*
oplook(Prog * p)343 oplook(Prog *p)
344 {
345 	int a1, a2, a3, a4, r;
346 	char *c1, *c3, *c4;
347 	Optab *o, *e;
348 
349 	a1 = p->optab;
350 	if(a1)
351 		return optab+(a1-1);
352 	a1 = p->from.class;
353 	if(a1 == 0) {
354 		a1 = aclass(&p->from) + 1;
355 		p->from.class = a1;
356 	}
357 	a1--;
358 	a3 = p->from3.class;
359 	if(a3 == 0) {
360 		a3 = aclass(&p->from3) + 1;
361 		p->from3.class = a3;
362 	}
363 	a3--;
364 	a4 = p->to.class;
365 	if(a4 == 0) {
366 		a4 = aclass(&p->to) + 1;
367 		p->to.class = a4;
368 	}
369 	a4--;
370 	a2 = C_NONE;
371 	if(p->reg != NREG)
372 		a2 = C_REG;
373 	r = p->as;
374 	o = oprange[r].start;
375 	if(o == 0)
376 		o = oprange[r].stop; /* just generate an error */
377 	e = oprange[r].stop;
378 	c1 = xcmp[a1];
379 	c3 = xcmp[a3];
380 	c4 = xcmp[a4];
381 	for(; o<e; o++)
382 		if(o->a2 == a2)
383 		if(c1[o->a1])
384 		if(c3[o->a3])
385 		if(c4[o->a4]) {
386 			p->optab = (o-optab)+1;
387 			return o;
388 		}
389 	diag("illegal combination %A %R %R %R %R",
390 		p->as, a1, a2, a3, a4);
391 	if(1||!debug['a'])
392 		prasm(p);
393 	if(o == 0)
394 		errorexit();
395 	return o;
396 }
397 
398 int
cmp(int a,int b)399 cmp(int a, int b)
400 {
401 
402 	if(a == b)
403 		return 1;
404 	switch(a) {
405 	case C_LCON:
406 		if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON)
407 			return 1;
408 		break;
409 	case C_ADDCON:
410 		if(b == C_ZCON || b == C_SCON)
411 			return 1;
412 		break;
413 	case C_ANDCON:
414 		if(b == C_ZCON || b == C_SCON)
415 			return 1;
416 		break;
417 	case C_SPR:
418 		if(b == C_LR || b == C_XER || b == C_CTR)
419 			return 1;
420 		break;
421 	case C_UCON:
422 		if(b == C_ZCON)
423 			return 1;
424 		break;
425 	case C_SCON:
426 		if(b == C_ZCON)
427 			return 1;
428 		break;
429 	case C_LACON:
430 		if(b == C_SACON)
431 			return 1;
432 		break;
433 	case C_LBRA:
434 		if(b == C_SBRA)
435 			return 1;
436 		break;
437 	case C_LEXT:
438 		if(b == C_SEXT)
439 			return 1;
440 		break;
441 	case C_LAUTO:
442 		if(b == C_SAUTO)
443 			return 1;
444 		break;
445 	case C_REG:
446 		if(b == C_ZCON)
447 			return r0iszero;
448 		break;
449 	case C_LOREG:
450 		if(b == C_ZOREG || b == C_SOREG)
451 			return 1;
452 		break;
453 	case C_SOREG:
454 		if(b == C_ZOREG)
455 			return 1;
456 		break;
457 
458 	case C_ANY:
459 		return 1;
460 	}
461 	return 0;
462 }
463 
464 int
ocmp(void * a1,void * a2)465 ocmp(void *a1, void *a2)
466 {
467 	Optab *p1, *p2;
468 	int n;
469 
470 	p1 = a1;
471 	p2 = a2;
472 	n = p1->as - p2->as;
473 	if(n)
474 		return n;
475 	n = p1->a1 - p2->a1;
476 	if(n)
477 		return n;
478 	n = p1->a2 - p2->a2;
479 	if(n)
480 		return n;
481 	n = p1->a3 - p2->a3;
482 	if(n)
483 		return n;
484 	n = p1->a4 - p2->a4;
485 	if(n)
486 		return n;
487 	return 0;
488 }
489 
490 void
buildop(void)491 buildop(void)
492 {
493 	int i, n, r;
494 
495 	for(i=0; i<C_NCLASS; i++)
496 		for(n=0; n<C_NCLASS; n++)
497 			xcmp[i][n] = cmp(n, i);
498 	for(n=0; optab[n].as != AXXX; n++)
499 		;
500 	qsort(optab, n, sizeof(optab[0]), ocmp);
501 	for(i=0; i<n; i++) {
502 		r = optab[i].as;
503 		oprange[r].start = optab+i;
504 		while(optab[i].as == r)
505 			i++;
506 		oprange[r].stop = optab+i;
507 		i--;
508 
509 		switch(r)
510 		{
511 		default:
512 			diag("unknown op in build: %A", r);
513 			errorexit();
514 		case ADCBF:	/* unary indexed: op (b+a); op (b) */
515 			oprange[ADCBI] = oprange[r];
516 			oprange[ADCBST] = oprange[r];
517 			oprange[ADCBT] = oprange[r];
518 			oprange[ADCBTST] = oprange[r];
519 			oprange[ADCBZ] = oprange[r];
520 			oprange[AICBI] = oprange[r];
521 			break;
522 		case AECOWX:	/* indexed store: op s,(b+a); op s,(b) */
523 			oprange[ASTWCCC] = oprange[r];
524 			break;
525 		case AREM:	/* macro */
526 			oprange[AREMCC] = oprange[r];
527 			oprange[AREMV] = oprange[r];
528 			oprange[AREMVCC] = oprange[r];
529 			oprange[AREMU] = oprange[r];
530 			oprange[AREMUCC] = oprange[r];
531 			oprange[AREMUV] = oprange[r];
532 			oprange[AREMUVCC] = oprange[r];
533 			break;
534 		case AREMD:
535 			oprange[AREMDCC] = oprange[r];
536 			oprange[AREMDV] = oprange[r];
537 			oprange[AREMDVCC] = oprange[r];
538 			oprange[AREMDU] = oprange[r];
539 			oprange[AREMDUCC] = oprange[r];
540 			oprange[AREMDUV] = oprange[r];
541 			oprange[AREMDUVCC] = oprange[r];
542 			break;
543 		case ADIVW:	/* op Rb[,Ra],Rd */
544 			oprange[AMULHW] = oprange[r];
545 			oprange[AMULHWCC] = oprange[r];
546 			oprange[AMULHWU] = oprange[r];
547 			oprange[AMULHWUCC] = oprange[r];
548 			oprange[AMULLWCC] = oprange[r];
549 			oprange[AMULLWVCC] = oprange[r];
550 			oprange[AMULLWV] = oprange[r];
551 			oprange[ADIVWCC] = oprange[r];
552 			oprange[ADIVWV] = oprange[r];
553 			oprange[ADIVWVCC] = oprange[r];
554 			oprange[ADIVWU] = oprange[r];
555 			oprange[ADIVWUCC] = oprange[r];
556 			oprange[ADIVWUV] = oprange[r];
557 			oprange[ADIVWUVCC] = oprange[r];
558 			oprange[AADDCC] = oprange[r];
559 			oprange[AADDCV] = oprange[r];
560 			oprange[AADDCVCC] = oprange[r];
561 			oprange[AADDV] = oprange[r];
562 			oprange[AADDVCC] = oprange[r];
563 			oprange[AADDE] = oprange[r];
564 			oprange[AADDECC] = oprange[r];
565 			oprange[AADDEV] = oprange[r];
566 			oprange[AADDEVCC] = oprange[r];
567 			oprange[ACRAND] = oprange[r];
568 			oprange[ACRANDN] = oprange[r];
569 			oprange[ACREQV] = oprange[r];
570 			oprange[ACRNAND] = oprange[r];
571 			oprange[ACRNOR] = oprange[r];
572 			oprange[ACROR] = oprange[r];
573 			oprange[ACRORN] = oprange[r];
574 			oprange[ACRXOR] = oprange[r];
575 			oprange[AMULHD] = oprange[r];
576 			oprange[AMULHDCC] = oprange[r];
577 			oprange[AMULHDU] = oprange[r];
578 			oprange[AMULHDUCC] = oprange[r];
579 			oprange[AMULLD] = oprange[r];
580 			oprange[AMULLDCC] = oprange[r];
581 			oprange[AMULLDVCC] = oprange[r];
582 			oprange[AMULLDV] = oprange[r];
583 			oprange[ADIVD] = oprange[r];
584 			oprange[ADIVDCC] = oprange[r];
585 			oprange[ADIVDVCC] = oprange[r];
586 			oprange[ADIVDV] = oprange[r];
587 			oprange[ADIVDU] = oprange[r];
588 			oprange[ADIVDUCC] = oprange[r];
589 			oprange[ADIVDUVCC] = oprange[r];
590 			oprange[ADIVDUCC] = oprange[r];
591 			break;
592 		case AMOVBZ:	/* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
593 			oprange[AMOVH] = oprange[r];
594 			oprange[AMOVHZ] = oprange[r];
595 			break;
596 		case AMOVBZU:	/* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
597 			oprange[AMOVHU] = oprange[r];
598 			oprange[AMOVHZU] = oprange[r];
599 			oprange[AMOVWU] = oprange[r];
600 			oprange[AMOVWZU] = oprange[r];
601 			oprange[AMOVDU] = oprange[r];
602 			oprange[AMOVMW] = oprange[r];
603 			break;
604 		case AAND:	/* logical op Rb,Rs,Ra; no literal */
605 			oprange[AANDN] = oprange[r];
606 			oprange[AANDNCC] = oprange[r];
607 			oprange[AEQV] = oprange[r];
608 			oprange[AEQVCC] = oprange[r];
609 			oprange[ANAND] = oprange[r];
610 			oprange[ANANDCC] = oprange[r];
611 			oprange[ANOR] = oprange[r];
612 			oprange[ANORCC] = oprange[r];
613 			oprange[AORCC] = oprange[r];
614 			oprange[AORN] = oprange[r];
615 			oprange[AORNCC] = oprange[r];
616 			oprange[AXORCC] = oprange[r];
617 			break;
618 		case AADDME:	/* op Ra, Rd */
619 			oprange[AADDMECC] = oprange[r];
620 			oprange[AADDMEV] = oprange[r];
621 			oprange[AADDMEVCC] = oprange[r];
622 			oprange[AADDZE] = oprange[r];
623 			oprange[AADDZECC] = oprange[r];
624 			oprange[AADDZEV] = oprange[r];
625 			oprange[AADDZEVCC] = oprange[r];
626 			oprange[ASUBME] = oprange[r];
627 			oprange[ASUBMECC] = oprange[r];
628 			oprange[ASUBMEV] = oprange[r];
629 			oprange[ASUBMEVCC] = oprange[r];
630 			oprange[ASUBZE] = oprange[r];
631 			oprange[ASUBZECC] = oprange[r];
632 			oprange[ASUBZEV] = oprange[r];
633 			oprange[ASUBZEVCC] = oprange[r];
634 			break;
635 		case AADDC:
636 			oprange[AADDCCC] = oprange[r];
637 			break;
638 		case ABEQ:
639 			oprange[ABGE] = oprange[r];
640 			oprange[ABGT] = oprange[r];
641 			oprange[ABLE] = oprange[r];
642 			oprange[ABLT] = oprange[r];
643 			oprange[ABNE] = oprange[r];
644 			oprange[ABVC] = oprange[r];
645 			oprange[ABVS] = oprange[r];
646 			break;
647 		case ABR:
648 			oprange[ABL] = oprange[r];
649 			break;
650 		case ABC:
651 			oprange[ABCL] = oprange[r];
652 			break;
653 		case AEXTSB:	/* op Rs, Ra */
654 			oprange[AEXTSBCC] = oprange[r];
655 			oprange[AEXTSH] = oprange[r];
656 			oprange[AEXTSHCC] = oprange[r];
657 			oprange[ACNTLZW] = oprange[r];
658 			oprange[ACNTLZWCC] = oprange[r];
659 			oprange[ACNTLZD] = oprange[r];
660 			oprange[AEXTSW] = oprange[r];
661 			oprange[AEXTSWCC] = oprange[r];
662 			oprange[ACNTLZDCC] = oprange[r];
663 			break;
664 		case AFABS:	/* fop [s,]d */
665 			oprange[AFABSCC] = oprange[r];
666 			oprange[AFNABS] = oprange[r];
667 			oprange[AFNABSCC] = oprange[r];
668 			oprange[AFNEG] = oprange[r];
669 			oprange[AFNEGCC] = oprange[r];
670 			oprange[AFRSP] = oprange[r];
671 			oprange[AFRSPCC] = oprange[r];
672 			oprange[AFCTIW] = oprange[r];
673 			oprange[AFCTIWCC] = oprange[r];
674 			oprange[AFCTIWZ] = oprange[r];
675 			oprange[AFCTIWZCC] = oprange[r];
676 			oprange[AFCTID] = oprange[r];
677 			oprange[AFCTIDCC] = oprange[r];
678 			oprange[AFCTIDZ] = oprange[r];
679 			oprange[AFCTIDZCC] = oprange[r];
680 			oprange[AFCFID] = oprange[r];
681 			oprange[AFCFIDCC] = oprange[r];
682 			oprange[AFRES] = oprange[r];
683 			oprange[AFRESCC] = oprange[r];
684 			oprange[AFRSQRTE] = oprange[r];
685 			oprange[AFRSQRTECC] = oprange[r];
686 			oprange[AFSQRT] = oprange[r];
687 			oprange[AFSQRTCC] = oprange[r];
688 			oprange[AFSQRTS] = oprange[r];
689 			oprange[AFSQRTSCC] = oprange[r];
690 			break;
691 		case AFADD:
692 			oprange[AFADDS] = oprange[r];
693 			oprange[AFADDCC] = oprange[r];
694 			oprange[AFADDSCC] = oprange[r];
695 			oprange[AFDIV] = oprange[r];
696 			oprange[AFDIVS] = oprange[r];
697 			oprange[AFDIVCC] = oprange[r];
698 			oprange[AFDIVSCC] = oprange[r];
699 			oprange[AFSUB] = oprange[r];
700 			oprange[AFSUBS] = oprange[r];
701 			oprange[AFSUBCC] = oprange[r];
702 			oprange[AFSUBSCC] = oprange[r];
703 			break;
704 		case AFMADD:
705 			oprange[AFMADDCC] = oprange[r];
706 			oprange[AFMADDS] = oprange[r];
707 			oprange[AFMADDSCC] = oprange[r];
708 			oprange[AFMSUB] = oprange[r];
709 			oprange[AFMSUBCC] = oprange[r];
710 			oprange[AFMSUBS] = oprange[r];
711 			oprange[AFMSUBSCC] = oprange[r];
712 			oprange[AFNMADD] = oprange[r];
713 			oprange[AFNMADDCC] = oprange[r];
714 			oprange[AFNMADDS] = oprange[r];
715 			oprange[AFNMADDSCC] = oprange[r];
716 			oprange[AFNMSUB] = oprange[r];
717 			oprange[AFNMSUBCC] = oprange[r];
718 			oprange[AFNMSUBS] = oprange[r];
719 			oprange[AFNMSUBSCC] = oprange[r];
720 			oprange[AFSEL] = oprange[r];
721 			oprange[AFSELCC] = oprange[r];
722 			break;
723 		case AFMUL:
724 			oprange[AFMULS] = oprange[r];
725 			oprange[AFMULCC] = oprange[r];
726 			oprange[AFMULSCC] = oprange[r];
727 			break;
728 		case AFCMPO:
729 			oprange[AFCMPU] = oprange[r];
730 			break;
731 		case AMTFSB0:
732 			oprange[AMTFSB0CC] = oprange[r];
733 			oprange[AMTFSB1] = oprange[r];
734 			oprange[AMTFSB1CC] = oprange[r];
735 			break;
736 		case ANEG:	/* op [Ra,] Rd */
737 			oprange[ANEGCC] = oprange[r];
738 			oprange[ANEGV] = oprange[r];
739 			oprange[ANEGVCC] = oprange[r];
740 			break;
741 		case AOR:	/* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
742 			oprange[AXOR] = oprange[r];
743 			break;
744 		case ASLW:
745 			oprange[ASLWCC] = oprange[r];
746 			oprange[ASRW] = oprange[r];
747 			oprange[ASRWCC] = oprange[r];
748 			break;
749 		case ASLD:
750 			oprange[ASLDCC] = oprange[r];
751 			oprange[ASRD] = oprange[r];
752 			oprange[ASRDCC] = oprange[r];
753 			break;
754 		case ASRAW:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
755 			oprange[ASRAWCC] = oprange[r];
756 			break;
757 		case ASRAD:	/* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
758 			oprange[ASRADCC] = oprange[r];
759 			break;
760 		case ASUB:	/* SUB Ra,Rb,Rd => subf Rd,ra,rb */
761 			oprange[ASUB] = oprange[r];
762 			oprange[ASUBCC] = oprange[r];
763 			oprange[ASUBV] = oprange[r];
764 			oprange[ASUBVCC] = oprange[r];
765 			oprange[ASUBCCC] = oprange[r];
766 			oprange[ASUBCV] = oprange[r];
767 			oprange[ASUBCVCC] = oprange[r];
768 			oprange[ASUBE] = oprange[r];
769 			oprange[ASUBECC] = oprange[r];
770 			oprange[ASUBEV] = oprange[r];
771 			oprange[ASUBEVCC] = oprange[r];
772 			break;
773 		case ASYNC:
774 			oprange[AISYNC] = oprange[r];
775 			oprange[APTESYNC] = oprange[r];
776 			oprange[ATLBSYNC] = oprange[r];
777 			break;
778 		case ARLWMI:
779 			oprange[ARLWMICC] = oprange[r];
780 			oprange[ARLWNM] = oprange[r];
781 			oprange[ARLWNMCC] = oprange[r];
782 			break;
783 		case ARLDMI:
784 			oprange[ARLDMICC] = oprange[r];
785 			break;
786 		case ARLDC:
787 			oprange[ARLDCCC] = oprange[r];
788 			break;
789 		case ARLDCL:
790 			oprange[ARLDCR] = oprange[r];
791 			oprange[ARLDCLCC] = oprange[r];
792 			oprange[ARLDCRCC] = oprange[r];
793 			break;
794 		case AFMOVD:
795 			oprange[AFMOVDCC] = oprange[r];
796 			oprange[AFMOVDU] = oprange[r];
797 			oprange[AFMOVS] = oprange[r];
798 			oprange[AFMOVSU] = oprange[r];
799 			break;
800 		case AECIWX:
801 			oprange[ALWAR] = oprange[r];
802 			break;
803 		case ASYSCALL:	/* just the op; flow of control */
804 			oprange[ARFI] = oprange[r];
805 			oprange[ARFCI] = oprange[r];
806 			oprange[ARFID] = oprange[r];
807 			oprange[AHRFID] = oprange[r];
808 			break;
809 		case AMOVHBR:
810 			oprange[AMOVWBR] = oprange[r];
811 			break;
812 		case ASLBMFEE:
813 			oprange[ASLBMFEV] = oprange[r];
814 			break;
815 		case ATW:
816 			oprange[ATD] = oprange[r];
817 			break;
818 		case ATLBIE:
819 			oprange[ASLBIE] = oprange[r];
820 			oprange[ATLBIEL] = oprange[r];
821 			break;
822 		case AEIEIO:
823 			oprange[ASLBIA] = oprange[r];
824 			break;
825 		case ACMP:
826 			oprange[ACMPW] = oprange[r];
827 			break;
828 		case ACMPU:
829 			oprange[ACMPWU] = oprange[r];
830 			break;
831 		case AADD:
832 		case AANDCC:	/* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
833 		case ALSW:
834 		case AMOVW:	/* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
835 		case AMOVWZ:	/* load/store/move word with zero extension; move 32-bit literals  */
836 		case AMOVD:	/* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
837 		case AMOVB:	/* macro: move byte with sign extension */
838 		case AMOVBU:	/* macro: move byte with sign extension & update */
839 		case AMOVFL:
840 		case AMULLW:	/* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
841 		case ASUBC:	/* op r1,$s,r3; op r1[,r2],r3 */
842 		case ASTSW:
843 		case ASLBMTE:
844 		case AWORD:
845 		case ADWORD:
846 		case ANOP:
847 		case ATEXT:
848 			break;
849 		}
850 	}
851 }
852 
853 enum{
854 	ABSD = 0,
855 	ABSU = 1,
856 	RELD = 2,
857 	RELU = 3,
858 };
859 
860 int modemap[8] = { 0, 1, -1, 2, 3, 4, 5, 6};
861 
862 typedef struct Reloc Reloc;
863 
864 struct Reloc
865 {
866 	int n;
867 	int t;
868 	uchar *m;
869 	ulong *a;
870 };
871 
872 Reloc rels;
873 
874 static void
grow(Reloc * r)875 grow(Reloc *r)
876 {
877 	int t;
878 	uchar *m, *nm;
879 	ulong *a, *na;
880 
881 	t = r->t;
882 	r->t += 64;
883 	m = r->m;
884 	a = r->a;
885 	r->m = nm = malloc(r->t*sizeof(uchar));
886 	r->a = na = malloc(r->t*sizeof(ulong));
887 	memmove(nm, m, t*sizeof(uchar));
888 	memmove(na, a, t*sizeof(ulong));
889 	free(m);
890 	free(a);
891 }
892 
893 void
dynreloc(Sym * s,long v,int abs,int split,int sext)894 dynreloc(Sym *s, long v, int abs, int split, int sext)
895 {
896 	int i, k, n;
897 	uchar *m;
898 	ulong *a;
899 	Reloc *r;
900 
901 	if(v&3)
902 		diag("bad relocation address");
903 	v >>= 2;
904 	if(s->type == SUNDEF)
905 		k = abs ? ABSU : RELU;
906 	else
907 		k = abs ? ABSD : RELD;
908 	if(split)
909 		k += 4;
910 	if(sext)
911 		k += 2;
912 	/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
913 	k = modemap[k];
914 	r = &rels;
915 	n = r->n;
916 	if(n >= r->t)
917 		grow(r);
918 	m = r->m;
919 	a = r->a;
920 	for(i = n; i > 0; i--){
921 		if(v < a[i-1]){	/* happens occasionally for data */
922 			m[i] = m[i-1];
923 			a[i] = a[i-1];
924 		}
925 		else
926 			break;
927 	}
928 	m[i] = k;
929 	a[i] = v;
930 	r->n++;
931 }
932 
933 static int
sput(char * s)934 sput(char *s)
935 {
936 	char *p;
937 
938 	p = s;
939 	while(*s)
940 		cput(*s++);
941 	cput(0);
942 	return s-p+1;
943 }
944 
945 void
asmdyn()946 asmdyn()
947 {
948 	int i, n, t, c;
949 	Sym *s;
950 	ulong la, ra, *a;
951 	vlong off;
952 	uchar *m;
953 	Reloc *r;
954 
955 	cflush();
956 	off = seek(cout, 0, 1);
957 	lput(0);
958 	t = 0;
959 	lput(imports);
960 	t += 4;
961 	for(i = 0; i < NHASH; i++)
962 		for(s = hash[i]; s != S; s = s->link)
963 			if(s->type == SUNDEF){
964 				lput(s->sig);
965 				t += 4;
966 				t += sput(s->name);
967 			}
968 
969 	la = 0;
970 	r = &rels;
971 	n = r->n;
972 	m = r->m;
973 	a = r->a;
974 	lput(n);
975 	t += 4;
976 	for(i = 0; i < n; i++){
977 		ra = *a-la;
978 		if(*a < la)
979 			diag("bad relocation order");
980 		if(ra < 256)
981 			c = 0;
982 		else if(ra < 65536)
983 			c = 1;
984 		else
985 			c = 2;
986 		cput((c<<6)|*m++);
987 		t++;
988 		if(c == 0){
989 			cput(ra);
990 			t++;
991 		}
992 		else if(c == 1){
993 			wput(ra);
994 			t += 2;
995 		}
996 		else{
997 			lput(ra);
998 			t += 4;
999 		}
1000 		la = *a++;
1001 	}
1002 
1003 	cflush();
1004 	seek(cout, off, 0);
1005 	lput(t);
1006 
1007 	if(debug['v']){
1008 		Bprint(&bso, "import table entries = %d\n", imports);
1009 		Bprint(&bso, "export table entries = %d\n", exports);
1010 	}
1011 }
1012