summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/8a/a.y7
-rw-r--r--src/cmd/8l/l.h1
-rw-r--r--src/cmd/8l/optab.c3
-rw-r--r--src/cmd/8l/pass.c7
-rw-r--r--src/cmd/8l/span.c14
-rw-r--r--src/cmd/ld/data.c6
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;