174a4d8c2SCharles.Forsyth #include "l.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth void
pagebug(Prog * p)474a4d8c2SCharles.Forsyth pagebug(Prog *p)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth Prog *q;
774a4d8c2SCharles.Forsyth
874a4d8c2SCharles.Forsyth switch(p->as) {
974a4d8c2SCharles.Forsyth case ABGEZAL:
1074a4d8c2SCharles.Forsyth case ABLTZAL:
1174a4d8c2SCharles.Forsyth case AJAL:
1274a4d8c2SCharles.Forsyth case ABEQ:
1374a4d8c2SCharles.Forsyth case ABGEZ:
1474a4d8c2SCharles.Forsyth case ABGTZ:
1574a4d8c2SCharles.Forsyth case ABLEZ:
1674a4d8c2SCharles.Forsyth case ABLTZ:
1774a4d8c2SCharles.Forsyth case ABNE:
1874a4d8c2SCharles.Forsyth case ABFPT:
1974a4d8c2SCharles.Forsyth case ABFPF:
2074a4d8c2SCharles.Forsyth case AJMP:
2174a4d8c2SCharles.Forsyth q = prg();
2274a4d8c2SCharles.Forsyth *q = *p;
2374a4d8c2SCharles.Forsyth p->link = q;
2474a4d8c2SCharles.Forsyth p->as = ANOR;
2574a4d8c2SCharles.Forsyth p->optab = 0;
2674a4d8c2SCharles.Forsyth p->from = zprg.from;
2774a4d8c2SCharles.Forsyth p->from.type = D_REG;
2874a4d8c2SCharles.Forsyth p->from.reg = REGZERO;
2974a4d8c2SCharles.Forsyth p->to = p->from;
3074a4d8c2SCharles.Forsyth }
3174a4d8c2SCharles.Forsyth }
3274a4d8c2SCharles.Forsyth
3374a4d8c2SCharles.Forsyth void
span(void)3474a4d8c2SCharles.Forsyth span(void)
3574a4d8c2SCharles.Forsyth {
3674a4d8c2SCharles.Forsyth Prog *p, *q;
3774a4d8c2SCharles.Forsyth Sym *setext, *s;
3874a4d8c2SCharles.Forsyth Optab *o;
3974a4d8c2SCharles.Forsyth int m, bflag, i;
4074a4d8c2SCharles.Forsyth long c, otxt, v;
4174a4d8c2SCharles.Forsyth
4274a4d8c2SCharles.Forsyth if(debug['v'])
4374a4d8c2SCharles.Forsyth Bprint(&bso, "%5.2f span\n", cputime());
4474a4d8c2SCharles.Forsyth Bflush(&bso);
4574a4d8c2SCharles.Forsyth
4674a4d8c2SCharles.Forsyth bflag = 0;
4774a4d8c2SCharles.Forsyth c = INITTEXT;
4874a4d8c2SCharles.Forsyth otxt = c;
4974a4d8c2SCharles.Forsyth for(p = firstp; p != P; p = p->link) {
5074a4d8c2SCharles.Forsyth /* bug in early 4000 chips delayslot on page boundary */
5174a4d8c2SCharles.Forsyth if((c&(0x1000-1)) == 0xffc)
5274a4d8c2SCharles.Forsyth pagebug(p);
5374a4d8c2SCharles.Forsyth p->pc = c;
5474a4d8c2SCharles.Forsyth o = oplook(p);
5574a4d8c2SCharles.Forsyth m = o->size;
5674a4d8c2SCharles.Forsyth if(m == 0) {
5774a4d8c2SCharles.Forsyth if(p->as == ATEXT) {
5874a4d8c2SCharles.Forsyth curtext = p;
5974a4d8c2SCharles.Forsyth autosize = p->to.offset + 4;
6074a4d8c2SCharles.Forsyth if(p->from.sym != S)
6174a4d8c2SCharles.Forsyth p->from.sym->value = c;
6274a4d8c2SCharles.Forsyth /* need passes to resolve branches */
6374a4d8c2SCharles.Forsyth if(c-otxt >= 1L<<17)
6474a4d8c2SCharles.Forsyth bflag = 1;
6574a4d8c2SCharles.Forsyth otxt = c;
6674a4d8c2SCharles.Forsyth continue;
6774a4d8c2SCharles.Forsyth }
6874a4d8c2SCharles.Forsyth diag("zero-width instruction\n%P", p);
6974a4d8c2SCharles.Forsyth continue;
7074a4d8c2SCharles.Forsyth }
7174a4d8c2SCharles.Forsyth c += m;
7274a4d8c2SCharles.Forsyth }
7374a4d8c2SCharles.Forsyth
7474a4d8c2SCharles.Forsyth /*
7574a4d8c2SCharles.Forsyth * if any procedure is large enough to
7674a4d8c2SCharles.Forsyth * generate a large SBRA branch, then
7774a4d8c2SCharles.Forsyth * generate extra passes putting branches
7874a4d8c2SCharles.Forsyth * around jmps to fix. this is rare.
7974a4d8c2SCharles.Forsyth */
8074a4d8c2SCharles.Forsyth while(bflag) {
8174a4d8c2SCharles.Forsyth if(debug['v'])
8274a4d8c2SCharles.Forsyth Bprint(&bso, "%5.2f span1\n", cputime());
8374a4d8c2SCharles.Forsyth bflag = 0;
8474a4d8c2SCharles.Forsyth c = INITTEXT;
8574a4d8c2SCharles.Forsyth for(p = firstp; p != P; p = p->link) {
8674a4d8c2SCharles.Forsyth /* bug in early 4000 chips delayslot on page boundary */
8774a4d8c2SCharles.Forsyth if((c&(0x1000-1)) == 0xffc)
8874a4d8c2SCharles.Forsyth pagebug(p);
8974a4d8c2SCharles.Forsyth p->pc = c;
9074a4d8c2SCharles.Forsyth o = oplook(p);
9174a4d8c2SCharles.Forsyth if(o->type == 6 && p->cond) {
9274a4d8c2SCharles.Forsyth otxt = p->cond->pc - c;
9374a4d8c2SCharles.Forsyth if(otxt < 0)
9474a4d8c2SCharles.Forsyth otxt = -otxt;
9574a4d8c2SCharles.Forsyth if(otxt >= (1L<<17) - 10) {
9674a4d8c2SCharles.Forsyth q = prg();
9774a4d8c2SCharles.Forsyth q->link = p->link;
9874a4d8c2SCharles.Forsyth p->link = q;
9974a4d8c2SCharles.Forsyth q->as = AJMP;
10074a4d8c2SCharles.Forsyth q->to.type = D_BRANCH;
10174a4d8c2SCharles.Forsyth q->cond = p->cond;
10274a4d8c2SCharles.Forsyth p->cond = q;
10374a4d8c2SCharles.Forsyth q = prg();
10474a4d8c2SCharles.Forsyth q->link = p->link;
10574a4d8c2SCharles.Forsyth p->link = q;
10674a4d8c2SCharles.Forsyth q->as = AJMP;
10774a4d8c2SCharles.Forsyth q->to.type = D_BRANCH;
10874a4d8c2SCharles.Forsyth q->cond = q->link->link;
10974a4d8c2SCharles.Forsyth addnop(p->link);
11074a4d8c2SCharles.Forsyth addnop(p);
11174a4d8c2SCharles.Forsyth bflag = 1;
11274a4d8c2SCharles.Forsyth }
11374a4d8c2SCharles.Forsyth }
11474a4d8c2SCharles.Forsyth m = o->size;
11574a4d8c2SCharles.Forsyth if(m == 0) {
11674a4d8c2SCharles.Forsyth if(p->as == ATEXT) {
11774a4d8c2SCharles.Forsyth curtext = p;
11874a4d8c2SCharles.Forsyth autosize = p->to.offset + 4;
11974a4d8c2SCharles.Forsyth if(p->from.sym != S)
12074a4d8c2SCharles.Forsyth p->from.sym->value = c;
12174a4d8c2SCharles.Forsyth continue;
12274a4d8c2SCharles.Forsyth }
12374a4d8c2SCharles.Forsyth diag("zero-width instruction\n%P", p);
12474a4d8c2SCharles.Forsyth continue;
12574a4d8c2SCharles.Forsyth }
12674a4d8c2SCharles.Forsyth c += m;
12774a4d8c2SCharles.Forsyth }
12874a4d8c2SCharles.Forsyth }
12974a4d8c2SCharles.Forsyth
13074a4d8c2SCharles.Forsyth if(debug['t']) {
13174a4d8c2SCharles.Forsyth /*
13274a4d8c2SCharles.Forsyth * add strings to text segment
13374a4d8c2SCharles.Forsyth */
13474a4d8c2SCharles.Forsyth c = rnd(c, 8);
13574a4d8c2SCharles.Forsyth for(i=0; i<NHASH; i++)
13674a4d8c2SCharles.Forsyth for(s = hash[i]; s != S; s = s->link) {
13774a4d8c2SCharles.Forsyth if(s->type != SSTRING)
13874a4d8c2SCharles.Forsyth continue;
13974a4d8c2SCharles.Forsyth v = s->value;
14074a4d8c2SCharles.Forsyth while(v & 3)
14174a4d8c2SCharles.Forsyth v++;
14274a4d8c2SCharles.Forsyth s->value = c;
14374a4d8c2SCharles.Forsyth c += v;
14474a4d8c2SCharles.Forsyth }
14574a4d8c2SCharles.Forsyth }
14674a4d8c2SCharles.Forsyth
14774a4d8c2SCharles.Forsyth c = rnd(c, 8);
14874a4d8c2SCharles.Forsyth
14974a4d8c2SCharles.Forsyth setext = lookup("etext", 0);
15074a4d8c2SCharles.Forsyth if(setext != S) {
15174a4d8c2SCharles.Forsyth setext->value = c;
15274a4d8c2SCharles.Forsyth textsize = c - INITTEXT;
15374a4d8c2SCharles.Forsyth }
15474a4d8c2SCharles.Forsyth if(INITRND)
15574a4d8c2SCharles.Forsyth INITDAT = rnd(c, INITRND);
15674a4d8c2SCharles.Forsyth if(debug['v'])
15774a4d8c2SCharles.Forsyth Bprint(&bso, "tsize = %lux\n", textsize);
15874a4d8c2SCharles.Forsyth Bflush(&bso);
15974a4d8c2SCharles.Forsyth }
16074a4d8c2SCharles.Forsyth
16174a4d8c2SCharles.Forsyth void
xdefine(char * p,int t,long v)16274a4d8c2SCharles.Forsyth xdefine(char *p, int t, long v)
16374a4d8c2SCharles.Forsyth {
16474a4d8c2SCharles.Forsyth Sym *s;
16574a4d8c2SCharles.Forsyth
16674a4d8c2SCharles.Forsyth s = lookup(p, 0);
16774a4d8c2SCharles.Forsyth if(s->type == 0 || s->type == SXREF) {
16874a4d8c2SCharles.Forsyth s->type = t;
16974a4d8c2SCharles.Forsyth s->value = v;
17074a4d8c2SCharles.Forsyth }
17174a4d8c2SCharles.Forsyth }
17274a4d8c2SCharles.Forsyth
17374a4d8c2SCharles.Forsyth long
regoff(Adr * a)17474a4d8c2SCharles.Forsyth regoff(Adr *a)
17574a4d8c2SCharles.Forsyth {
17674a4d8c2SCharles.Forsyth
17774a4d8c2SCharles.Forsyth instoffset = 0;
17874a4d8c2SCharles.Forsyth aclass(a);
17974a4d8c2SCharles.Forsyth return instoffset;
18074a4d8c2SCharles.Forsyth }
18174a4d8c2SCharles.Forsyth
1826e425a9dSCharles.Forsyth int
aclass(Adr * a)18374a4d8c2SCharles.Forsyth aclass(Adr *a)
18474a4d8c2SCharles.Forsyth {
18574a4d8c2SCharles.Forsyth Sym *s;
18674a4d8c2SCharles.Forsyth int t;
18774a4d8c2SCharles.Forsyth
18874a4d8c2SCharles.Forsyth switch(a->type) {
18974a4d8c2SCharles.Forsyth case D_NONE:
19074a4d8c2SCharles.Forsyth return C_NONE;
19174a4d8c2SCharles.Forsyth
19274a4d8c2SCharles.Forsyth case D_REG:
19374a4d8c2SCharles.Forsyth return C_REG;
19474a4d8c2SCharles.Forsyth
19574a4d8c2SCharles.Forsyth case D_FREG:
19674a4d8c2SCharles.Forsyth return C_FREG;
19774a4d8c2SCharles.Forsyth
19874a4d8c2SCharles.Forsyth case D_FCREG:
19974a4d8c2SCharles.Forsyth return C_FCREG;
20074a4d8c2SCharles.Forsyth
20174a4d8c2SCharles.Forsyth case D_MREG:
20274a4d8c2SCharles.Forsyth return C_MREG;
20374a4d8c2SCharles.Forsyth
20474a4d8c2SCharles.Forsyth case D_OREG:
20574a4d8c2SCharles.Forsyth switch(a->name) {
20674a4d8c2SCharles.Forsyth case D_EXTERN:
20774a4d8c2SCharles.Forsyth case D_STATIC:
20874a4d8c2SCharles.Forsyth if(a->sym == 0 || a->sym->name == 0) {
20974a4d8c2SCharles.Forsyth print("null sym external\n");
21074a4d8c2SCharles.Forsyth print("%D\n", a);
21174a4d8c2SCharles.Forsyth return C_GOK;
21274a4d8c2SCharles.Forsyth }
21374a4d8c2SCharles.Forsyth t = a->sym->type;
21474a4d8c2SCharles.Forsyth if(t == 0 || t == SXREF) {
21574a4d8c2SCharles.Forsyth diag("undefined external: %s in %s",
21674a4d8c2SCharles.Forsyth a->sym->name, TNAME);
21774a4d8c2SCharles.Forsyth a->sym->type = SDATA;
21874a4d8c2SCharles.Forsyth }
21974a4d8c2SCharles.Forsyth instoffset = a->sym->value + a->offset - BIG;
22074a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
22174a4d8c2SCharles.Forsyth return C_SEXT;
22274a4d8c2SCharles.Forsyth return C_LEXT;
22374a4d8c2SCharles.Forsyth case D_AUTO:
22474a4d8c2SCharles.Forsyth instoffset = autosize + a->offset;
22574a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
22674a4d8c2SCharles.Forsyth return C_SAUTO;
22774a4d8c2SCharles.Forsyth return C_LAUTO;
22874a4d8c2SCharles.Forsyth
22974a4d8c2SCharles.Forsyth case D_PARAM:
23074a4d8c2SCharles.Forsyth instoffset = autosize + a->offset + 4L;
23174a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
23274a4d8c2SCharles.Forsyth return C_SAUTO;
23374a4d8c2SCharles.Forsyth return C_LAUTO;
23474a4d8c2SCharles.Forsyth case D_NONE:
23574a4d8c2SCharles.Forsyth instoffset = a->offset;
23674a4d8c2SCharles.Forsyth if(instoffset == 0)
23774a4d8c2SCharles.Forsyth return C_ZOREG;
23874a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
23974a4d8c2SCharles.Forsyth return C_SOREG;
24074a4d8c2SCharles.Forsyth return C_LOREG;
24174a4d8c2SCharles.Forsyth }
24274a4d8c2SCharles.Forsyth return C_GOK;
24374a4d8c2SCharles.Forsyth
24474a4d8c2SCharles.Forsyth case D_HI:
24574a4d8c2SCharles.Forsyth return C_LO;
24674a4d8c2SCharles.Forsyth case D_LO:
24774a4d8c2SCharles.Forsyth return C_HI;
24874a4d8c2SCharles.Forsyth
24974a4d8c2SCharles.Forsyth case D_OCONST:
25074a4d8c2SCharles.Forsyth switch(a->name) {
25174a4d8c2SCharles.Forsyth case D_EXTERN:
25274a4d8c2SCharles.Forsyth case D_STATIC:
25374a4d8c2SCharles.Forsyth s = a->sym;
25474a4d8c2SCharles.Forsyth t = s->type;
25574a4d8c2SCharles.Forsyth if(t == 0 || t == SXREF) {
25674a4d8c2SCharles.Forsyth diag("undefined external: %s in %s",
25774a4d8c2SCharles.Forsyth s->name, TNAME);
25874a4d8c2SCharles.Forsyth s->type = SDATA;
25974a4d8c2SCharles.Forsyth }
26074a4d8c2SCharles.Forsyth instoffset = s->value + a->offset + INITDAT;
26174a4d8c2SCharles.Forsyth if(s->type == STEXT || s->type == SLEAF)
26274a4d8c2SCharles.Forsyth instoffset = s->value + a->offset;
26374a4d8c2SCharles.Forsyth return C_LCON;
26474a4d8c2SCharles.Forsyth }
26574a4d8c2SCharles.Forsyth return C_GOK;
26674a4d8c2SCharles.Forsyth
26774a4d8c2SCharles.Forsyth case D_CONST:
26874a4d8c2SCharles.Forsyth switch(a->name) {
26974a4d8c2SCharles.Forsyth
27074a4d8c2SCharles.Forsyth case D_NONE:
27174a4d8c2SCharles.Forsyth instoffset = a->offset;
27274a4d8c2SCharles.Forsyth consize:
27374a4d8c2SCharles.Forsyth if(instoffset > 0) {
27474a4d8c2SCharles.Forsyth if(instoffset <= 0x7fff)
27574a4d8c2SCharles.Forsyth return C_SCON;
27674a4d8c2SCharles.Forsyth if(instoffset <= 0xffff)
27774a4d8c2SCharles.Forsyth return C_ANDCON;
27874a4d8c2SCharles.Forsyth if((instoffset & 0xffff) == 0)
27974a4d8c2SCharles.Forsyth return C_UCON;
28074a4d8c2SCharles.Forsyth return C_LCON;
28174a4d8c2SCharles.Forsyth }
28274a4d8c2SCharles.Forsyth if(instoffset == 0)
28374a4d8c2SCharles.Forsyth return C_ZCON;
28474a4d8c2SCharles.Forsyth if(instoffset >= -0x8000)
28574a4d8c2SCharles.Forsyth return C_ADDCON;
28674a4d8c2SCharles.Forsyth if((instoffset & 0xffff) == 0)
28774a4d8c2SCharles.Forsyth return C_UCON;
28874a4d8c2SCharles.Forsyth return C_LCON;
28974a4d8c2SCharles.Forsyth
29074a4d8c2SCharles.Forsyth case D_EXTERN:
29174a4d8c2SCharles.Forsyth case D_STATIC:
29274a4d8c2SCharles.Forsyth s = a->sym;
29374a4d8c2SCharles.Forsyth if(s == S)
29474a4d8c2SCharles.Forsyth break;
29574a4d8c2SCharles.Forsyth t = s->type;
29674a4d8c2SCharles.Forsyth switch(t) {
29774a4d8c2SCharles.Forsyth case 0:
29874a4d8c2SCharles.Forsyth case SXREF:
29974a4d8c2SCharles.Forsyth diag("undefined external: %s in %s",
30074a4d8c2SCharles.Forsyth s->name, TNAME);
30174a4d8c2SCharles.Forsyth s->type = SDATA;
30274a4d8c2SCharles.Forsyth break;
30374a4d8c2SCharles.Forsyth case SCONST:
30474a4d8c2SCharles.Forsyth instoffset = s->value + a->offset;
30574a4d8c2SCharles.Forsyth goto consize;
30674a4d8c2SCharles.Forsyth case STEXT:
30774a4d8c2SCharles.Forsyth case SLEAF:
30874a4d8c2SCharles.Forsyth case SSTRING:
30974a4d8c2SCharles.Forsyth instoffset = s->value + a->offset;
31074a4d8c2SCharles.Forsyth return C_LCON;
31174a4d8c2SCharles.Forsyth }
31274a4d8c2SCharles.Forsyth instoffset = s->value + a->offset - BIG;
31374a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
31474a4d8c2SCharles.Forsyth return C_SECON;
31574a4d8c2SCharles.Forsyth instoffset = s->value + a->offset + INITDAT;
31674a4d8c2SCharles.Forsyth return C_LCON;
31774a4d8c2SCharles.Forsyth
31874a4d8c2SCharles.Forsyth case D_AUTO:
31974a4d8c2SCharles.Forsyth instoffset = autosize + a->offset;
32074a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
32174a4d8c2SCharles.Forsyth return C_SACON;
32274a4d8c2SCharles.Forsyth return C_LACON;
32374a4d8c2SCharles.Forsyth
32474a4d8c2SCharles.Forsyth case D_PARAM:
32574a4d8c2SCharles.Forsyth instoffset = autosize + a->offset + 4L;
32674a4d8c2SCharles.Forsyth if(instoffset >= -BIG && instoffset < BIG)
32774a4d8c2SCharles.Forsyth return C_SACON;
32874a4d8c2SCharles.Forsyth return C_LACON;
32974a4d8c2SCharles.Forsyth }
33074a4d8c2SCharles.Forsyth return C_GOK;
33174a4d8c2SCharles.Forsyth
33274a4d8c2SCharles.Forsyth case D_BRANCH:
33374a4d8c2SCharles.Forsyth return C_SBRA;
33474a4d8c2SCharles.Forsyth }
33574a4d8c2SCharles.Forsyth return C_GOK;
33674a4d8c2SCharles.Forsyth }
33774a4d8c2SCharles.Forsyth
33874a4d8c2SCharles.Forsyth Optab*
oplook(Prog * p)33974a4d8c2SCharles.Forsyth oplook(Prog *p)
34074a4d8c2SCharles.Forsyth {
34174a4d8c2SCharles.Forsyth int a1, a2, a3, r;
34274a4d8c2SCharles.Forsyth char *c1, *c3;
34374a4d8c2SCharles.Forsyth Optab *o, *e;
34474a4d8c2SCharles.Forsyth
34574a4d8c2SCharles.Forsyth a1 = p->optab;
34674a4d8c2SCharles.Forsyth if(a1)
34774a4d8c2SCharles.Forsyth return optab+(a1-1);
34874a4d8c2SCharles.Forsyth a1 = p->from.class;
34974a4d8c2SCharles.Forsyth if(a1 == 0) {
35074a4d8c2SCharles.Forsyth a1 = aclass(&p->from) + 1;
35174a4d8c2SCharles.Forsyth p->from.class = a1;
35274a4d8c2SCharles.Forsyth }
35374a4d8c2SCharles.Forsyth a1--;
35474a4d8c2SCharles.Forsyth a3 = p->to.class;
35574a4d8c2SCharles.Forsyth if(a3 == 0) {
35674a4d8c2SCharles.Forsyth a3 = aclass(&p->to) + 1;
35774a4d8c2SCharles.Forsyth p->to.class = a3;
35874a4d8c2SCharles.Forsyth }
35974a4d8c2SCharles.Forsyth a3--;
36074a4d8c2SCharles.Forsyth a2 = C_NONE;
36174a4d8c2SCharles.Forsyth if(p->reg != NREG)
36274a4d8c2SCharles.Forsyth a2 = C_REG;
36374a4d8c2SCharles.Forsyth r = p->as;
36474a4d8c2SCharles.Forsyth o = oprange[r].start;
36574a4d8c2SCharles.Forsyth if(o == 0) {
36674a4d8c2SCharles.Forsyth a1 = opcross[repop[r]][a1][a2][a3];
36774a4d8c2SCharles.Forsyth if(a1) {
36874a4d8c2SCharles.Forsyth p->optab = a1+1;
36974a4d8c2SCharles.Forsyth return optab+a1;
37074a4d8c2SCharles.Forsyth }
37174a4d8c2SCharles.Forsyth o = oprange[r].stop; /* just generate an error */
37274a4d8c2SCharles.Forsyth }
37374a4d8c2SCharles.Forsyth e = oprange[r].stop;
37474a4d8c2SCharles.Forsyth c1 = xcmp[a1];
37574a4d8c2SCharles.Forsyth c3 = xcmp[a3];
37674a4d8c2SCharles.Forsyth for(; o<e; o++)
37774a4d8c2SCharles.Forsyth if(o->a2 == a2)
37874a4d8c2SCharles.Forsyth if(c1[o->a1])
37974a4d8c2SCharles.Forsyth if(c3[o->a3]) {
38074a4d8c2SCharles.Forsyth p->optab = (o-optab)+1;
38174a4d8c2SCharles.Forsyth return o;
38274a4d8c2SCharles.Forsyth }
38374a4d8c2SCharles.Forsyth diag("illegal combination %A %d %d %d",
38474a4d8c2SCharles.Forsyth p->as, a1, a2, a3);
38574a4d8c2SCharles.Forsyth if(!debug['a'])
38674a4d8c2SCharles.Forsyth prasm(p);
38774a4d8c2SCharles.Forsyth o = optab;
38874a4d8c2SCharles.Forsyth p->optab = (o-optab)+1;
38974a4d8c2SCharles.Forsyth return o;
39074a4d8c2SCharles.Forsyth }
39174a4d8c2SCharles.Forsyth
39274a4d8c2SCharles.Forsyth int
cmp(int a,int b)39374a4d8c2SCharles.Forsyth cmp(int a, int b)
39474a4d8c2SCharles.Forsyth {
39574a4d8c2SCharles.Forsyth
39674a4d8c2SCharles.Forsyth if(a == b)
39774a4d8c2SCharles.Forsyth return 1;
39874a4d8c2SCharles.Forsyth switch(a) {
39974a4d8c2SCharles.Forsyth case C_LCON:
40074a4d8c2SCharles.Forsyth if(b == C_ZCON || b == C_SCON || b == C_UCON ||
40174a4d8c2SCharles.Forsyth b == C_ADDCON || b == C_ANDCON)
40274a4d8c2SCharles.Forsyth return 1;
40374a4d8c2SCharles.Forsyth break;
40474a4d8c2SCharles.Forsyth case C_ADD0CON:
40574a4d8c2SCharles.Forsyth if(b == C_ADDCON)
40674a4d8c2SCharles.Forsyth return 1;
40774a4d8c2SCharles.Forsyth case C_ADDCON:
40874a4d8c2SCharles.Forsyth if(b == C_ZCON || b == C_SCON)
40974a4d8c2SCharles.Forsyth return 1;
41074a4d8c2SCharles.Forsyth break;
41174a4d8c2SCharles.Forsyth case C_AND0CON:
41274a4d8c2SCharles.Forsyth if(b == C_ANDCON)
41374a4d8c2SCharles.Forsyth return 1;
41474a4d8c2SCharles.Forsyth case C_ANDCON:
41574a4d8c2SCharles.Forsyth if(b == C_ZCON || b == C_SCON)
41674a4d8c2SCharles.Forsyth return 1;
41774a4d8c2SCharles.Forsyth break;
41874a4d8c2SCharles.Forsyth case C_UCON:
41974a4d8c2SCharles.Forsyth if(b == C_ZCON)
42074a4d8c2SCharles.Forsyth return 1;
42174a4d8c2SCharles.Forsyth break;
42274a4d8c2SCharles.Forsyth case C_SCON:
42374a4d8c2SCharles.Forsyth if(b == C_ZCON)
42474a4d8c2SCharles.Forsyth return 1;
42574a4d8c2SCharles.Forsyth break;
42674a4d8c2SCharles.Forsyth case C_LACON:
42774a4d8c2SCharles.Forsyth if(b == C_SACON)
42874a4d8c2SCharles.Forsyth return 1;
42974a4d8c2SCharles.Forsyth break;
43074a4d8c2SCharles.Forsyth case C_LBRA:
43174a4d8c2SCharles.Forsyth if(b == C_SBRA)
43274a4d8c2SCharles.Forsyth return 1;
43374a4d8c2SCharles.Forsyth break;
43474a4d8c2SCharles.Forsyth case C_LEXT:
43574a4d8c2SCharles.Forsyth if(b == C_SEXT)
43674a4d8c2SCharles.Forsyth return 1;
43774a4d8c2SCharles.Forsyth break;
43874a4d8c2SCharles.Forsyth case C_LAUTO:
43974a4d8c2SCharles.Forsyth if(b == C_SAUTO)
44074a4d8c2SCharles.Forsyth return 1;
44174a4d8c2SCharles.Forsyth break;
44274a4d8c2SCharles.Forsyth case C_REG:
44374a4d8c2SCharles.Forsyth if(b == C_ZCON)
44474a4d8c2SCharles.Forsyth return 1;
44574a4d8c2SCharles.Forsyth break;
44674a4d8c2SCharles.Forsyth case C_LOREG:
44774a4d8c2SCharles.Forsyth if(b == C_ZOREG || b == C_SOREG)
44874a4d8c2SCharles.Forsyth return 1;
44974a4d8c2SCharles.Forsyth break;
45074a4d8c2SCharles.Forsyth case C_SOREG:
45174a4d8c2SCharles.Forsyth if(b == C_ZOREG)
45274a4d8c2SCharles.Forsyth return 1;
45374a4d8c2SCharles.Forsyth break;
45474a4d8c2SCharles.Forsyth }
45574a4d8c2SCharles.Forsyth return 0;
45674a4d8c2SCharles.Forsyth }
45774a4d8c2SCharles.Forsyth
45874a4d8c2SCharles.Forsyth int
ocmp(void * a1,void * a2)459*45a20ab7Sforsyth ocmp(void *a1, void *a2)
46074a4d8c2SCharles.Forsyth {
46174a4d8c2SCharles.Forsyth Optab *p1, *p2;
46274a4d8c2SCharles.Forsyth int n;
46374a4d8c2SCharles.Forsyth
46474a4d8c2SCharles.Forsyth p1 = (Optab*)a1;
46574a4d8c2SCharles.Forsyth p2 = (Optab*)a2;
46674a4d8c2SCharles.Forsyth n = p1->as - p2->as;
46774a4d8c2SCharles.Forsyth if(n)
46874a4d8c2SCharles.Forsyth return n;
46974a4d8c2SCharles.Forsyth n = p1->a1 - p2->a1;
47074a4d8c2SCharles.Forsyth if(n)
47174a4d8c2SCharles.Forsyth return n;
47274a4d8c2SCharles.Forsyth n = p1->a2 - p2->a2;
47374a4d8c2SCharles.Forsyth if(n)
47474a4d8c2SCharles.Forsyth return n;
47574a4d8c2SCharles.Forsyth n = p1->a3 - p2->a3;
47674a4d8c2SCharles.Forsyth if(n)
47774a4d8c2SCharles.Forsyth return n;
47874a4d8c2SCharles.Forsyth return 0;
47974a4d8c2SCharles.Forsyth }
48074a4d8c2SCharles.Forsyth
48174a4d8c2SCharles.Forsyth void
buildop(void)48274a4d8c2SCharles.Forsyth buildop(void)
48374a4d8c2SCharles.Forsyth {
48474a4d8c2SCharles.Forsyth int i, n, r;
48574a4d8c2SCharles.Forsyth
48674a4d8c2SCharles.Forsyth for(i=0; i<32; i++)
48774a4d8c2SCharles.Forsyth for(n=0; n<32; n++)
48874a4d8c2SCharles.Forsyth xcmp[i][n] = cmp(n, i);
48974a4d8c2SCharles.Forsyth for(n=0; optab[n].as != AXXX; n++)
49074a4d8c2SCharles.Forsyth ;
49174a4d8c2SCharles.Forsyth qsort(optab, n, sizeof(optab[0]), ocmp);
49274a4d8c2SCharles.Forsyth for(i=0; i<n; i++) {
49374a4d8c2SCharles.Forsyth r = optab[i].as;
49474a4d8c2SCharles.Forsyth oprange[r].start = optab+i;
49574a4d8c2SCharles.Forsyth while(optab[i].as == r)
49674a4d8c2SCharles.Forsyth i++;
49774a4d8c2SCharles.Forsyth oprange[r].stop = optab+i;
49874a4d8c2SCharles.Forsyth i--;
49974a4d8c2SCharles.Forsyth
50074a4d8c2SCharles.Forsyth switch(r)
50174a4d8c2SCharles.Forsyth {
50274a4d8c2SCharles.Forsyth default:
50374a4d8c2SCharles.Forsyth diag("unknown op in build: %A", r);
50474a4d8c2SCharles.Forsyth errorexit();
50574a4d8c2SCharles.Forsyth case AABSF:
50674a4d8c2SCharles.Forsyth oprange[AMOVFD] = oprange[r];
50774a4d8c2SCharles.Forsyth oprange[AMOVDF] = oprange[r];
50874a4d8c2SCharles.Forsyth oprange[AMOVWF] = oprange[r];
50974a4d8c2SCharles.Forsyth oprange[AMOVFW] = oprange[r];
51074a4d8c2SCharles.Forsyth oprange[AMOVWD] = oprange[r];
51174a4d8c2SCharles.Forsyth oprange[AMOVDW] = oprange[r];
51274a4d8c2SCharles.Forsyth oprange[ANEGF] = oprange[r];
51374a4d8c2SCharles.Forsyth oprange[ANEGD] = oprange[r];
51474a4d8c2SCharles.Forsyth oprange[AABSD] = oprange[r];
51574a4d8c2SCharles.Forsyth break;
51674a4d8c2SCharles.Forsyth case AADD:
51774a4d8c2SCharles.Forsyth buildrep(1, AADD);
51874a4d8c2SCharles.Forsyth oprange[ASGT] = oprange[r];
51974a4d8c2SCharles.Forsyth repop[ASGT] = 1;
52074a4d8c2SCharles.Forsyth oprange[ASGTU] = oprange[r];
52174a4d8c2SCharles.Forsyth repop[ASGTU] = 1;
52274a4d8c2SCharles.Forsyth oprange[AADDU] = oprange[r];
52374a4d8c2SCharles.Forsyth repop[AADDU] = 1;
52474a4d8c2SCharles.Forsyth oprange[AADDVU] = oprange[r];
52574a4d8c2SCharles.Forsyth repop[AADDVU] = 1;
52674a4d8c2SCharles.Forsyth break;
52774a4d8c2SCharles.Forsyth case AADDF:
52874a4d8c2SCharles.Forsyth oprange[ADIVF] = oprange[r];
52974a4d8c2SCharles.Forsyth oprange[ADIVD] = oprange[r];
53074a4d8c2SCharles.Forsyth oprange[AMULF] = oprange[r];
53174a4d8c2SCharles.Forsyth oprange[AMULD] = oprange[r];
53274a4d8c2SCharles.Forsyth oprange[ASUBF] = oprange[r];
53374a4d8c2SCharles.Forsyth oprange[ASUBD] = oprange[r];
53474a4d8c2SCharles.Forsyth oprange[AADDD] = oprange[r];
53574a4d8c2SCharles.Forsyth break;
53674a4d8c2SCharles.Forsyth case AAND:
53774a4d8c2SCharles.Forsyth buildrep(2, AAND);
53874a4d8c2SCharles.Forsyth oprange[AXOR] = oprange[r];
53974a4d8c2SCharles.Forsyth repop[AXOR] = 2;
54074a4d8c2SCharles.Forsyth oprange[AOR] = oprange[r];
54174a4d8c2SCharles.Forsyth repop[AOR] = 2;
54274a4d8c2SCharles.Forsyth break;
54374a4d8c2SCharles.Forsyth case ABEQ:
54474a4d8c2SCharles.Forsyth oprange[ABNE] = oprange[r];
54574a4d8c2SCharles.Forsyth break;
54674a4d8c2SCharles.Forsyth case ABLEZ:
54774a4d8c2SCharles.Forsyth oprange[ABGEZ] = oprange[r];
54874a4d8c2SCharles.Forsyth oprange[ABGEZAL] = oprange[r];
54974a4d8c2SCharles.Forsyth oprange[ABLTZ] = oprange[r];
55074a4d8c2SCharles.Forsyth oprange[ABLTZAL] = oprange[r];
55174a4d8c2SCharles.Forsyth oprange[ABGTZ] = oprange[r];
55274a4d8c2SCharles.Forsyth break;
55374a4d8c2SCharles.Forsyth case AMOVB:
55474a4d8c2SCharles.Forsyth buildrep(3, AMOVB);
55574a4d8c2SCharles.Forsyth oprange[AMOVH] = oprange[r];
55674a4d8c2SCharles.Forsyth repop[AMOVH] = 3;
55774a4d8c2SCharles.Forsyth break;
55874a4d8c2SCharles.Forsyth case AMOVBU:
55974a4d8c2SCharles.Forsyth buildrep(4, AMOVBU);
56074a4d8c2SCharles.Forsyth oprange[AMOVHU] = oprange[r];
56174a4d8c2SCharles.Forsyth repop[AMOVHU] = 4;
56274a4d8c2SCharles.Forsyth break;
56374a4d8c2SCharles.Forsyth case AMUL:
56474a4d8c2SCharles.Forsyth oprange[AREM] = oprange[r];
56574a4d8c2SCharles.Forsyth oprange[AREMU] = oprange[r];
56674a4d8c2SCharles.Forsyth oprange[ADIVU] = oprange[r];
56774a4d8c2SCharles.Forsyth oprange[AMULU] = oprange[r];
56874a4d8c2SCharles.Forsyth oprange[ADIV] = oprange[r];
56974a4d8c2SCharles.Forsyth oprange[ADIVVU] = oprange[r];
57074a4d8c2SCharles.Forsyth oprange[ADIVV] = oprange[r];
57174a4d8c2SCharles.Forsyth break;
57274a4d8c2SCharles.Forsyth case ASLL:
57374a4d8c2SCharles.Forsyth oprange[ASRL] = oprange[r];
57474a4d8c2SCharles.Forsyth oprange[ASRA] = oprange[r];
57574a4d8c2SCharles.Forsyth oprange[ASLLV] = oprange[r];
57674a4d8c2SCharles.Forsyth oprange[ASRAV] = oprange[r];
57774a4d8c2SCharles.Forsyth oprange[ASRLV] = oprange[r];
57874a4d8c2SCharles.Forsyth break;
57974a4d8c2SCharles.Forsyth case ASUB:
58074a4d8c2SCharles.Forsyth oprange[ASUBU] = oprange[r];
58174a4d8c2SCharles.Forsyth oprange[ANOR] = oprange[r];
58274a4d8c2SCharles.Forsyth break;
58374a4d8c2SCharles.Forsyth case ASYSCALL:
58474a4d8c2SCharles.Forsyth oprange[ATLBP] = oprange[r];
58574a4d8c2SCharles.Forsyth oprange[ATLBR] = oprange[r];
58674a4d8c2SCharles.Forsyth oprange[ATLBWI] = oprange[r];
58774a4d8c2SCharles.Forsyth oprange[ATLBWR] = oprange[r];
58874a4d8c2SCharles.Forsyth break;
58974a4d8c2SCharles.Forsyth case ACMPEQF:
59074a4d8c2SCharles.Forsyth oprange[ACMPGTF] = oprange[r];
59174a4d8c2SCharles.Forsyth oprange[ACMPGTD] = oprange[r];
59274a4d8c2SCharles.Forsyth oprange[ACMPGEF] = oprange[r];
59374a4d8c2SCharles.Forsyth oprange[ACMPGED] = oprange[r];
59474a4d8c2SCharles.Forsyth oprange[ACMPEQD] = oprange[r];
59574a4d8c2SCharles.Forsyth break;
59674a4d8c2SCharles.Forsyth case ABFPT:
59774a4d8c2SCharles.Forsyth oprange[ABFPF] = oprange[r];
59874a4d8c2SCharles.Forsyth break;
59974a4d8c2SCharles.Forsyth case AMOVWL:
60074a4d8c2SCharles.Forsyth oprange[AMOVWR] = oprange[r];
60174a4d8c2SCharles.Forsyth oprange[AMOVVR] = oprange[r];
60274a4d8c2SCharles.Forsyth oprange[AMOVVL] = oprange[r];
60374a4d8c2SCharles.Forsyth break;
60474a4d8c2SCharles.Forsyth case AMOVW:
60574a4d8c2SCharles.Forsyth buildrep(5, AMOVW);
60674a4d8c2SCharles.Forsyth break;
60774a4d8c2SCharles.Forsyth case AMOVD:
60874a4d8c2SCharles.Forsyth buildrep(6, AMOVD);
60974a4d8c2SCharles.Forsyth break;
61074a4d8c2SCharles.Forsyth case AMOVF:
61174a4d8c2SCharles.Forsyth buildrep(7, AMOVF);
61274a4d8c2SCharles.Forsyth break;
61374a4d8c2SCharles.Forsyth case AMOVV:
61474a4d8c2SCharles.Forsyth buildrep(8, AMOVV);
61574a4d8c2SCharles.Forsyth break;
61674a4d8c2SCharles.Forsyth case ABREAK:
61774a4d8c2SCharles.Forsyth case AWORD:
61874a4d8c2SCharles.Forsyth case ARFE:
61974a4d8c2SCharles.Forsyth case AJAL:
62074a4d8c2SCharles.Forsyth case AJMP:
62174a4d8c2SCharles.Forsyth case ATEXT:
62274a4d8c2SCharles.Forsyth case ACASE:
62374a4d8c2SCharles.Forsyth case ABCASE:
62474a4d8c2SCharles.Forsyth break;
62574a4d8c2SCharles.Forsyth }
62674a4d8c2SCharles.Forsyth }
62774a4d8c2SCharles.Forsyth }
62874a4d8c2SCharles.Forsyth
62974a4d8c2SCharles.Forsyth void
buildrep(int x,int as)63074a4d8c2SCharles.Forsyth buildrep(int x, int as)
63174a4d8c2SCharles.Forsyth {
63274a4d8c2SCharles.Forsyth Opcross *p;
63374a4d8c2SCharles.Forsyth Optab *e, *s, *o;
63474a4d8c2SCharles.Forsyth int a1, a2, a3, n;
63574a4d8c2SCharles.Forsyth
63674a4d8c2SCharles.Forsyth if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
63774a4d8c2SCharles.Forsyth diag("assumptions fail in buildrep");
63874a4d8c2SCharles.Forsyth errorexit();
63974a4d8c2SCharles.Forsyth }
64074a4d8c2SCharles.Forsyth repop[as] = x;
64174a4d8c2SCharles.Forsyth p = (opcross + x);
64274a4d8c2SCharles.Forsyth s = oprange[as].start;
64374a4d8c2SCharles.Forsyth e = oprange[as].stop;
64474a4d8c2SCharles.Forsyth for(o=e-1; o>=s; o--) {
64574a4d8c2SCharles.Forsyth n = o-optab;
64674a4d8c2SCharles.Forsyth for(a2=0; a2<2; a2++) {
64774a4d8c2SCharles.Forsyth if(a2) {
64874a4d8c2SCharles.Forsyth if(o->a2 == C_NONE)
64974a4d8c2SCharles.Forsyth continue;
65074a4d8c2SCharles.Forsyth } else
65174a4d8c2SCharles.Forsyth if(o->a2 != C_NONE)
65274a4d8c2SCharles.Forsyth continue;
65374a4d8c2SCharles.Forsyth for(a1=0; a1<32; a1++) {
65474a4d8c2SCharles.Forsyth if(!xcmp[a1][o->a1])
65574a4d8c2SCharles.Forsyth continue;
65674a4d8c2SCharles.Forsyth for(a3=0; a3<32; a3++)
65774a4d8c2SCharles.Forsyth if(xcmp[a3][o->a3])
65874a4d8c2SCharles.Forsyth (*p)[a1][a2][a3] = n;
65974a4d8c2SCharles.Forsyth }
66074a4d8c2SCharles.Forsyth }
66174a4d8c2SCharles.Forsyth }
66274a4d8c2SCharles.Forsyth oprange[as].start = 0;
66374a4d8c2SCharles.Forsyth }
664