7l: add arm64 linker (initial sync)
This commit is contained in:
parent
394d095ee0
commit
d8d4802f80
15 changed files with 12923 additions and 0 deletions
615
sys/src/cmd/7l/asm.c
Normal file
615
sys/src/cmd/7l/asm.c
Normal file
|
@ -0,0 +1,615 @@
|
|||
#include "l.h"
|
||||
|
||||
long OFFSET;
|
||||
|
||||
#define PADDR(a) ((a) & ~0xfffffffff0000000ull)
|
||||
|
||||
vlong
|
||||
entryvalue(void)
|
||||
{
|
||||
char *a;
|
||||
Sym *s;
|
||||
|
||||
a = INITENTRY;
|
||||
if(*a >= '0' && *a <= '9')
|
||||
return atolwhex(a);
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
case SLEAF:
|
||||
break;
|
||||
case SDATA:
|
||||
if(dlm)
|
||||
return s->value+INITDAT;
|
||||
default:
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
return s->value;
|
||||
}
|
||||
|
||||
void
|
||||
cflush(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sizeof(buf.cbuf) - cbc;
|
||||
if(n)
|
||||
write(cout, buf.cbuf, n);
|
||||
cbp = buf.cbuf;
|
||||
cbc = sizeof(buf.cbuf);
|
||||
}
|
||||
|
||||
void
|
||||
asmb(void)
|
||||
{
|
||||
Prog *p;
|
||||
long magic, t, etext;
|
||||
vlong vl;
|
||||
Optab *o;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asm\n", cputime());
|
||||
Bflush(&bso);
|
||||
OFFSET = HEADR;
|
||||
seek(cout, OFFSET, 0);
|
||||
pc = INITTEXT;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT) {
|
||||
curtext = p;
|
||||
autosize = p->to.offset + PCSZ;
|
||||
}
|
||||
if(p->as == ADWORD && (pc & 7) != 0) {
|
||||
lputl(0);
|
||||
pc += 4;
|
||||
}
|
||||
if(p->pc != pc) {
|
||||
diag("phase error %llux sb %llux",
|
||||
p->pc, pc);
|
||||
if(!debug['a'])
|
||||
prasm(curp);
|
||||
pc = p->pc;
|
||||
}
|
||||
curp = p;
|
||||
o = oplook(p); /* could probably avoid this call */
|
||||
asmout(p, o);
|
||||
pc += o->size;
|
||||
}
|
||||
|
||||
if(debug['a'])
|
||||
Bprint(&bso, "\n");
|
||||
Bflush(&bso);
|
||||
cflush();
|
||||
|
||||
/* output strings in text segment */
|
||||
etext = INITTEXT + textsize;
|
||||
for(t = pc; t < etext; t += sizeof(buf)-100) {
|
||||
if(etext-t > sizeof(buf)-100)
|
||||
datblk(t, sizeof(buf)-100, 1);
|
||||
else
|
||||
datblk(t, etext-t, 1);
|
||||
}
|
||||
|
||||
curtext = P;
|
||||
switch(HEADTYPE) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 7:
|
||||
OFFSET = HEADR+textsize;
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 6: /* no header, padded segments */
|
||||
OFFSET = rnd(HEADR+textsize, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
}
|
||||
if(dlm){
|
||||
char buf[8];
|
||||
|
||||
write(cout, buf, INITDAT-textsize);
|
||||
textsize = INITDAT;
|
||||
}
|
||||
for(t = 0; t < datsize; t += sizeof(buf)-100) {
|
||||
if(datsize-t > sizeof(buf)-100)
|
||||
datblk(t, sizeof(buf)-100, 0);
|
||||
else
|
||||
datblk(t, datsize-t, 0);
|
||||
}
|
||||
|
||||
symsize = 0;
|
||||
lcsize = 0;
|
||||
if(!debug['s']) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f sym\n", cputime());
|
||||
Bflush(&bso);
|
||||
switch(HEADTYPE) {
|
||||
case 0:
|
||||
debug['s'] = 1;
|
||||
break;
|
||||
case 2:
|
||||
OFFSET = HEADR+textsize+datsize;
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 6: /* no header, padded segments */
|
||||
OFFSET += rnd(datsize, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
}
|
||||
if(!debug['s'])
|
||||
asmsym();
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f pc\n", cputime());
|
||||
Bflush(&bso);
|
||||
if(!debug['s'])
|
||||
asmlc();
|
||||
if(dlm)
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
else if(dlm){
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f header\n", cputime());
|
||||
Bflush(&bso);
|
||||
OFFSET = 0;
|
||||
seek(cout, OFFSET, 0);
|
||||
switch(HEADTYPE) {
|
||||
case 0: /* no header */
|
||||
case 6: /* no header, padded segments */
|
||||
break;
|
||||
case 2: /* plan 9 */
|
||||
magic = 4*28*28+7;
|
||||
magic |= 0x00008000; /* fat header */
|
||||
if(dlm)
|
||||
magic |= 0x80000000; /* dlm */
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(symsize); /* nsyms */
|
||||
vl = entryvalue();
|
||||
lput(PADDR(vl)); /* va of entry */
|
||||
lput(0L);
|
||||
lput(lcsize);
|
||||
llput(vl); /* va of entry */
|
||||
break;
|
||||
}
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
cput(int c)
|
||||
{
|
||||
cbp[0] = c;
|
||||
cbp++;
|
||||
cbc--;
|
||||
if(cbc <= 0)
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
wput(long l)
|
||||
{
|
||||
|
||||
cbp[0] = l>>8;
|
||||
cbp[1] = l;
|
||||
cbp += 2;
|
||||
cbc -= 2;
|
||||
if(cbc <= 0)
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
wputl(long l)
|
||||
{
|
||||
|
||||
cbp[0] = l;
|
||||
cbp[1] = l>>8;
|
||||
cbp += 2;
|
||||
cbc -= 2;
|
||||
if(cbc <= 0)
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
lput(long l)
|
||||
{
|
||||
|
||||
cbp[0] = l>>24;
|
||||
cbp[1] = l>>16;
|
||||
cbp[2] = l>>8;
|
||||
cbp[3] = l;
|
||||
cbp += 4;
|
||||
cbc -= 4;
|
||||
if(cbc <= 0)
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
lputl(long l)
|
||||
{
|
||||
|
||||
cbp[3] = l>>24;
|
||||
cbp[2] = l>>16;
|
||||
cbp[1] = l>>8;
|
||||
cbp[0] = l;
|
||||
cbp += 4;
|
||||
cbc -= 4;
|
||||
if(cbc <= 0)
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
llput(vlong v)
|
||||
{
|
||||
lput(v>>32);
|
||||
lput(v);
|
||||
}
|
||||
|
||||
void
|
||||
llputl(vlong v)
|
||||
{
|
||||
lputl(v);
|
||||
lputl(v>>32);
|
||||
}
|
||||
|
||||
void
|
||||
asmsym(void)
|
||||
{
|
||||
Prog *p;
|
||||
Auto *a;
|
||||
Sym *s;
|
||||
int h;
|
||||
|
||||
s = lookup("etext", 0);
|
||||
if(s->type == STEXT)
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
|
||||
for(h=0; h<NHASH; h++)
|
||||
for(s=hash[h]; s!=S; s=s->link)
|
||||
switch(s->type) {
|
||||
case SCONST:
|
||||
putsymb(s->name, 'D', s->value, s->version);
|
||||
continue;
|
||||
|
||||
case SDATA:
|
||||
putsymb(s->name, 'D', s->value+INITDAT, s->version);
|
||||
continue;
|
||||
|
||||
case SBSS:
|
||||
putsymb(s->name, 'B', s->value+INITDAT, s->version);
|
||||
continue;
|
||||
|
||||
case SSTRING:
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
continue;
|
||||
|
||||
case SFILE:
|
||||
putsymb(s->name, 'f', s->value, s->version);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(p=textp; p!=P; p=p->cond) {
|
||||
s = p->from.sym;
|
||||
if(s->type != STEXT && s->type != SLEAF)
|
||||
continue;
|
||||
|
||||
/* filenames first */
|
||||
for(a=p->to.autom; a; a=a->link)
|
||||
if(a->type == D_FILE)
|
||||
putsymb(a->asym->name, 'z', a->aoffset, 0);
|
||||
else
|
||||
if(a->type == D_FILE1)
|
||||
putsymb(a->asym->name, 'Z', a->aoffset, 0);
|
||||
|
||||
if(s->type == STEXT)
|
||||
putsymb(s->name, 'T', s->value, s->version);
|
||||
else
|
||||
putsymb(s->name, 'L', s->value, s->version);
|
||||
|
||||
/* frame, auto and param after */
|
||||
putsymb(".frame", 'm', p->to.offset+PCSZ, 0);
|
||||
for(a=p->to.autom; a; a=a->link)
|
||||
if(a->type == D_AUTO)
|
||||
putsymb(a->asym->name, 'a', -a->aoffset, 0);
|
||||
else
|
||||
if(a->type == D_PARAM)
|
||||
putsymb(a->asym->name, 'p', a->aoffset, 0);
|
||||
}
|
||||
if(debug['v'] || debug['n'])
|
||||
Bprint(&bso, "symsize = %lud\n", symsize);
|
||||
Bflush(&bso);
|
||||
}
|
||||
|
||||
void
|
||||
putsymb(char *s, int t, vlong v, int ver)
|
||||
{
|
||||
int i, f, l;
|
||||
|
||||
if(t == 'f')
|
||||
s++;
|
||||
l = 4;
|
||||
switch(HEADTYPE){
|
||||
default:
|
||||
break;
|
||||
case 2:
|
||||
lput(v>>32);
|
||||
l = 8;
|
||||
break;
|
||||
}
|
||||
lput(v);
|
||||
if(ver)
|
||||
t += 'a' - 'A';
|
||||
cput(t+0x80); /* 0x80 is variable length */
|
||||
|
||||
if(t == 'Z' || t == 'z') {
|
||||
cput(s[0]);
|
||||
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
|
||||
cput(s[i]);
|
||||
cput(s[i+1]);
|
||||
}
|
||||
cput(0);
|
||||
cput(0);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
for(i=0; s[i]; i++)
|
||||
cput(s[i]);
|
||||
cput(0);
|
||||
}
|
||||
symsize += l + 1 + i + 1;
|
||||
|
||||
if(debug['n']) {
|
||||
if(t == 'z' || t == 'Z') {
|
||||
Bprint(&bso, "%c %.8llux ", t, v);
|
||||
for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
|
||||
f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
|
||||
Bprint(&bso, "/%x", f);
|
||||
}
|
||||
Bprint(&bso, "\n");
|
||||
return;
|
||||
}
|
||||
if(ver)
|
||||
Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
|
||||
else
|
||||
Bprint(&bso, "%c %.8llux %s\n", t, v, s);
|
||||
}
|
||||
}
|
||||
|
||||
#define MINLC 4
|
||||
void
|
||||
asmlc(void)
|
||||
{
|
||||
long oldpc, oldlc;
|
||||
Prog *p;
|
||||
long v, s;
|
||||
|
||||
oldpc = INITTEXT;
|
||||
oldlc = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(debug['V'])
|
||||
Bprint(&bso, "%6llux %P\n",
|
||||
p->pc, p);
|
||||
continue;
|
||||
}
|
||||
if(debug['V'])
|
||||
Bprint(&bso, "\t\t%6ld", lcsize);
|
||||
v = (p->pc - oldpc) / MINLC;
|
||||
while(v) {
|
||||
s = 127;
|
||||
if(v < 127)
|
||||
s = v;
|
||||
cput(s+128); /* 129-255 +pc */
|
||||
if(debug['V'])
|
||||
Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
|
||||
v -= s;
|
||||
lcsize++;
|
||||
}
|
||||
s = p->line - oldlc;
|
||||
oldlc = p->line;
|
||||
oldpc = p->pc + MINLC;
|
||||
if(s > 64 || s < -64) {
|
||||
cput(0); /* 0 vv +lc */
|
||||
cput(s>>24);
|
||||
cput(s>>16);
|
||||
cput(s>>8);
|
||||
cput(s);
|
||||
if(debug['V']) {
|
||||
if(s > 0)
|
||||
Bprint(&bso, " lc+%ld(%d,%ld)\n",
|
||||
s, 0, s);
|
||||
else
|
||||
Bprint(&bso, " lc%ld(%d,%ld)\n",
|
||||
s, 0, s);
|
||||
Bprint(&bso, "%6llux %P\n",
|
||||
p->pc, p);
|
||||
}
|
||||
lcsize += 5;
|
||||
continue;
|
||||
}
|
||||
if(s > 0) {
|
||||
cput(0+s); /* 1-64 +lc */
|
||||
if(debug['V']) {
|
||||
Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
|
||||
Bprint(&bso, "%6llux %P\n",
|
||||
p->pc, p);
|
||||
}
|
||||
} else {
|
||||
cput(64-s); /* 65-128 -lc */
|
||||
if(debug['V']) {
|
||||
Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
|
||||
Bprint(&bso, "%6llux %P\n",
|
||||
p->pc, p);
|
||||
}
|
||||
}
|
||||
lcsize++;
|
||||
}
|
||||
while(lcsize & 1) {
|
||||
s = 129;
|
||||
cput(s);
|
||||
lcsize++;
|
||||
}
|
||||
if(debug['v'] || debug['V'])
|
||||
Bprint(&bso, "lcsize = %ld\n", lcsize);
|
||||
Bflush(&bso);
|
||||
}
|
||||
|
||||
void
|
||||
datblk(long s, long n, int str)
|
||||
{
|
||||
Sym *v;
|
||||
Prog *p;
|
||||
char *cast;
|
||||
long a, l, fl, j;
|
||||
vlong d;
|
||||
int i, c;
|
||||
|
||||
memset(buf.dbuf, 0, n+100);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
if(str != (p->from.sym->type == SSTRING))
|
||||
continue;
|
||||
curp = p;
|
||||
a = p->from.sym->value + p->from.offset;
|
||||
l = a - s;
|
||||
c = p->reg;
|
||||
i = 0;
|
||||
if(l < 0) {
|
||||
if(l+c <= 0)
|
||||
continue;
|
||||
while(l < 0) {
|
||||
l++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(l >= n)
|
||||
continue;
|
||||
if(p->as != AINIT && p->as != ADYNT) {
|
||||
for(j=l+(c-i)-1; j>=l; j--)
|
||||
if(buf.dbuf[j]) {
|
||||
print("%P\n", p);
|
||||
diag("multiple initialization");
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(p->to.type) {
|
||||
default:
|
||||
diag("unknown mode in initialization%P", p);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
switch(c) {
|
||||
default:
|
||||
case 4:
|
||||
fl = ieeedtof(p->to.ieee);
|
||||
cast = (char*)&fl;
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
cast = (char*)p->to.ieee;
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = p->to.sval[i];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
d = p->to.offset;
|
||||
v = p->to.sym;
|
||||
if(v) {
|
||||
switch(v->type) {
|
||||
case SUNDEF:
|
||||
ckoff(v, d);
|
||||
case STEXT:
|
||||
case SLEAF:
|
||||
case SSTRING:
|
||||
d += p->to.sym->value;
|
||||
break;
|
||||
case SDATA:
|
||||
case SBSS:
|
||||
d += p->to.sym->value + INITDAT;
|
||||
}
|
||||
if(dlm)
|
||||
dynreloc(v, a+INITDAT, 1);
|
||||
}
|
||||
cast = (char*)&d;
|
||||
switch(c) {
|
||||
default:
|
||||
diag("bad nuxi %d %d%P", c, i, curp);
|
||||
break;
|
||||
case 1:
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi1[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi2[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
write(cout, buf.dbuf, n);
|
||||
}
|
||||
|
||||
static Ieee chipfloats[] = {
|
||||
{0x00000000, 0x00000000}, /* 0 */
|
||||
{0x00000000, 0x3ff00000}, /* 1 */
|
||||
{0x00000000, 0x40000000}, /* 2 */
|
||||
{0x00000000, 0x40080000}, /* 3 */
|
||||
{0x00000000, 0x40100000}, /* 4 */
|
||||
{0x00000000, 0x40140000}, /* 5 */
|
||||
{0x00000000, 0x3fe00000}, /* .5 */
|
||||
{0x00000000, 0x40240000}, /* 10 */
|
||||
};
|
||||
|
||||
int
|
||||
chipfloat(Ieee *e)
|
||||
{
|
||||
Ieee *p;
|
||||
int n;
|
||||
|
||||
for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
|
||||
p = &chipfloats[n];
|
||||
if(p->l == e->l && p->h == e->h && 0)
|
||||
return n; /* TO DO: return imm8 encoding */
|
||||
}
|
||||
return -1;
|
||||
}
|
1709
sys/src/cmd/7l/asmout.c
Normal file
1709
sys/src/cmd/7l/asmout.c
Normal file
File diff suppressed because it is too large
Load diff
5359
sys/src/cmd/7l/bits.c
Normal file
5359
sys/src/cmd/7l/bits.c
Normal file
File diff suppressed because it is too large
Load diff
56
sys/src/cmd/7l/compat.c
Normal file
56
sys/src/cmd/7l/compat.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "l.h"
|
||||
|
||||
/*
|
||||
* fake malloc
|
||||
*/
|
||||
void*
|
||||
malloc(ulong n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
while(n & 7)
|
||||
n++;
|
||||
while(nhunk < n)
|
||||
gethunk();
|
||||
p = hunk;
|
||||
nhunk -= n;
|
||||
hunk += n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
free(void *p)
|
||||
{
|
||||
USED(p);
|
||||
}
|
||||
|
||||
void*
|
||||
calloc(ulong m, ulong n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
n *= m;
|
||||
p = malloc(n);
|
||||
memset(p, 0, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void*
|
||||
realloc(void *p, ulong n)
|
||||
{
|
||||
fprint(2, "realloc(0x%p %ld) called\n", p, n);
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
mysbrk(ulong size)
|
||||
{
|
||||
return sbrk(size);
|
||||
}
|
||||
|
||||
void
|
||||
setmalloctag(void *v, uintptr pc)
|
||||
{
|
||||
USED(v, pc);
|
||||
}
|
157
sys/src/cmd/7l/dyn.c
Normal file
157
sys/src/cmd/7l/dyn.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
#include "l.h"
|
||||
|
||||
enum{
|
||||
ABSD = 0,
|
||||
ABSU = 1,
|
||||
RELD = 2,
|
||||
RELU = 3,
|
||||
};
|
||||
|
||||
int modemap[4] = { 0, 1, -1, 2, };
|
||||
|
||||
typedef struct Reloc Reloc;
|
||||
|
||||
struct Reloc
|
||||
{
|
||||
int n;
|
||||
int t;
|
||||
uchar *m;
|
||||
ulong *a;
|
||||
};
|
||||
|
||||
Reloc rels;
|
||||
|
||||
static void
|
||||
grow(Reloc *r)
|
||||
{
|
||||
int t;
|
||||
uchar *m, *nm;
|
||||
ulong *a, *na;
|
||||
|
||||
t = r->t;
|
||||
r->t += 64;
|
||||
m = r->m;
|
||||
a = r->a;
|
||||
r->m = nm = malloc(r->t*sizeof(uchar));
|
||||
r->a = na = malloc(r->t*sizeof(ulong));
|
||||
memmove(nm, m, t*sizeof(uchar));
|
||||
memmove(na, a, t*sizeof(ulong));
|
||||
free(m);
|
||||
free(a);
|
||||
}
|
||||
|
||||
void
|
||||
dynreloc(Sym *s, long v, int abs)
|
||||
{
|
||||
int i, k, n;
|
||||
uchar *m;
|
||||
ulong *a;
|
||||
Reloc *r;
|
||||
|
||||
if(v&3)
|
||||
diag("bad relocation address");
|
||||
v >>= 2;
|
||||
if(s != S && s->type == SUNDEF)
|
||||
k = abs ? ABSU : RELU;
|
||||
else
|
||||
k = abs ? ABSD : RELD;
|
||||
/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
|
||||
k = modemap[k];
|
||||
r = &rels;
|
||||
n = r->n;
|
||||
if(n >= r->t)
|
||||
grow(r);
|
||||
m = r->m;
|
||||
a = r->a;
|
||||
for(i = n; i > 0; i--){
|
||||
if(v < a[i-1]){ /* happens occasionally for data */
|
||||
m[i] = m[i-1];
|
||||
a[i] = a[i-1];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
m[i] = k;
|
||||
a[i] = v;
|
||||
r->n++;
|
||||
}
|
||||
|
||||
static int
|
||||
sput(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = s;
|
||||
while(*s)
|
||||
cput(*s++);
|
||||
cput(0);
|
||||
return s-p+1;
|
||||
}
|
||||
|
||||
void
|
||||
asmdyn(void)
|
||||
{
|
||||
int i, n, t, c;
|
||||
Sym *s;
|
||||
ulong la, ra, *a;
|
||||
vlong off;
|
||||
uchar *m;
|
||||
Reloc *r;
|
||||
|
||||
cflush();
|
||||
off = seek(cout, 0, 1);
|
||||
lput(0);
|
||||
t = 0;
|
||||
lput(imports);
|
||||
t += 4;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->type == SUNDEF){
|
||||
lput(s->sig);
|
||||
t += 4;
|
||||
t += sput(s->name);
|
||||
}
|
||||
|
||||
la = 0;
|
||||
r = &rels;
|
||||
n = r->n;
|
||||
m = r->m;
|
||||
a = r->a;
|
||||
lput(n);
|
||||
t += 4;
|
||||
for(i = 0; i < n; i++){
|
||||
ra = *a-la;
|
||||
if(*a < la)
|
||||
diag("bad relocation order");
|
||||
if(ra < 256)
|
||||
c = 0;
|
||||
else if(ra < 65536)
|
||||
c = 1;
|
||||
else
|
||||
c = 2;
|
||||
cput((c<<6)|*m++);
|
||||
t++;
|
||||
if(c == 0){
|
||||
cput(ra);
|
||||
t++;
|
||||
}
|
||||
else if(c == 1){
|
||||
wput(ra);
|
||||
t += 2;
|
||||
}
|
||||
else{
|
||||
lput(ra);
|
||||
t += 4;
|
||||
}
|
||||
la = *a++;
|
||||
}
|
||||
|
||||
cflush();
|
||||
seek(cout, off, 0);
|
||||
lput(t);
|
||||
|
||||
if(debug['v']){
|
||||
Bprint(&bso, "import table entries = %d\n", imports);
|
||||
Bprint(&bso, "export table entries = %d\n", exports);
|
||||
}
|
||||
}
|
430
sys/src/cmd/7l/l.h
Normal file
430
sys/src/cmd/7l/l.h
Normal file
|
@ -0,0 +1,430 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../7c/7.out.h"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define LIBNAMELEN 300
|
||||
|
||||
void addlibpath(char*);
|
||||
int fileexists(char*);
|
||||
int find1(long, int);
|
||||
char* findlib(char*);
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Autom Auto;
|
||||
typedef struct Count Count;
|
||||
typedef struct Ieee Ieee;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Mask Mask;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Oprang Oprang;
|
||||
typedef uchar Opcross[32][2][32];
|
||||
|
||||
#define P ((Prog*)0)
|
||||
#define S ((Sym*)0)
|
||||
#define TNAME (curtext&&curtext->from.sym?curtext->from.sym->name:noname)
|
||||
|
||||
struct Adr
|
||||
{
|
||||
union
|
||||
{
|
||||
vlong u0offset;
|
||||
char* u0sval;
|
||||
Ieee* u0ieee;
|
||||
} u0;
|
||||
union
|
||||
{
|
||||
Auto* u1autom;
|
||||
Sym* u1sym;
|
||||
} u1;
|
||||
char type;
|
||||
char reg;
|
||||
char name;
|
||||
char class;
|
||||
};
|
||||
|
||||
#define offset u0.u0offset
|
||||
#define sval u0.u0sval
|
||||
#define ieee u0.u0ieee
|
||||
|
||||
#define autom u1.u1autom
|
||||
#define sym u1.u1sym
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr from3; /* third register operand */
|
||||
Adr to;
|
||||
union
|
||||
{
|
||||
long u0regused;
|
||||
Prog* u0forwd;
|
||||
} u0;
|
||||
Prog* cond;
|
||||
Prog* link;
|
||||
vlong pc;
|
||||
long line;
|
||||
uchar mark;
|
||||
ushort optab;
|
||||
ushort as;
|
||||
uchar reg;
|
||||
};
|
||||
#define regused u0.u0regused
|
||||
#define forwd u0.u0forwd
|
||||
|
||||
struct Sym
|
||||
{
|
||||
char *name;
|
||||
short type;
|
||||
short version;
|
||||
short become;
|
||||
short frame;
|
||||
uchar subtype;
|
||||
ushort file;
|
||||
vlong value;
|
||||
long sig;
|
||||
Sym* link;
|
||||
};
|
||||
|
||||
#define SIGNINTERN (1729*325*1729) /* signature of internal functions such as _div */
|
||||
|
||||
struct Autom
|
||||
{
|
||||
Sym* asym;
|
||||
Auto* link;
|
||||
long aoffset;
|
||||
short type;
|
||||
};
|
||||
|
||||
struct Optab
|
||||
{
|
||||
ushort as;
|
||||
char a1;
|
||||
char a2;
|
||||
char a3;
|
||||
char type;
|
||||
char size;
|
||||
char param;
|
||||
char flag;
|
||||
};
|
||||
struct Oprang
|
||||
{
|
||||
Optab* start;
|
||||
Optab* stop;
|
||||
};
|
||||
struct Mask
|
||||
{
|
||||
uchar s;
|
||||
uchar e;
|
||||
uchar r;
|
||||
uvlong v;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
STEXT = 1,
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
SXREF,
|
||||
SLEAF,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SSTRING,
|
||||
SUNDEF,
|
||||
|
||||
SIMPORT,
|
||||
SEXPORT,
|
||||
|
||||
LFROM = 1<<0,
|
||||
LTO = 1<<1,
|
||||
LPOOL = 1<<2,
|
||||
|
||||
C_NONE = 0,
|
||||
C_REG,
|
||||
C_RSP, /* D_REG or D_SP */
|
||||
C_SHIFT, /* D_SHIFT: shift type, amount, value */
|
||||
C_EXTREG, /* D_EXTREG: reg, ext type, shift */
|
||||
C_FREG,
|
||||
C_SPR,
|
||||
C_COND,
|
||||
|
||||
C_ZCON, /* 0 (matching C_REG, not C_RSP, allowing REGZERO) */
|
||||
C_ADDCON0, /* 12-bit unsigned, unshifted */
|
||||
C_ADDCON, /* 12-bit unsigned, shifted left by 0 or 12 */
|
||||
C_MOVCON, /* generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 */
|
||||
C_BITCON, /* bimm32 */
|
||||
C_ABCON, /* could be C_ADDCON or C_BITCON */
|
||||
C_MBCON, /* could be C_MOVCON or C_BITCON */
|
||||
C_LCON, /* 32-bit constant */
|
||||
C_FCON, /* floating-point constant */
|
||||
C_VCON, /* 64-bit constant */
|
||||
|
||||
C_AACON, /* ADDCON offset in auto constant $a(FP) */
|
||||
C_LACON, /* 32-bit offset in auto constant $a(FP) */
|
||||
|
||||
C_AECON, /* ADDCON offset in extern constant $e(SB) */
|
||||
|
||||
C_SBRA,
|
||||
C_LBRA,
|
||||
|
||||
C_NPAUTO, /* -512 <= x < 0, 0 mod 8 */
|
||||
C_NSAUTO, /* -256 <= x < 0 */
|
||||
C_PSAUTO, /* 0 to 255 */
|
||||
C_PPAUTO, /* 0 to 504, 0 mod 8 */
|
||||
C_UAUTO4K, /* 0 to 4095 */
|
||||
C_UAUTO8K, /* 0 to 8190, 0 mod 2 */
|
||||
C_UAUTO16K, /* 0 to 16380, 0 mod 4 */
|
||||
C_UAUTO32K, /* 0 to 32760, 0 mod 8 */
|
||||
C_UAUTO64K, /* 0 to 65520, 0 mod 16 */
|
||||
C_LAUTO, /* any other 32-bit constant */
|
||||
|
||||
C_SEXT1, /* 0 to 4095, direct */
|
||||
C_SEXT2, /* 0 to 8190 */
|
||||
C_SEXT4, /* 0 to 16380 */
|
||||
C_SEXT8, /* 0 to 32760 */
|
||||
C_SEXT16, /* 0 to 65520 */
|
||||
C_LEXT,
|
||||
|
||||
C_NPOREG, /* mirror NPAUTO etc, except for ZOREG */
|
||||
C_NSOREG,
|
||||
C_ZOREG,
|
||||
C_PSOREG,
|
||||
C_PPOREG,
|
||||
C_UOREG4K,
|
||||
C_UOREG8K,
|
||||
C_UOREG16K,
|
||||
C_UOREG32K,
|
||||
C_UOREG64K,
|
||||
C_LOREG,
|
||||
|
||||
C_ADDR, /* relocatable address for dynamic loading */
|
||||
C_ROFF, /* register offset (inc register extended) */
|
||||
C_XPOST,
|
||||
C_XPRE,
|
||||
|
||||
C_VREG,
|
||||
|
||||
C_GOK,
|
||||
C_NCLASS, /* must be last */
|
||||
|
||||
/* mark flags */
|
||||
FOLL = 1<<0,
|
||||
LABEL = 1<<1,
|
||||
LEAF = 1<<2,
|
||||
FLOAT = 1<<3,
|
||||
BRANCH = 1<<4,
|
||||
LOAD = 1<<5,
|
||||
SYNC = 1<<6,
|
||||
NOSCHED = 1<<7,
|
||||
|
||||
MINSIZ = 64,
|
||||
|
||||
Roffset = 22, /* no. bits for offset in relocation address */
|
||||
Rindex = 10, /* no. bits for index in relocation address */
|
||||
|
||||
STACKALIGN = 16, /* alignment of stack */
|
||||
PCSZ= 8, /* size of PC */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
STRINGSZ = 200,
|
||||
NHASH = 10007,
|
||||
NHUNK = 100000,
|
||||
MAXIO = 8192,
|
||||
MAXHIST = 20, /* limit of path elements for history symbols */
|
||||
};
|
||||
|
||||
EXTERN union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uchar obuf[MAXIO]; /* output buffer */
|
||||
uchar ibuf[MAXIO]; /* input buffer */
|
||||
} u;
|
||||
char dbuf[1];
|
||||
} buf;
|
||||
|
||||
#define cbuf u.obuf
|
||||
#define xbuf u.ibuf
|
||||
|
||||
EXTERN long HEADR; /* length of header */
|
||||
EXTERN int HEADTYPE; /* type of header */
|
||||
EXTERN long INITDAT; /* data location */
|
||||
EXTERN long INITRND; /* data round above text location */
|
||||
EXTERN long INITTEXT; /* text location */
|
||||
EXTERN long INITTEXTP; /* text location (physical) */
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN long autosize;
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN long bsssize;
|
||||
EXTERN int cbc;
|
||||
EXTERN uchar* cbp;
|
||||
EXTERN int cout;
|
||||
EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Prog* curtext;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN long datsize;
|
||||
EXTERN char debug[128];
|
||||
EXTERN Prog* etextp;
|
||||
EXTERN Prog* firstp;
|
||||
|
||||
EXTERN char fnuxi4[4];
|
||||
EXTERN char fnuxi8[8];
|
||||
EXTERN char inuxi1[1];
|
||||
EXTERN char inuxi2[2];
|
||||
EXTERN char inuxi4[4];
|
||||
EXTERN uchar inuxi8[8];
|
||||
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN Sym* histfrog[MAXHIST];
|
||||
EXTERN int histfrogp;
|
||||
EXTERN int histgen;
|
||||
EXTERN char* hunk;
|
||||
|
||||
EXTERN char* library[50];
|
||||
EXTERN char* libraryobj[50];
|
||||
EXTERN int libraryp;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long lcsize;
|
||||
EXTERN char literal[32];
|
||||
EXTERN int nerrors;
|
||||
EXTERN long nhunk;
|
||||
EXTERN char* noname;
|
||||
EXTERN vlong instoffset;
|
||||
EXTERN Opcross opcross[8];
|
||||
EXTERN char* outfile;
|
||||
EXTERN vlong pc;
|
||||
EXTERN uchar repop[ALAST];
|
||||
EXTERN long symsize;
|
||||
EXTERN Prog* textp;
|
||||
EXTERN vlong textsize;
|
||||
EXTERN long thunk;
|
||||
EXTERN int version;
|
||||
EXTERN char xcmp[C_NCLASS][C_NCLASS];
|
||||
EXTERN int xrefresolv;
|
||||
EXTERN Prog zprg;
|
||||
EXTERN int dtype;
|
||||
|
||||
EXTERN int doexp, dlm;
|
||||
EXTERN int imports, nimports;
|
||||
EXTERN int exports, nexports;
|
||||
EXTERN char* EXPTAB;
|
||||
EXTERN Prog undefp;
|
||||
|
||||
#define UP (&undefp)
|
||||
|
||||
extern char* anames[];
|
||||
extern char* cnames[];
|
||||
extern Optab optab[];
|
||||
|
||||
EXTERN Prog* blitrl;
|
||||
EXTERN Prog* elitrl;
|
||||
|
||||
#pragma varargck argpos diag 1
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "A" uint
|
||||
#pragma varargck type "C" int
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "N" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
|
||||
int Aconv(Fmt*);
|
||||
int Cconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Nconv(Fmt*);
|
||||
int Pconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int aclass(Adr*);
|
||||
void addpool(Prog*, Adr*);
|
||||
vlong atolwhex(char*);
|
||||
void asmb(void);
|
||||
void asmdyn(void);
|
||||
void asmlc(void);
|
||||
void asmout(Prog*, Optab*);
|
||||
void asmsym(void);
|
||||
Prog* brchain(Prog*);
|
||||
Prog* brloop(Prog*);
|
||||
void buildop(void);
|
||||
void buildrep(int, int);
|
||||
void cflush(void);
|
||||
void ckoff(Sym*, long);
|
||||
int chipfloat(Ieee*);
|
||||
int cmp(int, int);
|
||||
int compound(Prog*);
|
||||
void cput(int);
|
||||
void datblk(long, long, int);
|
||||
void diag(char*, ...);
|
||||
void dodata(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
void dynreloc(Sym*, long, int);
|
||||
vlong entryvalue(void);
|
||||
void errorexit(void);
|
||||
void export(void);
|
||||
void follow(void);
|
||||
void gethunk(void);
|
||||
void histtoauto(void);
|
||||
void* halloc(usize);
|
||||
int isnop(Prog*);
|
||||
double ieeedtod(Ieee*);
|
||||
long ieeedtof(Ieee*);
|
||||
void import(void);
|
||||
void ldobj(int, long, char*);
|
||||
void listinit(void);
|
||||
void llput(vlong);
|
||||
void llputl(vlong);
|
||||
void loadlib(void);
|
||||
Sym* lookup(char*, int);
|
||||
void lput(long);
|
||||
void lputl(long);
|
||||
void mkfwd(void);
|
||||
int movcon(vlong);
|
||||
void* mysbrk(ulong);
|
||||
void names(void);
|
||||
void nocache(Prog*);
|
||||
void nuxiinit(void);
|
||||
void objfile(char*);
|
||||
vlong offsetshift(vlong, int);
|
||||
Optab* oplook(Prog*);
|
||||
void patch(void);
|
||||
int pseudo(Prog*);
|
||||
void prasm(Prog*);
|
||||
Prog* prg(void);
|
||||
void putsymb(char*, int, vlong, int);
|
||||
void readundefs(char*, int);
|
||||
long regoff(Adr*);
|
||||
int relinv(int);
|
||||
vlong rnd(vlong, long);
|
||||
void span(void);
|
||||
void undef(void);
|
||||
void wput(long);
|
||||
void wputl(long);
|
||||
void noops(void);
|
||||
Mask* findmask(uvlong);
|
||||
void xdefine(char*, int, long);
|
||||
void xfol(Prog*);
|
||||
void zerosig(char*);
|
||||
|
||||
|
||||
#pragma varargck type "R" int
|
||||
|
||||
/* for ../ld */
|
||||
#define isbranch(a) ((a) == AB)
|
||||
#define iscall(a) ((a) == ABL)
|
||||
#define isreturn(a) ((a) == ARETURN || (a) == ARET || (a) == AERET)
|
||||
#define branchop() AB
|
||||
#define canfollow(a) ((a) != ATEXT && (a) != ABCASE)
|
362
sys/src/cmd/7l/list.c
Normal file
362
sys/src/cmd/7l/list.c
Normal file
|
@ -0,0 +1,362 @@
|
|||
#include "l.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('D', Dconv);
|
||||
fmtinstall('P', Pconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('N', Nconv);
|
||||
fmtinstall('R', Rconv);
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ], *s;
|
||||
Prog *p;
|
||||
int a;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
curp = p;
|
||||
a = p->as;
|
||||
switch(a) {
|
||||
default:
|
||||
s = str;
|
||||
s += sprint(s, "(%ld)", p->line);
|
||||
if(p->reg == NREG && p->from3.type == D_NONE)
|
||||
sprint(s, " %A %D,%D",
|
||||
a, &p->from, &p->to);
|
||||
else if(p->from.type != D_FREG){
|
||||
s += sprint(s, " %A %D", a, &p->from);
|
||||
if(p->from3.type != D_NONE)
|
||||
s += sprint(s, ",%D", &p->from3);
|
||||
if(p->reg != NREG)
|
||||
s += sprint(s, ",R%d", p->reg);
|
||||
sprint(s, ",%D", &p->to);
|
||||
}else
|
||||
sprint(s, " %A %D,F%d,%D",
|
||||
a, &p->from, p->reg, &p->to);
|
||||
break;
|
||||
|
||||
case ADATA:
|
||||
case AINIT:
|
||||
case ADYNT:
|
||||
sprint(str, "(%ld) %A %D/%d,%D",
|
||||
p->line, a, &p->from, p->reg, &p->to);
|
||||
break;
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
char *s;
|
||||
int a;
|
||||
|
||||
a = va_arg(fp->args, int);
|
||||
s = "???";
|
||||
if(a >= AXXX && a < ALAST && anames[a])
|
||||
s = anames[a];
|
||||
return fmtstrcpy(fp, s);
|
||||
}
|
||||
|
||||
char* strcond[16] =
|
||||
{
|
||||
"EQ",
|
||||
"NE",
|
||||
"HS",
|
||||
"LO",
|
||||
"MI",
|
||||
"PL",
|
||||
"VS",
|
||||
"VC",
|
||||
"HI",
|
||||
"LS",
|
||||
"GE",
|
||||
"LT",
|
||||
"GT",
|
||||
"LE",
|
||||
"AL",
|
||||
"NV"
|
||||
};
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
char *op;
|
||||
Adr *a;
|
||||
long v;
|
||||
static char *extop[] = {".UB", ".UH", ".UW", ".UX", ".SB", ".SH", ".SW", ".SX"};
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
switch(a->type) {
|
||||
|
||||
default:
|
||||
sprint(str, "GOK-type(%d)", a->type);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
if(a->name != D_NONE || a->reg != NREG || a->sym != S)
|
||||
sprint(str, "%N(R%d)(NONE)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
if(a->reg == NREG || a->reg == REGZERO)
|
||||
sprint(str, "$%N", a);
|
||||
else
|
||||
sprint(str, "$%N(R%d)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>22) & 3) << 1);
|
||||
sprint(str, "R%ld%c%c%ld", (v>>16)&0x1F, op[0], op[1], (v>>10)&0x3F);
|
||||
if(a->reg != NREG)
|
||||
sprint(str+strlen(str), "(R%d)", a->reg);
|
||||
break;
|
||||
|
||||
case D_OCONST:
|
||||
sprint(str, "$*$%N", a);
|
||||
if(a->reg != NREG)
|
||||
sprint(str, "%N(R%d)(CONST)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_OREG:
|
||||
if(a->reg != NREG)
|
||||
sprint(str, "%N(R%d)", a, a->reg);
|
||||
else
|
||||
sprint(str, "%N", a);
|
||||
break;
|
||||
|
||||
case D_XPRE:
|
||||
if(a->reg != NREG)
|
||||
sprint(str, "%N(R%d)!", a, a->reg);
|
||||
else
|
||||
sprint(str, "%N!", a);
|
||||
break;
|
||||
|
||||
case D_XPOST:
|
||||
if(a->reg != NREG)
|
||||
sprint(str, "(R%d)%N!", a->reg, a);
|
||||
else
|
||||
sprint(str, "%N!", a);
|
||||
break;
|
||||
|
||||
case D_EXTREG:
|
||||
v = a->offset;
|
||||
if(v & (7<<10))
|
||||
snprint(str, sizeof(str), "R%ld%s<<%ld", (v>>16)&31, extop[(v>>13)&7], (v>>10)&7);
|
||||
else
|
||||
snprint(str, sizeof(str), "R%ld%s", (v>>16)&31, extop[(v>>13)&7]);
|
||||
break;
|
||||
|
||||
case D_ROFF:
|
||||
v = a->offset;
|
||||
if(v & (1<<16))
|
||||
snprint(str, sizeof(str), "(R%d)[R%ld%s]", a->reg, v&31, extop[(v>>8)&7]);
|
||||
else
|
||||
snprint(str, sizeof(str), "(R%d)(R%ld%s)", a->reg, v&31, extop[(v>>8)&7]);
|
||||
break;
|
||||
|
||||
case D_REG:
|
||||
sprint(str, "R%d", a->reg);
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
sprint(str, "%N(R%d)(REG)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_SP:
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
sprint(str, "%N(R%d)(REG)", a, a->reg);
|
||||
else
|
||||
strcpy(str, "SP");
|
||||
break;
|
||||
|
||||
case D_COND:
|
||||
strcpy(str, strcond[a->reg & 0xF]);
|
||||
break;
|
||||
|
||||
case D_FREG:
|
||||
sprint(str, "F%d", a->reg);
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
sprint(str, "%N(R%d)(REG)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_SPR:
|
||||
switch((ulong)a->offset){
|
||||
case D_FPSR:
|
||||
sprint(str, "FPSR");
|
||||
break;
|
||||
case D_FPCR:
|
||||
sprint(str, "FPCR");
|
||||
break;
|
||||
case D_NZCV:
|
||||
sprint(str, "NZCV");
|
||||
break;
|
||||
default:
|
||||
sprint(str, "SPR(%#llux)", a->offset);
|
||||
break;
|
||||
}
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
sprint(str, "%N(SPR%lld)(REG)", a, a->offset);
|
||||
break;
|
||||
|
||||
case D_BRANCH: /* botch */
|
||||
if(curp->cond != P) {
|
||||
v = curp->cond->pc;
|
||||
if(a->sym != S)
|
||||
sprint(str, "%s+%#.5lux(BRANCH)", a->sym->name, v);
|
||||
else
|
||||
sprint(str, "%.5lux(BRANCH)", v);
|
||||
} else
|
||||
if(a->sym != S)
|
||||
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%lld(APC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$%e", ieeedtod(a->ieee));
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->sval);
|
||||
break;
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Nconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Adr *a;
|
||||
Sym *s;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
s = a->sym;
|
||||
switch(a->name) {
|
||||
default:
|
||||
sprint(str, "GOK-name(%d)", a->name);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
sprint(str, "%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
if(s == S)
|
||||
sprint(str, "%lld(SB)", a->offset);
|
||||
else
|
||||
sprint(str, "%s+%lld(SB)", s->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
if(s == S)
|
||||
sprint(str, "<>+%lld(SB)", a->offset);
|
||||
else
|
||||
sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
if(s == S)
|
||||
sprint(str, "%lld(SP)", a->offset);
|
||||
else
|
||||
sprint(str, "%s-%lld(SP)", s->name, -a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(s == S)
|
||||
sprint(str, "%lld(FP)", a->offset);
|
||||
else
|
||||
sprint(str, "%s+%lld(FP)", s->name, a->offset);
|
||||
break;
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char *s;
|
||||
int a;
|
||||
|
||||
a = va_arg(fp->args, int);
|
||||
s = "C_??";
|
||||
if(a >= C_NONE && a <= C_NCLASS)
|
||||
s = cnames[a];
|
||||
return fmtstrcpy(fp, s);
|
||||
}
|
||||
|
||||
void
|
||||
prasm(Prog *p)
|
||||
{
|
||||
print("%P\n", p);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[STRINGSZ], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sizeof(long); i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9' ||
|
||||
c == ' ' || c == '%') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
void
|
||||
diag(char *fmt, ...)
|
||||
{
|
||||
char buf[STRINGSZ], *tn;
|
||||
va_list arg;
|
||||
|
||||
tn = "??none??";
|
||||
if(curtext != P && curtext->from.sym != S)
|
||||
tn = curtext->from.sym->name;
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||
va_end(arg);
|
||||
print("%s: %s\n", tn, buf);
|
||||
|
||||
nerrors++;
|
||||
if(nerrors > 10) {
|
||||
print("too many errors\n");
|
||||
errorexit();
|
||||
}
|
||||
}
|
17
sys/src/cmd/7l/mkcname
Normal file
17
sys/src/cmd/7l/mkcname
Normal file
|
@ -0,0 +1,17 @@
|
|||
ed - l.h <<'!'
|
||||
v/^ C_/d
|
||||
g/^ C_NCLASS/s//&,/
|
||||
g/[ ]*=.*,/s//,/
|
||||
v/,/p
|
||||
,s/^ C_/ "/
|
||||
,s/,.*$/",/
|
||||
1i
|
||||
char *cnames[] =
|
||||
{
|
||||
.
|
||||
,a
|
||||
};
|
||||
.
|
||||
w cnam.c
|
||||
Q
|
||||
!
|
37
sys/src/cmd/7l/mkfile
Normal file
37
sys/src/cmd/7l/mkfile
Normal file
|
@ -0,0 +1,37 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=7l
|
||||
OFILES=\
|
||||
asm.$O\
|
||||
asmout.$O\
|
||||
enam.$O\
|
||||
bits.$O\
|
||||
cnam.$O\
|
||||
compat.$O\
|
||||
dyn.$O\
|
||||
list.$O\
|
||||
noop.$O\
|
||||
obj.$O\
|
||||
optab.$O\
|
||||
span.$O\
|
||||
pass.$O\
|
||||
mod.$O\
|
||||
|
||||
HFILES=\
|
||||
l.h\
|
||||
../7c/7.out.h\
|
||||
|
||||
BIN=/$objtype/bin
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
../7c/enam.c: ../7c/7.out.h
|
||||
@ { cd ../7c; mk enam.c }
|
||||
|
||||
cnam.c: l.h mkcname
|
||||
rc mkcname
|
||||
|
||||
enam.$O: ../7c/enam.c
|
||||
$CC $CFLAGS ../7c/enam.c
|
||||
|
||||
x:V: $O.out
|
||||
$O.out -la -o/dev/null x.7
|
203
sys/src/cmd/7l/mod.c
Normal file
203
sys/src/cmd/7l/mod.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
#include "l.h"
|
||||
|
||||
void
|
||||
readundefs(char *f, int t)
|
||||
{
|
||||
int i, n;
|
||||
Sym *s;
|
||||
Biobuf *b;
|
||||
char *l, buf[256], *fields[64];
|
||||
|
||||
if(f == nil)
|
||||
return;
|
||||
b = Bopen(f, OREAD);
|
||||
if(b == nil){
|
||||
diag("could not open %s: %r", f);
|
||||
errorexit();
|
||||
}
|
||||
while((l = Brdline(b, '\n')) != nil){
|
||||
n = Blinelen(b);
|
||||
if(n >= sizeof(buf)){
|
||||
diag("%s: line too long", f);
|
||||
errorexit();
|
||||
}
|
||||
memmove(buf, l, n);
|
||||
buf[n-1] = '\0';
|
||||
n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
|
||||
if(n == nelem(fields)){
|
||||
diag("%s: bad format", f);
|
||||
errorexit();
|
||||
}
|
||||
for(i = 0; i < n; i++){
|
||||
s = lookup(fields[i], 0);
|
||||
s->type = SXREF;
|
||||
s->subtype = t;
|
||||
if(t == SIMPORT)
|
||||
nimports++;
|
||||
else
|
||||
nexports++;
|
||||
}
|
||||
}
|
||||
Bterm(b);
|
||||
}
|
||||
|
||||
void
|
||||
undefsym(Sym *s)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = imports;
|
||||
if(s->value != 0)
|
||||
diag("value != 0 on SXREF");
|
||||
if(n >= 1<<Rindex)
|
||||
diag("import index %d out of range", n);
|
||||
s->value = n<<Roffset;
|
||||
s->type = SUNDEF;
|
||||
imports++;
|
||||
}
|
||||
|
||||
void
|
||||
zerosig(char *sp)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
s = lookup(sp, 0);
|
||||
s->sig = 0;
|
||||
}
|
||||
|
||||
void
|
||||
import(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
|
||||
undefsym(s);
|
||||
Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, (vlong)s->value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ckoff(Sym *s, long v)
|
||||
{
|
||||
if(v < 0 || v >= 1<<Roffset)
|
||||
diag("relocation offset %ld for %s out of range", v, s->name);
|
||||
}
|
||||
|
||||
static Prog*
|
||||
newdata(Sym *s, int o, int w, int t)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = prg();
|
||||
p->link = datap;
|
||||
datap = p;
|
||||
p->as = ADATA;
|
||||
p->reg = w;
|
||||
p->from.type = D_OREG;
|
||||
p->from.name = t;
|
||||
p->from.sym = s;
|
||||
p->from.offset = o;
|
||||
p->to.type = D_CONST;
|
||||
p->to.name = D_NONE;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
export(void)
|
||||
{
|
||||
int i, j, n, off, nb, sv, ne;
|
||||
Sym *s, *et, *str, **esyms;
|
||||
Prog *p;
|
||||
char buf[NSNAME], *t;
|
||||
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
n++;
|
||||
esyms = malloc(n*sizeof(Sym*));
|
||||
ne = n;
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
esyms[n++] = s;
|
||||
for(i = 0; i < ne-1; i++)
|
||||
for(j = i+1; j < ne; j++)
|
||||
if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
|
||||
s = esyms[i];
|
||||
esyms[i] = esyms[j];
|
||||
esyms[j] = s;
|
||||
}
|
||||
|
||||
nb = 0;
|
||||
off = 0;
|
||||
et = lookup(EXPTAB, 0);
|
||||
if(et->type != 0 && et->type != SXREF)
|
||||
diag("%s already defined", EXPTAB);
|
||||
et->type = SDATA;
|
||||
str = lookup(".string", 0);
|
||||
if(str->type == 0)
|
||||
str->type = SDATA;
|
||||
sv = str->value;
|
||||
for(i = 0; i < ne; i++){
|
||||
s = esyms[i];
|
||||
Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
|
||||
|
||||
/* signature */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.offset = s->sig;
|
||||
|
||||
/* address */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.name = D_EXTERN;
|
||||
p->to.sym = s;
|
||||
|
||||
/* string */
|
||||
t = s->name;
|
||||
n = strlen(t)+1;
|
||||
for(;;){
|
||||
buf[nb++] = *t;
|
||||
sv++;
|
||||
if(nb >= NSNAME){
|
||||
p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
p->to.sval = malloc(NSNAME);
|
||||
memmove(p->to.sval, buf, NSNAME);
|
||||
nb = 0;
|
||||
}
|
||||
if(*t++ == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* name */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.name = D_STATIC;
|
||||
p->to.sym = str;
|
||||
p->to.offset = sv-n;
|
||||
}
|
||||
|
||||
if(nb > 0){
|
||||
p = newdata(str, sv-nb, nb, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
p->to.sval = malloc(NSNAME);
|
||||
memmove(p->to.sval, buf, nb);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
}
|
||||
et->value = off;
|
||||
if(sv == 0)
|
||||
sv = 1;
|
||||
str->value = sv;
|
||||
exports = ne;
|
||||
free(esyms);
|
||||
}
|
324
sys/src/cmd/7l/noop.c
Normal file
324
sys/src/cmd/7l/noop.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
#include "l.h"
|
||||
|
||||
void
|
||||
noops(void)
|
||||
{
|
||||
Prog *p, *q, *q1;
|
||||
int o, aoffset, curframe, curbecome, maxbecome;
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
* become sizes
|
||||
* frame sizes
|
||||
* strip NOPs
|
||||
* expand RET
|
||||
* expand BECOME pseudo
|
||||
*/
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f noops\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
maxbecome = 0;
|
||||
curtext = 0;
|
||||
|
||||
q = P;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
|
||||
/* find out how much arg space is used in this TEXT */
|
||||
if(p->to.type == D_OREG && p->to.reg == REGSP)
|
||||
if(p->to.offset > curframe)
|
||||
curframe = p->to.offset;
|
||||
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
|
||||
p->mark |= LEAF;
|
||||
curtext = p;
|
||||
break;
|
||||
|
||||
case ARETURN:
|
||||
/* special form of RETURN is BECOME */
|
||||
if(p->from.type == D_CONST)
|
||||
if(p->from.offset > curbecome)
|
||||
curbecome = p->from.offset;
|
||||
break;
|
||||
|
||||
case ANOP:
|
||||
q1 = p->link;
|
||||
q->link = q1; /* q is non-nop */
|
||||
q1->mark |= p->mark;
|
||||
continue;
|
||||
|
||||
case ABL:
|
||||
if(curtext != P)
|
||||
curtext->mark &= ~LEAF;
|
||||
|
||||
case ACBNZ:
|
||||
case ACBZ:
|
||||
case ACBNZW:
|
||||
case ACBZW:
|
||||
case ATBZ:
|
||||
case ATBNZ:
|
||||
|
||||
case ABCASE:
|
||||
case AB:
|
||||
|
||||
case ABEQ:
|
||||
case ABNE:
|
||||
case ABCS:
|
||||
case ABHS:
|
||||
case ABCC:
|
||||
case ABLO:
|
||||
case ABMI:
|
||||
case ABPL:
|
||||
case ABVS:
|
||||
case ABVC:
|
||||
case ABHI:
|
||||
case ABLS:
|
||||
case ABGE:
|
||||
case ABLT:
|
||||
case ABGT:
|
||||
case ABLE:
|
||||
|
||||
case AADR: /* strange */
|
||||
case AADRP:
|
||||
|
||||
q1 = p->cond;
|
||||
if(q1 != P) {
|
||||
while(q1->as == ANOP) {
|
||||
q1 = q1->link;
|
||||
p->cond = q1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
q = p;
|
||||
}
|
||||
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
|
||||
if(debug['b'])
|
||||
print("max become = %d\n", maxbecome);
|
||||
xdefine("ALEFbecome", STEXT, maxbecome);
|
||||
|
||||
curtext = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
curtext = p;
|
||||
break;
|
||||
case ABL:
|
||||
if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
|
||||
o = maxbecome - curtext->from.sym->frame;
|
||||
if(o <= 0)
|
||||
break;
|
||||
/* calling a become or calling a variable */
|
||||
if(p->to.sym == S || p->to.sym->become) {
|
||||
curtext->to.offset += o;
|
||||
if(debug['b']) {
|
||||
curp = p;
|
||||
print("%D calling %D increase %d\n",
|
||||
&curtext->from, &p->to, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
o = p->as;
|
||||
switch(o) {
|
||||
case ATEXT:
|
||||
curtext = p;
|
||||
if(p->to.offset < 0)
|
||||
autosize = 0;
|
||||
else
|
||||
autosize = p->to.offset + PCSZ;
|
||||
if((curtext->mark & LEAF) && autosize <= PCSZ)
|
||||
autosize = 0;
|
||||
else if(autosize & (STACKALIGN-1))
|
||||
autosize += STACKALIGN - (autosize&(STACKALIGN-1));
|
||||
p->to.offset = autosize - PCSZ;
|
||||
|
||||
if(autosize == 0 && !(curtext->mark & LEAF)) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "save suppressed in: %s\n",
|
||||
curtext->from.sym->name);
|
||||
Bflush(&bso);
|
||||
curtext->mark |= LEAF;
|
||||
}
|
||||
|
||||
aoffset = autosize;
|
||||
if(aoffset > 0xF0)
|
||||
aoffset = 0xF0;
|
||||
|
||||
if(curtext->mark & LEAF) {
|
||||
if(curtext->from.sym)
|
||||
curtext->from.sym->type = SLEAF;
|
||||
if(autosize == 0)
|
||||
break;
|
||||
aoffset = 0;
|
||||
}
|
||||
|
||||
q = p;
|
||||
if(autosize > aoffset){
|
||||
q = prg();
|
||||
q->as = ASUB;
|
||||
q->line = p->line;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = autosize - aoffset;
|
||||
q->to.type = D_REG;
|
||||
q->to.reg = REGSP;
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
|
||||
if(curtext->mark & LEAF)
|
||||
break;
|
||||
}
|
||||
|
||||
q1 = prg();
|
||||
q1->as = AMOV;
|
||||
q1->line = p->line;
|
||||
q1->from.type = D_REG;
|
||||
q1->from.reg = REGLINK;
|
||||
q1->to.type = D_XPRE;
|
||||
q1->to.offset = -aoffset;
|
||||
q1->to.reg = REGSP;
|
||||
|
||||
q1->link = q->link;
|
||||
q->link = q1;
|
||||
break;
|
||||
|
||||
case ARETURN:
|
||||
nocache(p);
|
||||
if(p->from.type == D_CONST)
|
||||
goto become;
|
||||
if(curtext->mark & LEAF) {
|
||||
if(autosize != 0){
|
||||
p->as = AADD;
|
||||
p->from.type = D_CONST;
|
||||
p->from.offset = autosize;
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGSP;
|
||||
}
|
||||
}else{
|
||||
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
|
||||
aoffset = autosize;
|
||||
if(aoffset > 0xF0)
|
||||
aoffset = 0xF0;
|
||||
|
||||
p->as = AMOV;
|
||||
p->from.type = D_XPOST;
|
||||
p->from.offset = aoffset;
|
||||
p->from.reg = REGSP;
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGLINK;
|
||||
|
||||
if(autosize > aoffset) {
|
||||
q = prg();
|
||||
q->as = AADD;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = autosize - aoffset;
|
||||
q->to.type = D_REG;
|
||||
q->to.reg = REGSP;
|
||||
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->as != ARETURN) {
|
||||
q = prg();
|
||||
q->line = p->line;
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
p = q;
|
||||
}
|
||||
|
||||
p->as = ARET;
|
||||
p->line = p->line;
|
||||
p->to.type = D_OREG;
|
||||
p->to.offset = 0;
|
||||
p->to.reg = REGLINK;
|
||||
|
||||
break;
|
||||
|
||||
become:
|
||||
if(curtext->mark & LEAF) {
|
||||
|
||||
if(!autosize) {
|
||||
p->as = AB;
|
||||
p->from = zprg.from;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef optimise_time
|
||||
q = prg();
|
||||
q->line = p->line;
|
||||
q->as = AB;
|
||||
q->from = zprg.from;
|
||||
q->to = p->to;
|
||||
q->cond = p->cond;
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
|
||||
p->as = AADD;
|
||||
p->from = zprg.from;
|
||||
p->from.type = D_CONST;
|
||||
p->from.offset = autosize;
|
||||
p->to = zprg.to;
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGSP;
|
||||
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
q = prg();
|
||||
q->line = p->line;
|
||||
q->as = AB;
|
||||
q->from = zprg.from;
|
||||
q->to = p->to;
|
||||
q->cond = p->cond;
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
|
||||
p->as = AMOV;
|
||||
p->from = zprg.from;
|
||||
p->from.type = D_XPRE;
|
||||
p->from.offset = -autosize;
|
||||
p->from.reg = REGSP;
|
||||
p->to = zprg.to;
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGLINK;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nocache(Prog *p)
|
||||
{
|
||||
p->optab = 0;
|
||||
p->from.class = 0;
|
||||
p->to.class = 0;
|
||||
}
|
1502
sys/src/cmd/7l/obj.c
Normal file
1502
sys/src/cmd/7l/obj.c
Normal file
File diff suppressed because it is too large
Load diff
388
sys/src/cmd/7l/optab.c
Normal file
388
sys/src/cmd/7l/optab.c
Normal file
|
@ -0,0 +1,388 @@
|
|||
#include "l.h"
|
||||
|
||||
Optab optab[] =
|
||||
{
|
||||
{ ATEXT, C_LEXT, C_NONE, C_LCON, 0, 0, 0 },
|
||||
{ ATEXT, C_LEXT, C_REG, C_LCON, 0, 0, 0 },
|
||||
{ ATEXT, C_ADDR, C_NONE, C_LCON, 0, 0, 0 },
|
||||
{ ATEXT, C_ADDR, C_REG, C_LCON, 0, 0, 0 },
|
||||
|
||||
/* arithmetic operations */
|
||||
{ AADD, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
{ AADD, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
{ AADC, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
{ AADC, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
{ ANEG, C_REG, C_NONE, C_REG, 25, 4, 0 },
|
||||
{ ANGC, C_REG, C_NONE, C_REG, 17, 4, 0 },
|
||||
{ ACMP, C_REG, C_RSP, C_NONE, 1, 4, 0 },
|
||||
|
||||
{ AADD, C_ADDCON, C_RSP, C_RSP, 2, 4, 0 },
|
||||
{ AADD, C_ADDCON, C_NONE, C_RSP, 2, 4, 0 },
|
||||
{ ACMP, C_ADDCON, C_RSP, C_NONE, 2, 4, 0 },
|
||||
|
||||
{ AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM },
|
||||
{ AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM },
|
||||
{ ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM },
|
||||
|
||||
{ AADD, C_SHIFT,C_REG, C_REG, 3, 4, 0 },
|
||||
{ AADD, C_SHIFT,C_NONE, C_REG, 3, 4, 0 },
|
||||
{ AMVN, C_SHIFT,C_NONE, C_REG, 3, 4, 0 },
|
||||
{ ACMP, C_SHIFT,C_REG, C_NONE, 3, 4, 0 },
|
||||
{ ANEG, C_SHIFT,C_NONE, C_REG, 26, 4, 0 },
|
||||
|
||||
{ AADD, C_REG, C_RSP, C_RSP, 27, 4, 0 },
|
||||
{ AADD, C_REG, C_NONE, C_RSP, 27, 4, 0 },
|
||||
{ AADD, C_EXTREG,C_RSP, C_RSP, 27, 4, 0 },
|
||||
{ AADD, C_EXTREG,C_NONE, C_RSP, 27, 4, 0 },
|
||||
{ AMVN, C_EXTREG,C_NONE, C_RSP, 27, 4, 0 },
|
||||
{ ACMP, C_EXTREG,C_RSP, C_NONE, 27, 4, 0 },
|
||||
|
||||
{ AADD, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
{ AADD, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
|
||||
/* logical operations */
|
||||
{ AAND, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
{ AAND, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
{ ABIC, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
{ ABIC, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
|
||||
{ AAND, C_BITCON, C_REG, C_REG, 53, 4, 0 },
|
||||
{ AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0 },
|
||||
{ ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0 },
|
||||
{ ABIC, C_BITCON, C_NONE, C_REG, 53, 4, 0 },
|
||||
|
||||
{ AAND, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM },
|
||||
{ AAND, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM },
|
||||
{ ABIC, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM },
|
||||
{ ABIC, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM },
|
||||
|
||||
{ AAND, C_SHIFT,C_REG, C_REG, 3, 4, 0 },
|
||||
{ AAND, C_SHIFT,C_NONE, C_REG, 3, 4, 0 },
|
||||
{ ABIC, C_SHIFT,C_REG, C_REG, 3, 4, 0 },
|
||||
{ ABIC, C_SHIFT,C_NONE, C_REG, 3, 4, 0 },
|
||||
|
||||
{ AMOV, C_RSP, C_NONE, C_RSP, 24, 4, 0 },
|
||||
{ AMVN, C_REG, C_NONE, C_REG, 24, 4, 0 },
|
||||
{ AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0 },
|
||||
{ AMOVBU, C_REG, C_NONE, C_REG, 45, 4, 0 },
|
||||
{ AMOVH, C_REG, C_NONE, C_REG, 45, 4, 0 }, /* also MOVHU */
|
||||
{ AMOVW, C_REG, C_NONE, C_REG, 45, 4, 0 }, /* also MOVWU */
|
||||
/* TO DO: MVN C_SHIFT */
|
||||
|
||||
/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
|
||||
{ AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0 },
|
||||
{ AMOV, C_MOVCON, C_NONE, C_REG, 32, 4, 0 },
|
||||
// { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 },
|
||||
// { AMOV, C_ADDCON, C_NONE, C_REG, 2, 4, 0 },
|
||||
// { AMOVW, C_BITCON, C_NONE, C_REG, 53, 4, 0 },
|
||||
// { AMOV, C_BITCON, C_NONE, C_REG, 53, 4, 0 },
|
||||
|
||||
{ AMOVK, C_LCON, C_NONE, C_REG, 33, 4, 0 },
|
||||
|
||||
{ AMOV, C_AECON,C_NONE, C_REG, 4, 4, REGSB },
|
||||
{ AMOV, C_AACON,C_NONE, C_REG, 4, 4, REGSP },
|
||||
|
||||
{ ASDIV, C_REG, C_NONE, C_REG, 1, 4, 0 },
|
||||
{ ASDIV, C_REG, C_REG, C_REG, 1, 4, 0 },
|
||||
|
||||
{ AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0 },
|
||||
{ ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0 },
|
||||
|
||||
{ AB, C_NONE, C_NONE, C_ZOREG, 6, 4, 0 },
|
||||
{ ABL, C_NONE, C_NONE, C_ZOREG, 6, 4, 0 },
|
||||
{ ARET, C_NONE, C_NONE, C_REG, 6, 4, 0 },
|
||||
{ ARET, C_NONE, C_NONE, C_ZOREG, 6, 4, 0 },
|
||||
|
||||
{ AADRP, C_SBRA, C_NONE, C_REG, 60, 4, 0 },
|
||||
{ AADR, C_SBRA, C_NONE, C_REG, 61, 4, 0 },
|
||||
|
||||
{ ABFM, C_LCON, C_REG, C_REG, 42, 4, 0 },
|
||||
{ ABFI, C_LCON, C_REG, C_REG, 43, 4, 0 },
|
||||
|
||||
{ AEXTR, C_LCON, C_REG, C_REG, 44, 4, 0 },
|
||||
{ ASXTB, C_REG, C_NONE, C_REG, 45, 4, 0 },
|
||||
{ ACLS, C_REG, C_NONE, C_REG, 46, 4, 0 },
|
||||
|
||||
{ ABEQ, C_NONE, C_NONE, C_SBRA, 7, 4, 0 },
|
||||
|
||||
{ ALSL, C_LCON, C_REG, C_REG, 8, 4, 0 },
|
||||
{ ALSL, C_LCON, C_NONE, C_REG, 8, 4, 0 },
|
||||
|
||||
{ ALSL, C_REG, C_NONE, C_REG, 9, 4, 0 },
|
||||
{ ALSL, C_REG, C_REG, C_REG, 9, 4, 0 },
|
||||
|
||||
{ ASVC, C_NONE, C_NONE, C_LCON, 10, 4, 0 },
|
||||
{ ASVC, C_NONE, C_NONE, C_NONE, 10, 4, 0 },
|
||||
|
||||
{ ADWORD, C_NONE, C_NONE, C_VCON, 11, 8, 0 },
|
||||
{ ADWORD, C_NONE, C_NONE, C_LEXT, 11, 8, 0 },
|
||||
{ ADWORD, C_NONE, C_NONE, C_ADDR, 11, 8, 0 },
|
||||
|
||||
{ AWORD, C_NONE, C_NONE, C_LCON, 14, 4, 0 },
|
||||
{ AWORD, C_NONE, C_NONE, C_LEXT, 14, 4, 0 },
|
||||
{ AWORD, C_NONE, C_NONE, C_ADDR, 14, 4, 0 },
|
||||
|
||||
{ AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM },
|
||||
{ AMOV, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM },
|
||||
|
||||
{ AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM },
|
||||
{ AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM },
|
||||
|
||||
{ AMUL, C_REG, C_REG, C_REG, 15, 4, 0 },
|
||||
{ AMUL, C_REG, C_NONE, C_REG, 15, 4, 0 },
|
||||
{ AMADD, C_REG, C_REG, C_REG, 15, 4, 0 },
|
||||
|
||||
{ AREM, C_REG, C_REG, C_REG, 16, 8, 0 },
|
||||
{ AREM, C_REG, C_NONE, C_REG, 16, 8, 0 },
|
||||
|
||||
{ ACSEL, C_COND, C_REG, C_REG, 18, 4, 0 }, /* from3 optional */
|
||||
{ ACSET, C_COND, C_NONE, C_REG, 18, 4, 0 },
|
||||
|
||||
{ ACCMN, C_COND, C_REG, C_LCON, 19, 4, 0 }, /* from3 either C_REG or C_LCON */
|
||||
|
||||
/* scaled 12-bit unsigned displacement store */
|
||||
|
||||
{ AMOVB, C_REG, C_NONE, C_SEXT1, 20, 4, REGSB }, //
|
||||
{ AMOVB, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP }, //
|
||||
{ AMOVB, C_REG, C_NONE, C_UOREG4K, 20, 4, 0 }, //
|
||||
{ AMOVBU, C_REG, C_NONE, C_SEXT1, 20, 4, REGSB }, //
|
||||
{ AMOVBU, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP }, //
|
||||
{ AMOVBU, C_REG, C_NONE, C_UOREG4K, 20, 4, 0 }, //
|
||||
|
||||
{ AMOVH, C_REG, C_NONE, C_SEXT2, 20, 4, REGSB }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_UAUTO8K, 20, 4, REGSP }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_ZOREG, 20, 4, 0 }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_UOREG8K, 20, 4, 0 }, //
|
||||
|
||||
{ AMOVW, C_REG, C_NONE, C_SEXT4, 20, 4, REGSB }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_UAUTO16K, 20, 4, REGSP }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_ZOREG, 20, 4, 0 }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_UOREG16K, 20, 4, 0 }, //
|
||||
|
||||
/* unscaled 9-bit signed displacement store */
|
||||
{ AMOVB, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP }, //
|
||||
{ AMOVB, C_REG, C_NONE, C_NSOREG, 20, 4, 0 }, //
|
||||
{ AMOVBU, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP }, //
|
||||
{ AMOVBU, C_REG, C_NONE, C_NSOREG, 20, 4, 0 }, //
|
||||
|
||||
{ AMOVH, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_NSOREG, 20, 4, 0 }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_NSOREG, 20, 4, 0 }, //
|
||||
|
||||
{ AMOV, C_REG, C_NONE, C_SEXT8, 20, 4, REGSB },
|
||||
{ AMOV, C_REG, C_NONE, C_UAUTO32K, 20, 4, REGSP },
|
||||
{ AMOV, C_REG, C_NONE, C_ZOREG, 20, 4, 0 },
|
||||
{ AMOV, C_REG, C_NONE, C_UOREG32K, 20, 4, 0 },
|
||||
|
||||
{ AMOV, C_REG, C_NONE, C_NSOREG, 20, 4, 0 }, //
|
||||
{ AMOV, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP }, //
|
||||
|
||||
/* short displacement load */
|
||||
|
||||
{ AMOVB, C_SEXT1, C_NONE, C_REG, 21, 4, REGSB }, //
|
||||
{ AMOVB, C_UAUTO4K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVB, C_NSAUTO,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVB, C_ZOREG,C_NONE, C_REG, 21, 4, 0 }, //
|
||||
{ AMOVB, C_UOREG4K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVB, C_NSOREG,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
|
||||
{ AMOVBU, C_SEXT1, C_NONE, C_REG, 21, 4, REGSB }, //
|
||||
{ AMOVBU, C_UAUTO4K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVBU, C_NSAUTO,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVBU, C_ZOREG,C_NONE, C_REG, 21, 4, 0 }, //
|
||||
{ AMOVBU, C_UOREG4K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVBU, C_NSOREG,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
|
||||
{ AMOVH, C_SEXT2, C_NONE, C_REG, 21, 4, REGSB }, //
|
||||
{ AMOVH, C_UAUTO8K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVH, C_NSAUTO,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVH, C_ZOREG,C_NONE, C_REG, 21, 4, 0 }, //
|
||||
{ AMOVH, C_UOREG8K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVH, C_NSOREG,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
|
||||
{ AMOVW, C_SEXT4, C_NONE, C_REG, 21, 4, REGSB }, //
|
||||
{ AMOVW, C_UAUTO16K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVW, C_NSAUTO,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVW, C_ZOREG,C_NONE, C_REG, 21, 4, 0 }, //
|
||||
{ AMOVW, C_UOREG16K,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
{ AMOVW, C_NSOREG,C_NONE, C_REG, 21, 4, REGSP }, //
|
||||
|
||||
{ AMOV, C_SEXT8, C_NONE, C_REG, 21, 4, REGSB },
|
||||
{ AMOV, C_UAUTO32K,C_NONE, C_REG, 21, 4, REGSP },
|
||||
{ AMOV, C_NSAUTO,C_NONE, C_REG, 21, 4, REGSP },
|
||||
{ AMOV, C_ZOREG,C_NONE, C_REG, 21, 4, 0 },
|
||||
{ AMOV, C_UOREG32K,C_NONE, C_REG, 21, 4, REGSP },
|
||||
{ AMOV, C_NSOREG,C_NONE, C_REG, 21, 4, REGSP },
|
||||
|
||||
/* long displacement store */
|
||||
{ AMOVB, C_REG, C_NONE, C_LEXT, 30, 8, REGSB }, //
|
||||
{ AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP }, //
|
||||
{ AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0 }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_LEXT, 30, 8, REGSB }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP }, //
|
||||
{ AMOVH, C_REG, C_NONE, C_LOREG, 30, 8, 0 }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_LEXT, 30, 8, REGSB }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP }, //
|
||||
{ AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0 }, //
|
||||
{ AMOV, C_REG, C_NONE, C_LEXT, 30, 8, REGSB }, //
|
||||
{ AMOV, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP }, //
|
||||
{ AMOV, C_REG, C_NONE, C_LOREG, 30, 8, 0 }, //
|
||||
|
||||
/* long displacement load */
|
||||
{ AMOVB, C_LEXT, C_NONE, C_REG, 31, 8, REGSB }, //
|
||||
{ AMOVB, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP }, //
|
||||
{ AMOVB, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOVB, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOVH, C_LEXT, C_NONE, C_REG, 31, 8, REGSB }, //
|
||||
{ AMOVH, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP }, //
|
||||
{ AMOVH, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOVH, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOVW, C_LEXT, C_NONE, C_REG, 31, 8, REGSB }, //
|
||||
{ AMOVW, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP }, //
|
||||
{ AMOVW, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOVW, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOV, C_LEXT, C_NONE, C_REG, 31, 8, REGSB }, //
|
||||
{ AMOV, C_LAUTO,C_NONE, C_REG, 31, 8, REGSP }, //
|
||||
{ AMOV, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
{ AMOV, C_LOREG,C_NONE, C_REG, 31, 8, 0 }, //
|
||||
|
||||
/* load long effective stack address (load long offset and add) */
|
||||
{ AMOV, C_LACON,C_NONE, C_REG, 34, 8, REGSP, LFROM }, //
|
||||
|
||||
/* pre/post-indexed load (unscaled, signed 9-bit offset) */
|
||||
{ AMOV, C_XPOST, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVW, C_XPOST, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVH, C_XPOST, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVB, C_XPOST, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVBU, C_XPOST, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AFMOVS, C_XPOST, C_NONE, C_FREG, 22, 4, 0 },
|
||||
{ AFMOVD, C_XPOST, C_NONE, C_FREG, 22, 4, 0 },
|
||||
|
||||
{ AMOV, C_XPRE, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVW, C_XPRE, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVH, C_XPRE, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVB, C_XPRE, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AMOVBU, C_XPRE, C_NONE, C_REG, 22, 4, 0 },
|
||||
{ AFMOVS, C_XPRE, C_NONE, C_FREG, 22, 4, 0 },
|
||||
{ AFMOVD, C_XPRE, C_NONE, C_FREG, 22, 4, 0 },
|
||||
|
||||
/* pre/post-indexed store (unscaled, signed 9-bit offset) */
|
||||
{ AMOV, C_REG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AMOVW, C_REG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AMOVH, C_REG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AMOVB, C_REG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AMOVBU, C_REG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_XPOST, 23, 4, 0 },
|
||||
|
||||
{ AMOV, C_REG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AMOVW, C_REG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AMOVH, C_REG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AMOVB, C_REG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AMOVBU, C_REG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_XPRE, 23, 4, 0 },
|
||||
|
||||
/* special */
|
||||
{ AMOV, C_SPR, C_NONE, C_REG, 35, 4, 0 },
|
||||
{ AMRS, C_SPR, C_NONE, C_REG, 35, 4, 0 },
|
||||
|
||||
{ AMOV, C_REG, C_NONE, C_SPR, 36, 4, 0 },
|
||||
{ AMSR, C_REG, C_NONE, C_SPR, 36, 4, 0 },
|
||||
|
||||
{ AMOV, C_LCON, C_NONE, C_SPR, 37, 4, 0 },
|
||||
{ AMSR, C_LCON, C_NONE, C_SPR, 37, 4, 0 },
|
||||
|
||||
{ AERET, C_NONE, C_NONE, C_NONE, 41, 4, 0 },
|
||||
|
||||
{ AFMOVS, C_FREG, C_NONE, C_SEXT4, 20, 4, REGSB },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_UAUTO16K, 20, 4, REGSP },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_ZOREG, 20, 4, 0 },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_UOREG16K, 20, 4, 0 },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_NSOREG, 20, 4, 0 },
|
||||
|
||||
{ AFMOVD, C_FREG, C_NONE, C_SEXT8, 20, 4, REGSB },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_UAUTO32K, 20, 4, REGSP },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_ZOREG, 20, 4, 0 },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_UOREG32K, 20, 4, 0 },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_NSOREG, 20, 4, 0 },
|
||||
|
||||
{ AFMOVS, C_SEXT4, C_NONE, C_FREG, 21, 4, REGSB },
|
||||
{ AFMOVS, C_UAUTO16K,C_NONE, C_FREG, 21, 4, REGSP },
|
||||
{ AFMOVS, C_NSAUTO,C_NONE, C_FREG, 21, 4, REGSP },
|
||||
{ AFMOVS, C_ZOREG,C_NONE, C_FREG, 21, 4, 0 },
|
||||
{ AFMOVS, C_UOREG16K,C_NONE, C_FREG, 21, 4, 0 },
|
||||
{ AFMOVS, C_NSOREG,C_NONE, C_FREG, 21, 4, 0 },
|
||||
|
||||
{ AFMOVD, C_SEXT8, C_NONE, C_FREG, 21, 4, REGSB },
|
||||
{ AFMOVD, C_UAUTO32K,C_NONE, C_FREG, 21, 4, REGSP },
|
||||
{ AFMOVD, C_NSAUTO,C_NONE, C_FREG, 21, 4, REGSP },
|
||||
{ AFMOVD, C_ZOREG,C_NONE, C_FREG, 21, 4, 0 },
|
||||
{ AFMOVD, C_UOREG32K,C_NONE, C_FREG, 21, 4, 0 },
|
||||
{ AFMOVD, C_NSOREG,C_NONE, C_FREG, 21, 4, 0 },
|
||||
|
||||
{ AFMOVS, C_FREG, C_NONE, C_LEXT, 30, 8, REGSB, LTO },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO },
|
||||
|
||||
{ AFMOVS, C_LEXT, C_NONE, C_FREG, 31, 8, REGSB, LFROM },
|
||||
{ AFMOVS, C_LAUTO,C_NONE, C_FREG, 31, 8, REGSP, LFROM },
|
||||
{ AFMOVS, C_LOREG,C_NONE, C_FREG, 31, 8, 0, LFROM },
|
||||
|
||||
{ AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 8, 0, LTO },
|
||||
{ AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 8, 0, LFROM },
|
||||
|
||||
{ AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AFADDS, C_FREG, C_REG, C_FREG, 54, 4, 0 },
|
||||
{ AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AFADDS, C_FCON, C_REG, C_FREG, 54, 4, 0 },
|
||||
|
||||
{ AFMOVS, C_FCON, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AFMOVS, C_FREG, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AFMOVD, C_FCON, C_NONE, C_FREG, 54, 4, 0 },
|
||||
{ AFMOVD, C_FREG, C_NONE, C_FREG, 54, 4, 0 },
|
||||
|
||||
{ AFCVTZSD, C_FREG, C_NONE, C_REG, 29, 4, 0 },
|
||||
{ ASCVTFD, C_REG, C_NONE, C_FREG, 29, 4, 0 },
|
||||
|
||||
{ AFCMPS, C_FREG, C_REG, C_NONE, 56, 4, 0 },
|
||||
{ AFCMPS, C_FCON, C_REG, C_NONE, 56, 4, 0 },
|
||||
|
||||
{ AFCCMPS, C_COND, C_REG, C_LCON, 57, 4, 0 },
|
||||
|
||||
{ AFCSELD, C_COND, C_REG, C_FREG, 18, 4, 0 },
|
||||
|
||||
{ AFCVTSD, C_FREG, C_NONE, C_FREG, 29, 4, 0 },
|
||||
|
||||
{ ACASE, C_REG, C_NONE, C_REG, 62, 4*4, 0 },
|
||||
{ ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0 },
|
||||
|
||||
{ ACLREX, C_NONE, C_NONE, C_LCON, 38, 4, 0 },
|
||||
{ ACLREX, C_NONE, C_NONE, C_NONE, 38, 4, 0 },
|
||||
|
||||
{ ACBZ, C_REG, C_NONE, C_SBRA, 39, 4, 0 },
|
||||
{ ATBZ, C_LCON, C_REG, C_SBRA, 40, 4, 0 },
|
||||
|
||||
{ ASYS, C_LCON, C_NONE, C_NONE, 50, 4, 0 },
|
||||
{ ASYS, C_LCON, C_REG, C_NONE, 50, 4, 0 },
|
||||
{ ASYSL, C_LCON, C_NONE, C_REG, 50, 4, 0 },
|
||||
|
||||
{ ADMB, C_LCON, C_NONE, C_NONE, 51, 4, 0 },
|
||||
{ AHINT, C_LCON, C_NONE, C_NONE, 52, 4, 0 },
|
||||
|
||||
{ ALDXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0 },
|
||||
{ ALDXP, C_ZOREG, C_REG, C_REG, 58, 4, 0 },
|
||||
{ ASTXR, C_REG, C_REG, C_ZOREG, 59, 4, 0 },
|
||||
{ ASTXP, C_REG, C_REG, C_ZOREG, 59, 4, 0 },
|
||||
|
||||
{ AAESD, C_VREG, C_NONE, C_VREG, 29, 4, 0 },
|
||||
{ ASHA1C, C_VREG, C_REG, C_VREG, 1, 4, 0 },
|
||||
|
||||
{ AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
|
||||
};
|
448
sys/src/cmd/7l/pass.c
Normal file
448
sys/src/cmd/7l/pass.c
Normal file
|
@ -0,0 +1,448 @@
|
|||
#include "l.h"
|
||||
|
||||
vlong
|
||||
atolwhex(char *s)
|
||||
{
|
||||
vlong n;
|
||||
int f;
|
||||
|
||||
n = 0;
|
||||
f = 0;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
if(*s == '-' || *s == '+') {
|
||||
if(*s++ == '-')
|
||||
f = 1;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
}
|
||||
if(s[0]=='0' && s[1]){
|
||||
if(s[1]=='x' || s[1]=='X'){
|
||||
s += 2;
|
||||
for(;;){
|
||||
if(*s >= '0' && *s <= '9')
|
||||
n = n*16 + *s++ - '0';
|
||||
else if(*s >= 'a' && *s <= 'f')
|
||||
n = n*16 + *s++ - 'a' + 10;
|
||||
else if(*s >= 'A' && *s <= 'F')
|
||||
n = n*16 + *s++ - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while(*s >= '0' && *s <= '7')
|
||||
n = n*8 + *s++ - '0';
|
||||
} else
|
||||
while(*s >= '0' && *s <= '9')
|
||||
n = n*10 + *s++ - '0';
|
||||
if(f)
|
||||
n = -n;
|
||||
return n;
|
||||
}
|
||||
|
||||
vlong
|
||||
rnd(vlong v, long r)
|
||||
{
|
||||
long c;
|
||||
|
||||
if(r <= 0)
|
||||
return v;
|
||||
v += r - 1;
|
||||
c = v % r;
|
||||
if(c < 0)
|
||||
c += r;
|
||||
v -= c;
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
dodata(void)
|
||||
{
|
||||
int i, t;
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
long orig, v;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f dodata\n", cputime());
|
||||
Bflush(&bso);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
s = p->from.sym;
|
||||
if(p->as == ADYNT || p->as == AINIT)
|
||||
s->value = dtype;
|
||||
if(s->type == SBSS)
|
||||
s->type = SDATA;
|
||||
if(s->type != SDATA)
|
||||
diag("initialize non-data (%d): %s\n%P",
|
||||
s->type, s->name, p);
|
||||
v = p->from.offset + p->reg;
|
||||
if(v > s->value)
|
||||
diag("initialize bounds (%lld): %s\n%P",
|
||||
(vlong)s->value, s->name, p);
|
||||
}
|
||||
|
||||
if(debug['t']) {
|
||||
/*
|
||||
* pull out string constants
|
||||
*/
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
s = p->from.sym;
|
||||
if(p->to.type == D_SCONST)
|
||||
s->type = SSTRING;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 1
|
||||
* assign 'small' variables to data segment
|
||||
* (rationale is that data segment is more easily
|
||||
* addressed through offset on REGSB)
|
||||
*/
|
||||
orig = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
t = s->type;
|
||||
if(t != SDATA && t != SBSS)
|
||||
continue;
|
||||
v = s->value;
|
||||
if(v == 0) {
|
||||
diag("%s: no size", s->name);
|
||||
v = 1;
|
||||
}
|
||||
v = rnd(v, 4);
|
||||
s->value = v;
|
||||
if(v > MINSIZ)
|
||||
continue;
|
||||
if(v >= 16)
|
||||
orig = rnd(orig, 16);
|
||||
else if(v >= 8)
|
||||
orig = rnd(orig, 8);
|
||||
s->value = orig;
|
||||
orig += v;
|
||||
s->type = SDATA1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 2
|
||||
* assign large 'data' variables to data segment
|
||||
*/
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
t = s->type;
|
||||
if(t != SDATA) {
|
||||
if(t == SDATA1)
|
||||
s->type = SDATA;
|
||||
continue;
|
||||
}
|
||||
v = s->value;
|
||||
if(v >= 16)
|
||||
orig = rnd(orig, 16);
|
||||
else if(v >= 8)
|
||||
orig = rnd(orig, 8);
|
||||
s->value = orig;
|
||||
orig += v;
|
||||
}
|
||||
|
||||
while(orig & 7)
|
||||
orig++;
|
||||
datsize = orig;
|
||||
|
||||
/*
|
||||
* pass 3
|
||||
* everything else to bss segment
|
||||
*/
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
v = s->value;
|
||||
if(v >= 16)
|
||||
orig = rnd(orig, 16);
|
||||
else if(v >= 8)
|
||||
orig = rnd(orig, 8);
|
||||
s->value = orig;
|
||||
orig += v;
|
||||
}
|
||||
while(orig & 7)
|
||||
orig++;
|
||||
bsssize = orig-datsize;
|
||||
|
||||
xdefine("setSB", SDATA, 0L);
|
||||
xdefine("bdata", SDATA, 0L);
|
||||
xdefine("edata", SDATA, datsize);
|
||||
xdefine("end", SBSS, datsize+bsssize);
|
||||
xdefine("etext", STEXT, 0L);
|
||||
}
|
||||
|
||||
Prog*
|
||||
brchain(Prog *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<20; i++) {
|
||||
if(p == P || !isbranch(p->as))
|
||||
return p;
|
||||
p = p->cond;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
void
|
||||
follow(void)
|
||||
{
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f follow\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
firstp = prg();
|
||||
lastp = firstp;
|
||||
xfol(textp);
|
||||
|
||||
firstp = firstp->link;
|
||||
lastp->link = P;
|
||||
}
|
||||
|
||||
void
|
||||
xfol(Prog *p)
|
||||
{
|
||||
Prog *q, *r;
|
||||
int a, i;
|
||||
|
||||
loop:
|
||||
if(p == P)
|
||||
return;
|
||||
a = p->as;
|
||||
if(a == ATEXT)
|
||||
curtext = p;
|
||||
if(isbranch(a)) {
|
||||
q = p->cond;
|
||||
if(q != P) {
|
||||
p->mark |= FOLL;
|
||||
p = q;
|
||||
if(!(p->mark & FOLL))
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
if(p->mark & FOLL) {
|
||||
for(i=0,q=p; i<4; i++,q=q->link) {
|
||||
if(q == lastp)
|
||||
break;
|
||||
a = q->as;
|
||||
if(a == ANOP) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(isbranch(a) || isreturn(a))
|
||||
goto copy;
|
||||
if(q->cond == nil || (q->cond->mark&FOLL))
|
||||
continue;
|
||||
if(a != ABEQ && a != ABNE)
|
||||
continue;
|
||||
copy:
|
||||
for(;;) {
|
||||
r = prg();
|
||||
*r = *p;
|
||||
if(!(r->mark&FOLL))
|
||||
print("cant happen 1\n");
|
||||
r->mark |= FOLL;
|
||||
if(p != q) {
|
||||
p = p->link;
|
||||
lastp->link = r;
|
||||
lastp = r;
|
||||
continue;
|
||||
}
|
||||
lastp->link = r;
|
||||
lastp = r;
|
||||
if(isbranch(a) || isreturn(a))
|
||||
return;
|
||||
r->as = a == ABNE? ABEQ: ABNE;
|
||||
r->cond = p->link;
|
||||
r->link = p->cond;
|
||||
if(!(r->link->mark&FOLL))
|
||||
xfol(r->link);
|
||||
if(!(r->cond->mark&FOLL))
|
||||
print("cant happen 2\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
a = branchop();
|
||||
q = prg();
|
||||
q->as = a;
|
||||
q->line = p->line;
|
||||
q->to.type = D_BRANCH;
|
||||
q->to.offset = p->pc;
|
||||
q->cond = p;
|
||||
p = q;
|
||||
}
|
||||
p->mark |= FOLL;
|
||||
lastp->link = p;
|
||||
lastp = p;
|
||||
if(isbranch(a) || isreturn(a))
|
||||
return;
|
||||
if(p->cond != P)
|
||||
if(!iscall(a) && p->link != P) {
|
||||
q = brchain(p->link);
|
||||
if(canfollow(a))
|
||||
if(q != P && (q->mark&FOLL)) {
|
||||
p->as = relinv(a);
|
||||
p->link = p->cond;
|
||||
p->cond = q;
|
||||
}
|
||||
xfol(p->link);
|
||||
q = brchain(p->cond);
|
||||
if(q == P)
|
||||
q = p->cond;
|
||||
if(q->mark&FOLL) {
|
||||
p->cond = q;
|
||||
return;
|
||||
}
|
||||
p = q;
|
||||
goto loop;
|
||||
}
|
||||
p = p->link;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void
|
||||
patch(void)
|
||||
{
|
||||
long c, vexit;
|
||||
Prog *p, *q;
|
||||
Sym *s;
|
||||
int a;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f patch\n", cputime());
|
||||
Bflush(&bso);
|
||||
mkfwd();
|
||||
s = lookup("exit", 0);
|
||||
vexit = s->value;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
a = p->as;
|
||||
if(a == ATEXT)
|
||||
curtext = p;
|
||||
if((iscall(a) || isbranch(a) || isreturn(a)) &&
|
||||
p->to.type != D_BRANCH && p->to.sym != S) {
|
||||
s = p->to.sym;
|
||||
switch(s->type) {
|
||||
default:
|
||||
diag("undefined: %s\n%P", s->name, p);
|
||||
s->type = STEXT;
|
||||
s->value = vexit;
|
||||
break;
|
||||
case STEXT:
|
||||
p->to.offset = s->value;
|
||||
break;
|
||||
case SUNDEF:
|
||||
if(!iscall(p->as))
|
||||
diag("help: SUNDEF in AB || ARET");
|
||||
p->to.offset = 0;
|
||||
p->cond = UP;
|
||||
break;
|
||||
}
|
||||
p->to.type = D_BRANCH;
|
||||
}
|
||||
if(p->cond == UP)
|
||||
continue;
|
||||
if(p->to.type == D_BRANCH)
|
||||
c = p->to.offset;
|
||||
else if(p->from.type == D_BRANCH)
|
||||
c = p->from.offset;
|
||||
else
|
||||
continue;
|
||||
for(q = firstp; q != P;) {
|
||||
if(q->forwd != P)
|
||||
if(c >= q->forwd->pc) {
|
||||
q = q->forwd;
|
||||
continue;
|
||||
}
|
||||
if(c == q->pc)
|
||||
break;
|
||||
q = q->link;
|
||||
}
|
||||
if(q == P) {
|
||||
diag("branch out of range %ld\n%P", c, p);
|
||||
p->to.type = D_NONE;
|
||||
}
|
||||
p->cond = q;
|
||||
}
|
||||
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->cond != P && p->cond != UP) {
|
||||
p->cond = brloop(p->cond);
|
||||
if(p->cond != P){
|
||||
if(p->to.type == D_BRANCH)
|
||||
p->to.offset = p->cond->pc;
|
||||
if(p->from.type == D_BRANCH)
|
||||
p->from.offset = p->cond->pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LOG 6
|
||||
void
|
||||
mkfwd(void)
|
||||
{
|
||||
Prog *p;
|
||||
long dwn[LOG], cnt[LOG], i;
|
||||
Prog *lst[LOG];
|
||||
|
||||
for(i=0; i<LOG; i++) {
|
||||
if(i == 0)
|
||||
cnt[i] = 1; else
|
||||
cnt[i] = LOG * cnt[i-1];
|
||||
dwn[i] = 1;
|
||||
lst[i] = P;
|
||||
}
|
||||
i = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
i--;
|
||||
if(i < 0)
|
||||
i = LOG-1;
|
||||
p->forwd = P;
|
||||
dwn[i]--;
|
||||
if(dwn[i] <= 0) {
|
||||
dwn[i] = cnt[i];
|
||||
if(lst[i] != P)
|
||||
lst[i]->forwd = p;
|
||||
lst[i] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prog*
|
||||
brloop(Prog *p)
|
||||
{
|
||||
Prog *q;
|
||||
int c;
|
||||
|
||||
for(c=0; p!=P;) {
|
||||
if(!isbranch(p->as))
|
||||
return p;
|
||||
q = p->cond;
|
||||
if(q <= p) {
|
||||
c++;
|
||||
if(q == p || c > 5000)
|
||||
break;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
void
|
||||
undef(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->type == SXREF)
|
||||
diag("%s: not defined", s->name);
|
||||
}
|
1316
sys/src/cmd/7l/span.c
Normal file
1316
sys/src/cmd/7l/span.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue