summaryrefslogtreecommitdiff
path: root/sys/src/cmd/kl/span.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/kl/span.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/kl/span.c')
-rwxr-xr-xsys/src/cmd/kl/span.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/sys/src/cmd/kl/span.c b/sys/src/cmd/kl/span.c
new file mode 100755
index 000000000..a788b8d37
--- /dev/null
+++ b/sys/src/cmd/kl/span.c
@@ -0,0 +1,524 @@
+#include "l.h"
+
+void
+span(void)
+{
+ Prog *p;
+ Sym *setext;
+ Optab *o;
+ int m;
+ long c;
+
+ if(debug['v'])
+ Bprint(&bso, "%5.2f span\n", cputime());
+ Bflush(&bso);
+ c = INITTEXT;
+ for(p = firstp; p != P; p = p->link) {
+ p->pc = c;
+ o = oplook(p);
+ m = o->size;
+ if(m == 0) {
+ if(p->as == ATEXT) {
+ curtext = p;
+ autosize = p->to.offset + 4;
+ if(p->from.sym != S)
+ p->from.sym->value = c;
+ continue;
+ }
+ if(p->as != ANOP)
+ diag("zero-width instruction\n%P", p);
+ continue;
+ }
+ c += m;
+ }
+ c = rnd(c, 8);
+
+ setext = lookup("etext", 0);
+ if(setext != S) {
+ setext->value = c;
+ textsize = c - INITTEXT;
+ }
+ if(INITRND)
+ INITDAT = rnd(c, INITRND);
+ if(debug['v'])
+ Bprint(&bso, "tsize = %lux\n", textsize);
+ Bflush(&bso);
+}
+
+void
+xdefine(char *p, int t, long v)
+{
+ Sym *s;
+
+ s = lookup(p, 0);
+ if(s->type == 0 || s->type == SXREF) {
+ s->type = t;
+ s->value = v;
+ }
+}
+
+long
+regoff(Adr *a)
+{
+
+ instoffset = 0;
+ aclass(a);
+ return instoffset;
+}
+
+int
+aclass(Adr *a)
+{
+ Sym *s;
+ int t;
+
+ switch(a->type) {
+ case D_NONE:
+ return C_NONE;
+
+ case D_REG:
+ return C_REG;
+
+ case D_FREG:
+ return C_FREG;
+
+ case D_CREG:
+ return C_CREG;
+
+ case D_PREG:
+ if(a->reg == D_FSR)
+ return C_FSR;
+ if(a->reg == D_FPQ)
+ return C_FQ;
+ return C_PREG;
+
+ case D_OREG:
+ switch(a->name) {
+ case D_EXTERN:
+ case D_STATIC:
+ if(a->sym == S)
+ break;
+ t = a->sym->type;
+ if(t == 0 || t == SXREF) {
+ diag("undefined external: %s in %s",
+ a->sym->name, TNAME);
+ a->sym->type = SDATA;
+ }
+ instoffset = a->sym->value + a->offset - BIG;
+ if(instoffset >= -BIG && instoffset < BIG) {
+ if(instoffset & 7)
+ return C_OSEXT;
+ return C_ESEXT;
+ }
+ if(instoffset & 7)
+ return C_OLEXT;
+ return C_ELEXT;
+ case D_AUTO:
+ instoffset = autosize + a->offset;
+ goto dauto;
+
+ case D_PARAM:
+ instoffset = autosize + a->offset + 4L;
+ dauto:
+ if(instoffset >= -BIG && instoffset < BIG) {
+ if(instoffset & 7)
+ return C_OSAUTO;
+ return C_ESAUTO;
+ }
+ if(instoffset & 7)
+ return C_OLAUTO;
+ return C_ELAUTO;
+ case D_NONE:
+ instoffset = a->offset;
+ if(instoffset == 0)
+ return C_ZOREG;
+ if(instoffset >= -BIG && instoffset < BIG)
+ return C_SOREG;
+ return C_LOREG;
+ }
+ return C_GOK;
+
+ case D_ASI:
+ if(a->name == D_NONE)
+ return C_ASI;
+ return C_GOK;
+
+ case D_CONST:
+ switch(a->name) {
+
+ case D_NONE:
+ instoffset = a->offset;
+ consize:
+ if(instoffset == 0)
+ return C_ZCON;
+ if(instoffset >= -0x1000 && instoffset <= 0xfff)
+ return C_SCON;
+ if((instoffset & 0x3ff) == 0)
+ return C_UCON;
+ return C_LCON;
+
+ case D_EXTERN:
+ case D_STATIC:
+ s = a->sym;
+ if(s == S)
+ break;
+ t = s->type;
+ if(t == 0 || t == SXREF) {
+ diag("undefined external: %s in %s",
+ s->name, TNAME);
+ s->type = SDATA;
+ }
+ if(s->type == STEXT || s->type == SLEAF) {
+ instoffset = s->value + a->offset;
+ return C_LCON;
+ }
+ if(s->type == SCONST) {
+ instoffset = s->value + a->offset;
+ goto consize;
+ }
+ instoffset = s->value + a->offset - BIG;
+ if(instoffset >= -BIG && instoffset < BIG && instoffset != 0)
+ return C_SECON;
+ instoffset = s->value + a->offset + INITDAT;
+/* not sure why this barfs */
+return C_LCON;
+/*
+ if(instoffset == 0)
+ return C_ZCON;
+ if(instoffset >= -0x1000 && instoffset <= 0xfff)
+ return C_SCON;
+ if((instoffset & 0x3ff) == 0)
+ return C_UCON;
+ return C_LCON;
+*/
+
+ case D_AUTO:
+ instoffset = autosize + a->offset;
+ if(instoffset >= -BIG && instoffset < BIG)
+ return C_SACON;
+ return C_LACON;
+
+ case D_PARAM:
+ instoffset = autosize + a->offset + 4L;
+ if(instoffset >= -BIG && instoffset < BIG)
+ return C_SACON;
+ return C_LACON;
+ }
+ return C_GOK;
+
+ case D_BRANCH:
+ return C_SBRA;
+ }
+ return C_GOK;
+}
+
+Optab*
+oplook(Prog *p)
+{
+ int a1, a2, a3, r;
+ char *c1, *c3;
+ Optab *o, *e;
+
+ a1 = p->optab;
+ if(a1)
+ return optab+(a1-1);
+ a1 = p->from.class;
+ if(a1 == 0) {
+ a1 = aclass(&p->from) + 1;
+ p->from.class = a1;
+ }
+ a1--;
+ a3 = p->to.class;
+ if(a3 == 0) {
+ a3 = aclass(&p->to) + 1;
+ p->to.class = a3;
+ }
+ a3--;
+ a2 = C_NONE;
+ if(p->reg != NREG)
+ a2 = C_REG;
+ r = p->as;
+ o = oprange[r].start;
+ if(o == 0)
+ o = oprange[r].stop; /* just generate an error */
+ e = oprange[r].stop;
+ c1 = xcmp[a1];
+ c3 = xcmp[a3];
+ for(; o<e; o++)
+ if(o->a2 == a2)
+ if(c1[o->a1])
+ if(c3[o->a3]) {
+ p->optab = (o-optab)+1;
+ return o;
+ }
+ diag("illegal combination %A %d %d %d",
+ p->as, a1, a2, a3);
+ if(1||!debug['a'])
+ prasm(p);
+ if(o == 0)
+ errorexit();
+ return o;
+}
+
+int
+cmp(int a, int b)
+{
+
+ if(a == b)
+ return 1;
+ switch(a) {
+ case C_LCON:
+ if(b == C_ZCON || b == C_SCON || b == C_UCON)
+ return 1;
+ break;
+ case C_UCON:
+ if(b == C_ZCON)
+ return 1;
+ break;
+ case C_SCON:
+ if(b == C_ZCON)
+ return 1;
+ break;
+ case C_LACON:
+ if(b == C_SACON)
+ return 1;
+ break;
+ case C_LBRA:
+ if(b == C_SBRA)
+ return 1;
+ break;
+ case C_ELEXT:
+ if(b == C_ESEXT)
+ return 1;
+ break;
+ case C_LEXT:
+ if(b == C_SEXT ||
+ b == C_ESEXT || b == C_OSEXT ||
+ b == C_ELEXT || b == C_OLEXT)
+ return 1;
+ break;
+ case C_SEXT:
+ if(b == C_ESEXT || b == C_OSEXT)
+ return 1;
+ break;
+ case C_ELAUTO:
+ if(b == C_ESAUTO)
+ return 1;
+ break;
+ case C_LAUTO:
+ if(b == C_SAUTO ||
+ b == C_ESAUTO || b == C_OSAUTO ||
+ b == C_ELAUTO || b == C_OLAUTO)
+ return 1;
+ break;
+ case C_SAUTO:
+ if(b == C_ESAUTO || b == C_OSAUTO)
+ return 1;
+ break;
+ case C_REG:
+ if(b == C_ZCON)
+ return 1;
+ break;
+ case C_LOREG:
+ if(b == C_ZOREG || b == C_SOREG)
+ return 1;
+ break;
+ case C_SOREG:
+ if(b == C_ZOREG)
+ return 1;
+ break;
+
+ case C_ANY:
+ return 1;
+ }
+ return 0;
+}
+
+int
+ocmp(const void *a1, const void *a2)
+{
+ Optab *p1, *p2;
+ int n;
+
+ p1 = (Optab*)a1;
+ p2 = (Optab*)a2;
+ n = p1->as - p2->as;
+ if(n)
+ return n;
+ n = p1->a1 - p2->a1;
+ if(n)
+ return n;
+ n = p1->a2 - p2->a2;
+ if(n)
+ return n;
+ n = p1->a3 - p2->a3;
+ if(n)
+ return n;
+ return 0;
+}
+
+void
+buildop(void)
+{
+ int i, n, r;
+
+ for(i=0; i<C_NCLASS; i++)
+ for(n=0; n<C_NCLASS; n++)
+ xcmp[i][n] = cmp(n, i);
+ for(n=0; optab[n].as != AXXX; n++)
+ ;
+ qsort(optab, n, sizeof(optab[0]), ocmp);
+ for(i=0; i<n; i++) {
+ r = optab[i].as;
+ oprange[r].start = optab+i;
+ while(optab[i].as == r)
+ i++;
+ oprange[r].stop = optab+i;
+ i--;
+
+ switch(r)
+ {
+ default:
+ diag("unknown op in build: %A", r);
+ errorexit();
+ case AADD:
+ oprange[AADDX] = oprange[r];
+ oprange[ASUB] = oprange[r];
+ oprange[ASUBX] = oprange[r];
+ oprange[AMUL] = oprange[r];
+ oprange[AXOR] = oprange[r];
+ oprange[AXNOR] = oprange[r];
+ oprange[AAND] = oprange[r];
+ oprange[AANDN] = oprange[r];
+ oprange[AOR] = oprange[r];
+ oprange[AORN] = oprange[r];
+ oprange[ASLL] = oprange[r];
+ oprange[ASRL] = oprange[r];
+ oprange[ASRA] = oprange[r];
+ oprange[AADDCC] = oprange[r];
+ oprange[AADDXCC] = oprange[r];
+ oprange[ATADDCC] = oprange[r];
+ oprange[ATADDCCTV] = oprange[r];
+ oprange[ASUBCC] = oprange[r];
+ oprange[ASUBXCC] = oprange[r];
+ oprange[ATSUBCC] = oprange[r];
+ oprange[ATSUBCCTV] = oprange[r];
+ oprange[AXORCC] = oprange[r];
+ oprange[AXNORCC] = oprange[r];
+ oprange[AANDCC] = oprange[r];
+ oprange[AANDNCC] = oprange[r];
+ oprange[AORCC] = oprange[r];
+ oprange[AORNCC] = oprange[r];
+ oprange[AMULSCC] = oprange[r];
+ oprange[ASAVE] = oprange[r];
+ oprange[ARESTORE] = oprange[r];
+ break;
+ case AMOVB:
+ oprange[AMOVH] = oprange[r];
+ oprange[AMOVHU] = oprange[r];
+ oprange[AMOVBU] = oprange[r];
+ oprange[ASWAP] = oprange[r];
+ oprange[ATAS] = oprange[r];
+ break;
+ case ABA:
+ oprange[ABN] = oprange[r];
+ oprange[AFBA] = oprange[r];
+ oprange[AFBN] = oprange[r];
+ break;
+ case ABE:
+ oprange[ABCC] = oprange[r];
+ oprange[ABCS] = oprange[r];
+ oprange[ABGE] = oprange[r];
+ oprange[ABGU] = oprange[r];
+ oprange[ABG] = oprange[r];
+ oprange[ABLEU] = oprange[r];
+ oprange[ABLE] = oprange[r];
+ oprange[ABL] = oprange[r];
+ oprange[ABNEG] = oprange[r];
+ oprange[ABNE] = oprange[r];
+ oprange[ABPOS] = oprange[r];
+ oprange[ABVC] = oprange[r];
+ oprange[ABVS] = oprange[r];
+
+ oprange[AFBE] = oprange[r];
+ oprange[AFBG] = oprange[r];
+ oprange[AFBGE] = oprange[r];
+ oprange[AFBL] = oprange[r];
+ oprange[AFBLE] = oprange[r];
+ oprange[AFBLG] = oprange[r];
+ oprange[AFBNE] = oprange[r];
+ oprange[AFBO] = oprange[r];
+ oprange[AFBU] = oprange[r];
+ oprange[AFBUE] = oprange[r];
+ oprange[AFBUG] = oprange[r];
+ oprange[AFBUGE] = oprange[r];
+ oprange[AFBUL] = oprange[r];
+ oprange[AFBULE] = oprange[r];
+ break;
+ case ATA:
+ oprange[ATCC] = oprange[r];
+ oprange[ATCS] = oprange[r];
+ oprange[ATE] = oprange[r];
+ oprange[ATGE] = oprange[r];
+ oprange[ATGU] = oprange[r];
+ oprange[ATG] = oprange[r];
+ oprange[ATLEU] = oprange[r];
+ oprange[ATLE] = oprange[r];
+ oprange[ATL] = oprange[r];
+ oprange[ATNEG] = oprange[r];
+ oprange[ATNE] = oprange[r];
+ oprange[ATN] = oprange[r];
+ oprange[ATPOS] = oprange[r];
+ oprange[ATVC] = oprange[r];
+ oprange[ATVS] = oprange[r];
+ break;
+ case AFADDD:
+ oprange[AFADDF] = oprange[r];
+ oprange[AFADDX] = oprange[r];
+ oprange[AFDIVD] = oprange[r];
+ oprange[AFDIVF] = oprange[r];
+ oprange[AFDIVX] = oprange[r];
+ oprange[AFMULD] = oprange[r];
+ oprange[AFMULF] = oprange[r];
+ oprange[AFMULX] = oprange[r];
+ oprange[AFSUBD] = oprange[r];
+ oprange[AFSUBF] = oprange[r];
+ oprange[AFSUBX] = oprange[r];
+ break;
+ case AFCMPD:
+ oprange[AFCMPF] = oprange[r];
+ oprange[AFCMPX] = oprange[r];
+ oprange[AFCMPED] = oprange[r];
+ oprange[AFCMPEF] = oprange[r];
+ oprange[AFCMPEX] = oprange[r];
+ break;
+ case AFABSF:
+ oprange[AFMOVDF] = oprange[r];
+ oprange[AFMOVDW] = oprange[r];
+ oprange[AFMOVFD] = oprange[r];
+ oprange[AFMOVFW] = oprange[r];
+ oprange[AFMOVWD] = oprange[r];
+ oprange[AFMOVWF] = oprange[r];
+ oprange[AFNEGF] = oprange[r];
+ oprange[AFSQRTD] = oprange[r];
+ oprange[AFSQRTF] = oprange[r];
+ break;
+ case AFMOVF:
+ case AFMOVD:
+ case AMOVW:
+ case AMOVD:
+ case AWORD:
+ case ARETT:
+ case AJMPL:
+ case AJMP:
+ case ACMP:
+ case ANOP:
+ case ATEXT:
+ case ADIV:
+ case ADIVL:
+ case AMOD:
+ case AMODL:
+ break;
+ }
+ }
+}