diff options
Diffstat (limited to 'src/cmd/8c')
-rw-r--r-- | src/cmd/8c/cgen.c | 35 | ||||
-rw-r--r-- | src/cmd/8c/doc.go | 6 | ||||
-rw-r--r-- | src/cmd/8c/gc.h | 1 | ||||
-rw-r--r-- | src/cmd/8c/list.c | 64 | ||||
-rw-r--r-- | src/cmd/8c/mul.c | 8 | ||||
-rw-r--r-- | src/cmd/8c/peep.c | 6 | ||||
-rw-r--r-- | src/cmd/8c/reg.c | 151 | ||||
-rw-r--r-- | src/cmd/8c/swt.c | 47 | ||||
-rw-r--r-- | src/cmd/8c/txt.c | 23 |
9 files changed, 302 insertions, 39 deletions
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c index 869d31ace..78eb7eced 100644 --- a/src/cmd/8c/cgen.c +++ b/src/cmd/8c/cgen.c @@ -277,6 +277,18 @@ cgen(Node *n, Node *nn) break; } } + if(n->op == OOR && l->op == OASHL && r->op == OLSHR + && l->right->op == OCONST && r->right->op == OCONST + && l->left->op == ONAME && r->left->op == ONAME + && l->left->sym == r->left->sym + && l->right->vconst + r->right->vconst == 8 * l->left->type->width) { + regalloc(&nod, l->left, nn); + cgen(l->left, &nod); + gopcode(OROTL, n->type, l->right, &nod); + gmove(&nod, nn); + regfree(&nod); + break; + } if(n->op == OADD && l->op == OASHL && l->right->op == OCONST && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) { c = l->right->vconst; @@ -1703,6 +1715,7 @@ copy: } } + v = w == 8; if(n->complex >= FNX && nn != nil && nn->complex >= FNX) { t = nn->type; nn->type = types[TLONG]; @@ -1728,8 +1741,28 @@ copy: } x = 0; - v = w == 8; if(v) { + if(nn != nil && nn->complex >= FNX) { + t = nn->type; + nn->type = types[TLONG]; + regialloc(&nod2, nn, Z); + lcgen(nn, &nod2); + nn->type = t; + + nod2.type = typ(TIND, t); + + nod1 = nod2; + nod1.op = OIND; + nod1.left = &nod2; + nod1.right = Z; + nod1.complex = 1; + nod1.type = t; + + sugen(n, &nod1, w); + regfree(&nod2); + return; + } + c = cursafe; if(n->left != Z && n->left->complex >= FNX && n->right != Z && n->right->complex >= FNX) { diff --git a/src/cmd/8c/doc.go b/src/cmd/8c/doc.go index e3aae857f..0d07db14d 100644 --- a/src/cmd/8c/doc.go +++ b/src/cmd/8c/doc.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build ignore + /* 8c is a version of the Plan 9 C compiler. The original is documented at - http://plan9.bell-labs.com/magic/man2html/1/2c + http://plan9.bell-labs.com/magic/man2html/1/8c Its target architecture is the x86, referred to by these tools for historical reasons as 386. */ -package documentation +package main diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h index 4a57f5d3c..bdf981b4c 100644 --- a/src/cmd/8c/gc.h +++ b/src/cmd/8c/gc.h @@ -297,6 +297,7 @@ void gbranch(int); void patch(Prog*, int32); int sconst(Node*); void gpseudo(int, Sym*, Node*); +void gprefetch(Node*); /* * swt.c diff --git a/src/cmd/8c/list.c b/src/cmd/8c/list.c index c422905cd..8506e08ef 100644 --- a/src/cmd/8c/list.c +++ b/src/cmd/8c/list.c @@ -93,7 +93,7 @@ Pconv(Fmt *fp) break; default: - sprint(str, "(%L) %A %D,%lD", + sprint(str, "(%L) %A %D,%D", p->lineno, p->as, &p->from, &p->to); break; } @@ -118,6 +118,17 @@ Dconv(Fmt *fp) a = va_arg(fp->args, Adr*); i = a->type; + + if(fp->flags & FmtLong) { + if(i == D_CONST2) + sprint(str, "$%d-%d", a->offset, a->offset2); + else { + // ATEXT dst is not constant + sprint(str, "!!%D", a); + } + goto brk; + } + if(i >= D_INDIR) { if(a->offset) sprint(str, "%d(%R)", a->offset, i-D_INDIR); @@ -126,7 +137,6 @@ Dconv(Fmt *fp) goto brk; } switch(i) { - default: if(a->offset) sprint(str, "$%d,%R", a->offset, i); @@ -139,7 +149,7 @@ Dconv(Fmt *fp) break; case D_BRANCH: - sprint(str, "%d(PC)", a->offset-pc); + sprint(str, "%d", a->offset); break; case D_EXTERN: @@ -147,12 +157,14 @@ Dconv(Fmt *fp) break; case D_STATIC: - sprint(str, "%s<>+%d(SB)", a->sym->name, - a->offset); + sprint(str, "%s<>+%d(SB)", a->sym->name, a->offset); break; case D_AUTO: - sprint(str, "%s+%d(SP)", a->sym->name, a->offset); + if(a->sym) + sprint(str, "%s+%d(SP)", a->sym->name, a->offset); + else + sprint(str, "%d(SP)", a->offset); break; case D_PARAM: @@ -167,7 +179,10 @@ Dconv(Fmt *fp) break; case D_CONST2: - sprint(str, "$%d-%d", a->offset, a->offset2); + if(!(fp->flags & FmtLong)) { + // D_CONST2 outside of ATEXT should not happen + sprint(str, "!!$%d-%d", a->offset, a->offset2); + } break; case D_FCONST: @@ -197,7 +212,7 @@ conv: char* regstr[] = { - "AL", /*[D_AL]*/ + "AL", /* [D_AL] */ "CL", "DL", "BL", @@ -206,7 +221,7 @@ char* regstr[] = "DH", "BH", - "AX", /*[D_AX]*/ + "AX", /* [D_AX] */ "CX", "DX", "BX", @@ -215,7 +230,7 @@ char* regstr[] = "SI", "DI", - "F0", /*[D_F0]*/ + "F0", /* [D_F0] */ "F1", "F2", "F3", @@ -224,20 +239,20 @@ char* regstr[] = "F6", "F7", - "CS", /*[D_CS]*/ + "CS", /* [D_CS] */ "SS", "DS", "ES", "FS", "GS", - "GDTR", /*[D_GDTR]*/ - "IDTR", /*[D_IDTR]*/ - "LDTR", /*[D_LDTR]*/ - "MSW", /*[D_MSW] */ - "TASK", /*[D_TASK]*/ + "GDTR", /* [D_GDTR] */ + "IDTR", /* [D_IDTR] */ + "LDTR", /* [D_LDTR] */ + "MSW", /* [D_MSW] */ + "TASK", /* [D_TASK] */ - "CR0", /*[D_CR]*/ + "CR0", /* [D_CR] */ "CR1", "CR2", "CR3", @@ -246,7 +261,7 @@ char* regstr[] = "CR6", "CR7", - "DR0", /*[D_DR]*/ + "DR0", /* [D_DR] */ "DR1", "DR2", "DR3", @@ -255,7 +270,7 @@ char* regstr[] = "DR6", "DR7", - "TR0", /*[D_TR]*/ + "TR0", /* [D_TR] */ "TR1", "TR2", "TR3", @@ -264,7 +279,16 @@ char* regstr[] = "TR6", "TR7", - "NONE", /*[D_NONE]*/ + "X0", /* [D_X0] */ + "X1", + "X2", + "X3", + "X4", + "X5", + "X6", + "X7", + + "NONE", /* [D_NONE] */ }; int diff --git a/src/cmd/8c/mul.c b/src/cmd/8c/mul.c index a0742807e..9955e762f 100644 --- a/src/cmd/8c/mul.c +++ b/src/cmd/8c/mul.c @@ -35,17 +35,17 @@ typedef struct Mparam Mparam; struct Malg { - char vals[10]; + schar vals[10]; }; struct Mparam { uint32 value; - char alg; + schar alg; char neg; char shift; char arg; - char off; + schar off; }; static Mparam multab[32]; @@ -101,7 +101,7 @@ mulparam(uint32 m, Mparam *mp) { int c, i, j, n, o, q, s; int bc, bi, bn, bo, bq, bs, bt; - char *p; + schar *p; int32 u; uint32 t; diff --git a/src/cmd/8c/peep.c b/src/cmd/8c/peep.c index 9511a5579..9c3e9a5af 100644 --- a/src/cmd/8c/peep.c +++ b/src/cmd/8c/peep.c @@ -602,6 +602,12 @@ copyu(Prog *p, Adr *v, Adr *s) case ACMPL: /* read only */ case ACMPW: case ACMPB: + + case APREFETCHT0: + case APREFETCHT1: + case APREFETCHT2: + case APREFETCHNTA: + case AFCOMB: case AFCOMBP: diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c index 6ba07bed2..6c87d70a5 100644 --- a/src/cmd/8c/reg.c +++ b/src/cmd/8c/reg.c @@ -30,6 +30,8 @@ #include "gc.h" +static void fixjmp(Reg*); + Reg* rega(void) { @@ -148,7 +150,6 @@ regopt(Prog *p) r->p1 = R; r1->s1 = R; } - bit = mkvar(r, &p->from); if(bany(&bit)) switch(p->as) { @@ -182,6 +183,10 @@ regopt(Prog *p) case ACMPB: case ACMPL: case ACMPW: + case APREFETCHT0: + case APREFETCHT1: + case APREFETCHT2: + case APREFETCHNTA: for(z=0; z<BITS; z++) r->use2.b[z] |= bit.b[z]; break; @@ -372,6 +377,12 @@ regopt(Prog *p) } /* + * pass 2.1 + * fix jumps + */ + fixjmp(firstr); + + /* * pass 2.5 * find looping structure */ @@ -543,6 +554,13 @@ brk: if(!debug['R'] || debug['P']) peep(); + if(debug['R'] && debug['v']) { + print("after pass 7 (peep)\n"); + for(r=firstr; r; r=r->link) + print("%04d %P\n", r->pc, r->prog); + print("\n"); + } + /* * pass 8 * recalculate pc @@ -596,6 +614,14 @@ brk: while(p->link && p->link->as == ANOP) p->link = p->link->link; } + + if(debug['R'] && debug['v']) { + print("after pass 8 (fixup pc)\n"); + for(p1=firstr->prog; p1!=P; p1=p1->link) + print("%P\n", p1); + print("\n"); + } + if(r1 != R) { r1->link = freer; freer = firstr; @@ -1285,3 +1311,126 @@ BtoR(int32 b) return 0; return bitno(b) + D_AX; } + +/* what instruction does a JMP to p eventually land on? */ +static Reg* +chasejmp(Reg *r, int *jmploop) +{ + int n; + + n = 0; + for(; r; r=r->s2) { + if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH) + break; + if(++n > 10) { + *jmploop = 1; + break; + } + } + return r; +} + +/* mark all code reachable from firstp as alive */ +static void +mark(Reg *firstr) +{ + Reg *r; + Prog *p; + + for(r=firstr; r; r=r->link) { + if(r->active) + break; + r->active = 1; + p = r->prog; + if(p->as != ACALL && p->to.type == D_BRANCH) + mark(r->s2); + if(p->as == AJMP || p->as == ARET || p->as == AUNDEF) + break; + } +} + +/* + * the code generator depends on being able to write out JMP + * instructions that it can jump to now but fill in later. + * the linker will resolve them nicely, but they make the code + * longer and more difficult to follow during debugging. + * remove them. + */ +static void +fixjmp(Reg *firstr) +{ + int jmploop; + Reg *r; + Prog *p; + + if(debug['R'] && debug['v']) + print("\nfixjmp\n"); + + // pass 1: resolve jump to AJMP, mark all code as dead. + jmploop = 0; + for(r=firstr; r; r=r->link) { + p = r->prog; + if(debug['R'] && debug['v']) + print("%04d %P\n", r->pc, p); + if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) { + r->s2 = chasejmp(r->s2, &jmploop); + p->to.offset = r->s2->pc; + if(debug['R'] && debug['v']) + print("->%P\n", p); + } + r->active = 0; + } + if(debug['R'] && debug['v']) + print("\n"); + + // pass 2: mark all reachable code alive + mark(firstr); + + // pass 3: delete dead code (mostly JMPs). + for(r=firstr; r; r=r->link) { + if(!r->active) { + p = r->prog; + if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) { + // This is the final ARET, and the code so far doesn't have one. + // Let it stay. + } else { + if(debug['R'] && debug['v']) + print("del %04d %P\n", r->pc, p); + p->as = ANOP; + } + } + } + + // pass 4: elide JMP to next instruction. + // only safe if there are no jumps to JMPs anymore. + if(!jmploop) { + for(r=firstr; r; r=r->link) { + p = r->prog; + if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) { + if(debug['R'] && debug['v']) + print("del %04d %P\n", r->pc, p); + p->as = ANOP; + } + } + } + + // fix back pointers. + for(r=firstr; r; r=r->link) { + r->p2 = R; + r->p2link = R; + } + for(r=firstr; r; r=r->link) { + if(r->s2) { + r->p2link = r->s2->p2; + r->s2->p2 = r; + } + } + + if(debug['R'] && debug['v']) { + print("\n"); + for(r=firstr; r; r=r->link) + print("%04d %P\n", r->pc, r->prog); + print("\n"); + } +} + diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index f1ca4c25f..d331eee1a 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -251,18 +251,12 @@ outcode(void) Binit(&b, f, OWRITE); Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); - if(ndynimp > 0 || ndynexp > 0) { - int i; - + if(pragcgobuf.to > pragcgobuf.start) { Bprint(&b, "\n"); Bprint(&b, "$$ // exports\n\n"); Bprint(&b, "$$ // local types\n\n"); - Bprint(&b, "$$ // dynimport\n"); - for(i=0; i<ndynimp; i++) - Bprint(&b, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path); - Bprint(&b, "\n$$ // dynexport\n"); - for(i=0; i<ndynexp; i++) - Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote); + Bprint(&b, "$$ // cgo\n"); + Bprint(&b, "%s", fmtstrflush(&pragcgobuf)); Bprint(&b, "\n$$\n\n"); } Bprint(&b, "!\n"); @@ -343,12 +337,38 @@ outhist(Biobuf *b) char *p, *q, *op, c; Prog pg; int n; + char *tofree; + static int first = 1; + static char *goroot, *goroot_final; + + if(first) { + // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. + first = 0; + goroot = getenv("GOROOT"); + goroot_final = getenv("GOROOT_FINAL"); + if(goroot == nil) + goroot = ""; + if(goroot_final == nil) + goroot_final = goroot; + if(strcmp(goroot, goroot_final) == 0) { + goroot = nil; + goroot_final = nil; + } + } + tofree = nil; pg = zprog; pg.as = AHISTORY; c = pathchar(); for(h = hist; h != H; h = h->link) { p = h->name; + if(p != nil && goroot != nil) { + n = strlen(goroot); + if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') { + tofree = smprint("%s%s", goroot_final, p+n); + p = tofree; + } + } op = 0; if(systemtype(Windows) && p && p[1] == ':'){ c = p[2]; @@ -404,6 +424,11 @@ outhist(Biobuf *b) Bputc(b, pg.lineno>>24); zaddr(b, &pg.from, 0); zaddr(b, &pg.to, 0); + + if(tofree) { + free(tofree); + tofree = nil; + } } } @@ -597,8 +622,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) int32 maxround(int32 max, int32 v) { - v += SZ_LONG-1; + v = xround(v, SZ_LONG); if(v > max) - max = xround(v, SZ_LONG); + return v; return max; } diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c index 3a08da7cd..1b7617bc5 100644 --- a/src/cmd/8c/txt.c +++ b/src/cmd/8c/txt.c @@ -1253,6 +1253,14 @@ gopcode(int o, Type *ty, Node *f, Node *t) a = ASALW; break; + case OROTL: + a = AROLL; + if(et == TCHAR || et == TUCHAR) + a = AROLB; + if(et == TSHORT || et == TUSHORT) + a = AROLW; + break; + case OFUNC: a = ACALL; break; @@ -1383,6 +1391,21 @@ gpseudo(int a, Sym *s, Node *n) pc--; } +void +gprefetch(Node *n) +{ + Node n1; + + if(strcmp(getgo386(), "sse2") != 0) // assume no prefetch on old machines + return; + + regalloc(&n1, n, Z); + gmove(n, &n1); + n1.op = OINDREG; + gins(APREFETCHNTA, &n1, Z); + regfree(&n1); +} + int sconst(Node *n) { |