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