Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"l.h"
2
 
3
void
4
pagebug(Prog *p)
5
{
6
	Prog *q;
7
 
8
	switch(p->as) {
9
	case ABGEZAL:
10
	case ABLTZAL:
11
	case AJAL:
12
	case ABEQ:
13
	case ABGEZ:
14
	case ABGTZ:
15
	case ABLEZ:
16
	case ABLTZ:
17
	case ABNE:
18
	case ABFPT:
19
	case ABFPF:
20
	case AJMP:
21
		q = prg();
22
		*q = *p;
23
		p->link = q;
24
		p->as = ANOR;
25
		p->optab = 0;
26
		p->from = zprg.from;
27
		p->from.type = D_REG;
28
		p->from.reg = REGZERO;
29
		p->to = p->from;
30
	}
31
}
32
 
33
void
34
span(void)
35
{
36
	Prog *p, *q;
37
	Sym *setext, *s;
38
	Optab *o;
39
	int m, bflag, i;
40
	vlong c, otxt, v;
41
 
42
	if(debug['v'])
43
		Bprint(&bso, "%5.2f span\n", cputime());
44
	Bflush(&bso);
45
 
46
	bflag = 0;
47
	c = INITTEXT;
48
	otxt = c;
49
	for(p = firstp; p != P; p = p->link) {
50
		/* bug in early 4000 chips delayslot on page boundary */
51
		if((c&(0x1000-1)) == 0xffc)
52
			pagebug(p);
53
		p->pc = c;
54
		o = oplook(p);
55
		m = o->size;
56
		if(m == 0) {
57
			if(p->as == ATEXT) {
58
				curtext = p;
59
				autosize = p->to.offset + 4;
60
				if(p->from.sym != S)
61
					p->from.sym->value = c;
62
				/* need passes to resolve branches */
63
				if(c-otxt >= 1L<<17)
64
					bflag = 1;
65
				otxt = c;
66
				continue;
67
			}
68
			diag("zero-width instruction\n%P", p);
69
			continue;
70
		}
71
		c += m;
72
	}
73
 
74
	/*
75
	 * if any procedure is large enough to
76
	 * generate a large SBRA branch, then
77
	 * generate extra passes putting branches
78
	 * around jmps to fix. this is rare.
79
	 */
80
	while(bflag) {
81
		if(debug['v'])
82
			Bprint(&bso, "%5.2f span1\n", cputime());
83
		bflag = 0;
84
		c = INITTEXT;
85
		for(p = firstp; p != P; p = p->link) {
86
			/* bug in early 4000 chips delayslot on page boundary */
87
			if((c&(0x1000-1)) == 0xffc)
88
				pagebug(p);
89
			p->pc = c;
90
			o = oplook(p);
91
			if(o->type == 6 && p->cond) {
92
				otxt = p->cond->pc - c;
93
				if(otxt < 0)
94
					otxt = -otxt;
95
				if(otxt >= (1L<<17) - 10) {
96
					q = prg();
97
					q->link = p->link;
98
					p->link = q;
99
					q->as = AJMP;
100
					q->to.type = D_BRANCH;
101
					q->cond = p->cond;
102
					p->cond = q;
103
					q = prg();
104
					q->link = p->link;
105
					p->link = q;
106
					q->as = AJMP;
107
					q->to.type = D_BRANCH;
108
					q->cond = q->link->link;
109
					addnop(p->link);
110
					addnop(p);
111
					bflag = 1;
112
				}
113
			}
114
			m = o->size;
115
			if(m == 0) {
116
				if(p->as == ATEXT) {
117
					curtext = p;
118
					autosize = p->to.offset + 4;
119
					if(p->from.sym != S)
120
						p->from.sym->value = c;
121
					continue;
122
				}
123
				diag("zero-width instruction\n%P", p);
124
				continue;
125
			}
126
			c += m;
127
		}
128
	}
129
 
130
	if(debug['t']) {
131
		/* 
132
		 * add strings to text segment
133
		 */
134
		c = rnd(c, 8);
135
		for(i=0; i<NHASH; i++)
136
		for(s = hash[i]; s != S; s = s->link) {
137
			if(s->type != SSTRING)
138
				continue;
139
			v = s->value;
140
			while(v & 3)
141
				v++;
142
			s->value = c;
143
			c += v;
144
		}
145
	}
146
 
147
	c = rnd(c, 8);
148
 
149
	setext = lookup("etext", 0);
150
	if(setext != S) {
151
		setext->value = c;
152
		textsize = c - INITTEXT;
153
	}
154
	if(INITRND)
155
		INITDAT = rnd(c, INITRND);
156
	if(debug['v'])
157
		Bprint(&bso, "tsize = %llux\n", textsize);
158
	Bflush(&bso);
159
}
160
 
161
void
162
xdefine(char *p, int t, long v)
163
{
164
	Sym *s;
165
 
166
	s = lookup(p, 0);
167
	if(s->type == 0 || s->type == SXREF) {
168
		s->type = t;
169
		s->value = v;
170
	}
171
}
172
 
173
long
174
regoff(Adr *a)
175
{
176
 
177
	instoffset = 0;
178
	aclass(a);
179
	return instoffset;
180
}
181
 
182
aclass(Adr *a)
183
{
184
	Sym *s;
185
	int t;
186
 
187
	switch(a->type) {
188
	case D_NONE:
189
		return C_NONE;
190
 
191
	case D_REG:
192
		return C_REG;
193
 
194
	case D_FREG:
195
		return C_FREG;
196
 
197
	case D_FCREG:
198
		return C_FCREG;
199
 
200
	case D_MREG:
201
		return C_MREG;
202
 
203
	case D_OREG:
204
		switch(a->name) {
205
		case D_EXTERN:
206
		case D_STATIC:
207
			if(a->sym == 0 || a->sym->name == 0) {
208
				print("null sym external\n");
209
				print("%D\n", a);
210
				return C_GOK;
211
			}
212
			t = a->sym->type;
213
			if(t == 0 || t == SXREF) {
214
				diag("undefined external: %s in %s",
215
					a->sym->name, TNAME);
216
				a->sym->type = SDATA;
217
			}
218
			instoffset = a->sym->value + a->offset - BIG;
219
			if(instoffset >= -BIG && instoffset < BIG)
220
				return C_SEXT;
221
			return C_LEXT;
222
		case D_AUTO:
223
			instoffset = autosize + a->offset;
224
			if(instoffset >= -BIG && instoffset < BIG)
225
				return C_SAUTO;
226
			return C_LAUTO;
227
 
228
		case D_PARAM:
229
			instoffset = autosize + a->offset + 4L;
230
			if(instoffset >= -BIG && instoffset < BIG)
231
				return C_SAUTO;
232
			return C_LAUTO;
233
		case D_NONE:
234
			instoffset = a->offset;
235
			if(instoffset == 0)
236
				return C_ZOREG;
237
			if(instoffset >= -BIG && instoffset < BIG)
238
				return C_SOREG;
239
			return C_LOREG;
240
		}
241
		return C_GOK;
242
 
243
	case D_HI:
244
		return C_LO;
245
	case D_LO:
246
		return C_HI;
247
 
248
	case D_OCONST:
249
		switch(a->name) {
250
		case D_EXTERN:
251
		case D_STATIC:
252
			s = a->sym;
253
			t = s->type;
254
			if(t == 0 || t == SXREF) {
255
				diag("undefined external: %s in %s",
256
					s->name, TNAME);
257
				s->type = SDATA;
258
			}
259
			instoffset = s->value + a->offset + INITDAT;
260
			if(s->type == STEXT || s->type == SLEAF)
261
				instoffset = s->value + a->offset;
262
			return C_LCON;
263
		}
264
		return C_GOK;
265
 
266
	case D_CONST:
267
		switch(a->name) {
268
 
269
		case D_NONE:
270
			instoffset = a->offset;
271
		consize:
272
			if(instoffset > 0) {
273
				if(instoffset <= 0x7fff)
274
					return C_SCON;
275
				if(instoffset <= 0xffff)
276
					return C_ANDCON;
277
				if((instoffset & 0xffff) == 0)
278
					return C_UCON;
279
				return C_LCON;
280
			}
281
			if(instoffset == 0)
282
				return C_ZCON;
283
			if(instoffset >= -0x8000)
284
				return C_ADDCON;
285
			if((instoffset & 0xffff) == 0)
286
				return C_UCON;
287
			return C_LCON;
288
 
289
		case D_EXTERN:
290
		case D_STATIC:
291
			s = a->sym;
292
			if(s == S)
293
				break;
294
			t = s->type;
295
			switch(t) {
296
			case 0:
297
			case SXREF:
298
				diag("undefined external: %s in %s",
299
					s->name, TNAME);
300
				s->type = SDATA;
301
				break;
302
			case SCONST:
303
				instoffset = s->value + a->offset;
304
				goto consize;
305
			case STEXT:
306
			case SLEAF:
307
			case SSTRING:
308
				instoffset = s->value + a->offset;
309
				return C_LCON;
310
			}
311
			instoffset = s->value + a->offset - BIG;
312
			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
313
				return C_SECON;
314
			instoffset = s->value + a->offset + INITDAT;
315
			return C_LCON;
316
 
317
		case D_AUTO:
318
			instoffset = autosize + a->offset;
319
			if(instoffset >= -BIG && instoffset < BIG)
320
				return C_SACON;
321
			return C_LACON;
322
 
323
		case D_PARAM:
324
			instoffset = autosize + a->offset + 4L;
325
			if(instoffset >= -BIG && instoffset < BIG)
326
				return C_SACON;
327
			return C_LACON;
328
		}
329
		return C_GOK;
330
 
331
	case D_BRANCH:
332
		return C_SBRA;
333
	}
334
	return C_GOK;
335
}
336
 
337
Optab*
338
oplook(Prog *p)
339
{
340
	int a1, a2, a3, r;
341
	char *c1, *c3;
342
	Optab *o, *e;
343
 
344
	a1 = p->optab;
345
	if(a1)
346
		return optab+(a1-1);
347
	a1 = p->from.class;
348
	if(a1 == 0) {
349
		a1 = aclass(&p->from) + 1;
350
		p->from.class = a1;
351
	}
352
	a1--;
353
	a3 = p->to.class;
354
	if(a3 == 0) {
355
		a3 = aclass(&p->to) + 1;
356
		p->to.class = a3;
357
	}
358
	a3--;
359
	a2 = C_NONE;
360
	if(p->reg != NREG)
361
		a2 = C_REG;
362
	r = p->as;
363
	o = oprange[r].start;
364
	if(o == 0) {
365
		a1 = opcross[repop[r]][a1][a2][a3];
366
		if(a1) {
367
			p->optab = a1+1;
368
			return optab+a1;
369
		}
370
		o = oprange[r].stop; /* just generate an error */
371
	}
372
	e = oprange[r].stop;
373
	c1 = xcmp[a1];
374
	c3 = xcmp[a3];
375
	for(; o<e; o++)
376
		if(o->a2 == a2)
377
		if(c1[o->a1])
378
		if(c3[o->a3]) {
379
			p->optab = (o-optab)+1;
380
			return o;
381
		}
382
	diag("illegal combination %A %d %d %d",
383
		p->as, a1, a2, a3);
384
	if(!debug['a'])
385
		prasm(p);
386
	o = optab;
387
	p->optab = (o-optab)+1;
388
	return o;
389
}
390
 
391
int
392
cmp(int a, int b)
393
{
394
 
395
	if(a == b)
396
		return 1;
397
	switch(a) {
398
	case C_LCON:
399
		if(b == C_ZCON || b == C_SCON || b == C_UCON ||
400
		   b == C_ADDCON || b == C_ANDCON)
401
			return 1;
402
		break;
403
	case C_ADD0CON:
404
		if(b == C_ADDCON)
405
			return 1;
406
	case C_ADDCON:
407
		if(b == C_ZCON || b == C_SCON)
408
			return 1;
409
		break;
410
	case C_AND0CON:
411
		if(b == C_ANDCON)
412
			return 1;
413
	case C_ANDCON:
414
		if(b == C_ZCON || b == C_SCON)
415
			return 1;
416
		break;
417
	case C_UCON:
418
		if(b == C_ZCON)
419
			return 1;
420
		break;
421
	case C_SCON:
422
		if(b == C_ZCON)
423
			return 1;
424
		break;
425
	case C_LACON:
426
		if(b == C_SACON)
427
			return 1;
428
		break;
429
	case C_LBRA:
430
		if(b == C_SBRA)
431
			return 1;
432
		break;
433
	case C_LEXT:
434
		if(b == C_SEXT)
435
			return 1;
436
		break;
437
	case C_LAUTO:
438
		if(b == C_SAUTO)
439
			return 1;
440
		break;
441
	case C_REG:
442
		if(b == C_ZCON)
443
			return 1;
444
		break;
445
	case C_LOREG:
446
		if(b == C_ZOREG || b == C_SOREG)
447
			return 1;
448
		break;
449
	case C_SOREG:
450
		if(b == C_ZOREG)
451
			return 1;
452
		break;
453
	}
454
	return 0;
455
}
456
 
457
int
458
ocmp(const void *a1, const void *a2)
459
{
460
	Optab *p1, *p2;
461
	int n;
462
 
463
	p1 = (Optab*)a1;
464
	p2 = (Optab*)a2;
465
	n = p1->as - p2->as;
466
	if(n)
467
		return n;
468
	n = p1->a1 - p2->a1;
469
	if(n)
470
		return n;
471
	n = p1->a2 - p2->a2;
472
	if(n)
473
		return n;
474
	n = p1->a3 - p2->a3;
475
	if(n)
476
		return n;
477
	return 0;
478
}
479
 
480
void
481
buildop(void)
482
{
483
	int i, n, r;
484
 
485
	for(i=0; i<32; i++)
486
		for(n=0; n<32; n++)
487
			xcmp[i][n] = cmp(n, i);
488
	for(n=0; optab[n].as != AXXX; n++)
489
		;
490
	qsort(optab, n, sizeof(optab[0]), ocmp);
491
	for(i=0; i<n; i++) {
492
		r = optab[i].as;
493
		oprange[r].start = optab+i;
494
		while(optab[i].as == r)
495
			i++;
496
		oprange[r].stop = optab+i;
497
		i--;
498
 
499
		switch(r)
500
		{
501
		default:
502
			diag("unknown op in build: %A", r);
503
			errorexit();
504
		case AABSF:
505
			oprange[AMOVFD] = oprange[r];
506
			oprange[AMOVDF] = oprange[r];
507
			oprange[AMOVWF] = oprange[r];
508
			oprange[AMOVFW] = oprange[r];
509
			oprange[AMOVWD] = oprange[r];
510
			oprange[AMOVDW] = oprange[r];
511
			oprange[ANEGF] = oprange[r];
512
			oprange[ANEGD] = oprange[r];
513
			oprange[AABSD] = oprange[r];
514
			break;
515
		case AADD:
516
			buildrep(1, AADD);
517
			oprange[ASGT] = oprange[r];
518
			repop[ASGT] = 1;
519
			oprange[ASGTU] = oprange[r];
520
			repop[ASGTU] = 1;
521
			oprange[AADDU] = oprange[r];
522
			repop[AADDU] = 1;
523
			oprange[AADDVU] = oprange[r];
524
			repop[AADDVU] = 1;
525
			break;
526
		case AADDF:
527
			oprange[ADIVF] = oprange[r];
528
			oprange[ADIVD] = oprange[r];
529
			oprange[AMULF] = oprange[r];
530
			oprange[AMULD] = oprange[r];
531
			oprange[ASUBF] = oprange[r];
532
			oprange[ASUBD] = oprange[r];
533
			oprange[AADDD] = oprange[r];
534
			break;
535
		case AAND:
536
			buildrep(2, AAND);
537
			oprange[AXOR] = oprange[r];
538
			repop[AXOR] = 2;
539
			oprange[AOR] = oprange[r];
540
			repop[AOR] = 2;
541
			break;
542
		case ABEQ:
543
			oprange[ABNE] = oprange[r];
544
			break;
545
		case ABLEZ:
546
			oprange[ABGEZ] = oprange[r];
547
			oprange[ABGEZAL] = oprange[r];
548
			oprange[ABLTZ] = oprange[r];
549
			oprange[ABLTZAL] = oprange[r];
550
			oprange[ABGTZ] = oprange[r];
551
			break;
552
		case AMOVB:
553
			buildrep(3, AMOVB);
554
			oprange[AMOVH] = oprange[r];
555
			repop[AMOVH] = 3;
556
			break;
557
		case AMOVBU:
558
			buildrep(4, AMOVBU);
559
			oprange[AMOVHU] = oprange[r];
560
			repop[AMOVHU] = 4;
561
			break;
562
		case AMUL:
563
			oprange[AREM] = oprange[r];
564
			oprange[AREMU] = oprange[r];
565
			oprange[ADIVU] = oprange[r];
566
			oprange[AMULU] = oprange[r];
567
			oprange[ADIV] = oprange[r];
568
			oprange[ADIVVU] = oprange[r];
569
			oprange[ADIVV] = oprange[r];
570
			break;
571
		case ASLL:
572
			oprange[ASRL] = oprange[r];
573
			oprange[ASRA] = oprange[r];
574
			oprange[ASLLV] = oprange[r];
575
			oprange[ASRAV] = oprange[r];
576
			oprange[ASRLV] = oprange[r];
577
			break;
578
		case ASUB:
579
			oprange[ASUBU] = oprange[r];
580
			oprange[ANOR] = oprange[r];
581
			break;
582
		case ASYSCALL:
583
			oprange[ATLBP] = oprange[r];
584
			oprange[ATLBR] = oprange[r];
585
			oprange[ATLBWI] = oprange[r];
586
			oprange[ATLBWR] = oprange[r];
587
			break;
588
		case ACMPEQF:
589
			oprange[ACMPGTF] = oprange[r];
590
			oprange[ACMPGTD] = oprange[r];
591
			oprange[ACMPGEF] = oprange[r];
592
			oprange[ACMPGED] = oprange[r];
593
			oprange[ACMPEQD] = oprange[r];
594
			break;
595
		case ABFPT:
596
			oprange[ABFPF] = oprange[r];
597
			break;
598
		case AMOVWL:
599
			oprange[AMOVWR] = oprange[r];
600
			oprange[AMOVVR] = oprange[r];
601
			oprange[AMOVVL] = oprange[r];
602
			break;
603
		case AMOVW:
604
			buildrep(5, AMOVW);
605
			break;
606
		case AMOVD:
607
			buildrep(6, AMOVD);
608
			break;
609
		case AMOVF:
610
			buildrep(7, AMOVF);
611
			break;
612
		case AMOVV:
613
			buildrep(8, AMOVV);
614
			break;
615
		case ABREAK:
616
		case AWORD:
617
		case ARFE:
618
		case AJAL:
619
		case AJMP:
620
		case ATEXT:
621
		case ACASE:
622
		case ABCASE:
623
			break;
624
		}
625
	}
626
}
627
 
628
void
629
buildrep(int x, int as)
630
{
631
	Opcross *p;
632
	Optab *e, *s, *o;
633
	int a1, a2, a3, n;
634
 
635
	if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
636
		diag("assumptions fail in buildrep");
637
		errorexit();
638
	}
639
	repop[as] = x;
640
	p = (opcross + x);
641
	s = oprange[as].start;
642
	e = oprange[as].stop;
643
	for(o=e-1; o>=s; o--) {
644
		n = o-optab;
645
		for(a2=0; a2<2; a2++) {
646
			if(a2) {
647
				if(o->a2 == C_NONE)
648
					continue;
649
			} else
650
				if(o->a2 != C_NONE)
651
					continue;
652
			for(a1=0; a1<32; a1++) {
653
				if(!xcmp[a1][o->a1])
654
					continue;
655
				for(a3=0; a3<32; a3++)
656
					if(xcmp[a3][o->a3])
657
						(*p)[a1][a2][a3] = n;
658
			}
659
		}
660
	}
661
	oprange[as].start = 0;
662
}