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…
Add table
Add a link
Reference in a new issue