diff options
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/8a/a.y | 7 | ||||
-rw-r--r-- | src/cmd/8l/l.h | 1 | ||||
-rw-r--r-- | src/cmd/8l/optab.c | 3 | ||||
-rw-r--r-- | src/cmd/8l/pass.c | 7 | ||||
-rw-r--r-- | src/cmd/8l/span.c | 14 | ||||
-rw-r--r-- | src/cmd/ld/data.c | 6 |
6 files changed, 34 insertions, 4 deletions
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y index a8ac773da..96976089d 100644 --- a/src/cmd/8a/a.y +++ b/src/cmd/8a/a.y @@ -210,6 +210,13 @@ spec3: /* JMP/CALL */ $$.from = nullgen; $$.to = $1; } +| '*' nam + { + $$.from = nullgen; + $$.to = $2; + $$.to.index = $2.type; + $$.to.type = D_INDIR+D_ADDR; + } spec4: /* NOP */ nonnon diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 4ee0db967..a721f384b 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -209,6 +209,7 @@ enum Zbr, Zcall, Zcallcon, + Zcallind, Zib_, Zib_rp, Zibo_m, diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c index 42490b861..69602d704 100644 --- a/src/cmd/8l/optab.c +++ b/src/cmd/8l/optab.c @@ -260,6 +260,7 @@ uchar yloop[] = uchar ycall[] = { Ynone, Yml, Zo_m, 2, + Ynone, Ycol, Zcallind, 2, Ynone, Ybr, Zcall, 0, Ynone, Yi32, Zcallcon, 1, 0 @@ -383,7 +384,7 @@ Optab optab[] = { ABTSL, yml_rl, Pm, 0xab }, { ABTSW, yml_rl, Pq, 0xab }, { ABYTE, ybyte, Px, 1 }, - { ACALL, ycall, Px, 0xff,(02),0xe8 }, + { ACALL, ycall, Px, 0xff,(02),0xff,(0x15),0xe8 }, { ACLC, ynone, Px, 0xf8 }, { ACLD, ynone, Px, 0xfc }, { ACLI, ynone, Px, 0xfa }, diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 2e0990c5a..54ea965da 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -307,9 +307,12 @@ patch(void) p->from.offset = 0; } } - if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) { + if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH)) { s = p->to.sym; - if(s) { + if(p->to.type == D_INDIR+D_ADDR) { + /* skip check if this is an indirect call (CALL *symbol(SB)) */ + continue; + } else if(s) { if(debug['c']) Bprint(&bso, "%s calls %s\n", TNAME, s->name); if((s->type&~SSUB) != STEXT) { diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index ba193da1c..81c1d37eb 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -285,6 +285,8 @@ oclass(Adr *a) } return Yxxx; } + //if(a->type == D_INDIR+D_ADDR) + // print("*Ycol\n"); return Ycol; } return Ym; @@ -1143,6 +1145,18 @@ found: r->add = p->to.offset; put4(0); break; + + case Zcallind: + *andptr++ = op; + *andptr++ = o->op[z+1]; + r = addrel(cursym); + r->off = p->pc + andptr - and; + r->type = D_ADDR; + r->siz = 4; + r->add = p->to.offset; + r->sym = p->to.sym; + put4(0); + break; case Zbyte: v = vaddr(&p->from, &rel); diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index e7269169e..a7f61c927 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -182,7 +182,11 @@ relocsym(Sym *s) o = symaddr(r->sym) + r->add; break; case D_PCREL: - o = symaddr(r->sym) + r->add - (s->value + r->off + r->siz); + // r->sym can be null when CALL $(constant) is transformed from absoulte PC to relative PC call. + o = 0; + if(r->sym) + o += symaddr(r->sym); + o += r->add - (s->value + r->off + r->siz); break; case D_SIZE: o = r->sym->size + r->add; |