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