Commit 4a4ec238 authored by Russ Cox's avatar Russ Cox

8l: step toward native client.

  - ELF header bits and addresses
  - do not let instructions span 32-byte boundary
  - align CALLs so return is to 32-byte boundary
  - align indirect jump targets to 32-byte boundary
    (only possible indirect jumps are function entries)

still to do:
  - replace indirect jump, indirect call, and ret with
    nacl-approved instruction sequences
  - switch to GS segment for m-local storage

R=ken
OCL=34818
CL=34818
parent c64986f7
...@@ -132,6 +132,7 @@ asmb(void) ...@@ -132,6 +132,7 @@ asmb(void)
int a, np, nl, ns; int a, np, nl, ns;
uint32 va, fo, w, symo; uint32 va, fo, w, symo;
uchar *op1; uchar *op1;
ulong expectpc;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
...@@ -143,17 +144,39 @@ asmb(void) ...@@ -143,17 +144,39 @@ asmb(void)
for(p = firstp; p != P; p = p->link) { for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) if(p->as == ATEXT)
curtext = p; curtext = p;
curp = p;
if(HEADTYPE == 8) {
// native client
expectpc = p->pc;
p->pc = pc;
asmins(p);
if(p->pc != expectpc) {
Bflush(&bso);
diag("phase error %lux sb %lux in %s", p->pc, expectpc, TNAME);
}
while(pc < p->pc) {
cput(0x90); // nop
pc++;
}
}
if(p->pc != pc) { if(p->pc != pc) {
Bflush(&bso);
if(!debug['a']) if(!debug['a'])
print("%P\n", curp); print("%P\n", curp);
diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME); diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
pc = p->pc; pc = p->pc;
} }
curp = p; if(HEADTYPE != 8) {
asmins(p); asmins(p);
if(pc != p->pc) {
Bflush(&bso);
diag("asmins changed pc %lux sb %lux in %s", p->pc, pc, TNAME);
}
}
if(cbc < sizeof(and)) if(cbc < sizeof(and))
cflush(); cflush();
a = (andptr - and); a = (andptr - and);
if(debug['a']) { if(debug['a']) {
Bprint(&bso, pcstr, pc); Bprint(&bso, pcstr, pc);
for(op1 = and; op1 < andptr; op1++) for(op1 = and; op1 < andptr; op1++)
...@@ -171,6 +194,12 @@ asmb(void) ...@@ -171,6 +194,12 @@ asmb(void)
pc += a; pc += a;
cbc -= a; cbc -= a;
} }
if(HEADTYPE == 8) {
while(pc < INITDAT) {
cput(0xf4); // hlt
pc++;
}
}
cflush(); cflush();
switch(HEADTYPE) { switch(HEADTYPE) {
default: default:
...@@ -200,6 +229,7 @@ asmb(void) ...@@ -200,6 +229,7 @@ asmb(void)
cflush(); cflush();
break; break;
case 7: case 7:
case 8:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = elfstrtable(); strtabsize = elfstrtable();
cflush(); cflush();
...@@ -254,6 +284,7 @@ asmb(void) ...@@ -254,6 +284,7 @@ asmb(void)
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND); symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
break; break;
case 7: case 7:
case 8:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
...@@ -485,10 +516,12 @@ asmb(void) ...@@ -485,10 +516,12 @@ asmb(void)
break; break;
case 7: case 7:
case 8:
np = 3; np = 3;
ns = 5; ns = 5;
if(!debug['s']) { if(!debug['s']) {
np++; if(HEADTYPE != 8) // no loading of debug info under native client
np++;
ns += 2; ns += 2;
} }
...@@ -497,14 +530,24 @@ asmb(void) ...@@ -497,14 +530,24 @@ asmb(void)
cput(1); /* class = 32 bit */ cput(1); /* class = 32 bit */
cput(1); /* data = LSB */ cput(1); /* data = LSB */
cput(1); /* version = CURRENT */ cput(1); /* version = CURRENT */
strnput("", 9); if(HEADTYPE == 8) {
cput(123); /* os abi - native client */
cput(5); /* nacl abi version */
} else {
cput(0);
cput(0);
}
strnput("", 7);
wputl(2); /* type = EXEC */ wputl(2); /* type = EXEC */
wputl(3); /* machine = AMD64 */ wputl(3); /* machine = AMD64 */
lputl(1L); /* version = CURRENT */ lputl(1L); /* version = CURRENT */
lputl(entryvalue()); /* entry vaddr */ lputl(entryvalue()); /* entry vaddr */
lputl(52L); /* offset to first phdr */ lputl(52L); /* offset to first phdr */
lputl(52L+32L*np); /* offset to first shdr */ lputl(52L+32L*np); /* offset to first shdr */
lputl(0L); /* processor specific flags */ if(HEADTYPE == 8)
lputl(0x200000); /* native client - align mod 32 */
else
lputl(0L); /* processor specific flags */
wputl(52L); /* Ehdr size */ wputl(52L); /* Ehdr size */
wputl(32L); /* Phdr size */ wputl(32L); /* Phdr size */
wputl(np); /* # of Phdrs */ wputl(np); /* # of Phdrs */
...@@ -513,13 +556,13 @@ asmb(void) ...@@ -513,13 +556,13 @@ asmb(void)
wputl(4); /* Shdr with strings */ wputl(4); /* Shdr with strings */
/* prog headers */ /* prog headers */
fo = 0; fo = HEADR;
va = INITTEXT & ~((vlong)INITRND - 1); va = INITTEXT;
w = HEADR+textsize; w = textsize;
elfphdr(1, /* text - type = PT_LOAD */ elfphdr(1, /* text - type = PT_LOAD */
1L+4L, /* text - flags = PF_X+PF_R */ 1L+4L, /* text - flags = PF_X+PF_R */
0, /* file offset */ fo, /* file offset */
va, /* vaddr */ va, /* vaddr */
va, /* paddr */ va, /* paddr */
w, /* file size */ w, /* file size */
...@@ -539,7 +582,7 @@ asmb(void) ...@@ -539,7 +582,7 @@ asmb(void)
w+bsssize, /* memory size */ w+bsssize, /* memory size */
INITRND); /* alignment */ INITRND); /* alignment */
if(!debug['s']) { if(!debug['s'] && HEADTYPE != 8) {
elfphdr(1, /* data - type = PT_LOAD */ elfphdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */ 2L+4L, /* data - flags = PF_W+PF_R */
symo, /* file offset */ symo, /* file offset */
...@@ -573,7 +616,7 @@ asmb(void) ...@@ -573,7 +616,7 @@ asmb(void)
stroffset = 1; /* 0 means no name, so start at 1 */ stroffset = 1; /* 0 means no name, so start at 1 */
fo = HEADR; fo = HEADR;
va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; va = INITTEXT;
w = textsize; w = textsize;
elfshdr(".text", /* name */ elfshdr(".text", /* name */
......
...@@ -288,7 +288,7 @@ EXTERN uchar inuxi2[2]; ...@@ -288,7 +288,7 @@ EXTERN uchar inuxi2[2];
EXTERN uchar inuxi4[4]; EXTERN uchar inuxi4[4];
EXTERN uchar ycover[Ymax*Ymax]; EXTERN uchar ycover[Ymax*Ymax];
EXTERN uchar* andptr; EXTERN uchar* andptr;
EXTERN uchar and[30]; EXTERN uchar and[100];
EXTERN char reg[D_NONE]; EXTERN char reg[D_NONE];
EXTERN Prog* lastp; EXTERN Prog* lastp;
EXTERN int32 lcsize; EXTERN int32 lcsize;
......
...@@ -150,6 +150,9 @@ main(int argc, char *argv[]) ...@@ -150,6 +150,9 @@ main(int argc, char *argv[])
else else
if(strcmp(goos, "darwin") == 0) if(strcmp(goos, "darwin") == 0)
HEADTYPE = 6; HEADTYPE = 6;
else
if(strcmp(goos, "nacl") == 0)
HEADTYPE = 8;
else else
print("goos is not known: %sn", goos); print("goos is not known: %sn", goos);
} }
...@@ -225,6 +228,15 @@ main(int argc, char *argv[]) ...@@ -225,6 +228,15 @@ main(int argc, char *argv[])
if(INITRND == -1) if(INITRND == -1)
INITRND = 4096; INITRND = 4096;
break; break;
case 8: /* native client elf32 executable */
HEADR = 4096;
if(INITTEXT == -1)
INITTEXT = 0x20000;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
} }
if(INITDAT != 0 && INITRND != 0) if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%lux is ignored because of -R0x%lux\n", print("warning: -D0x%lux is ignored because of -R0x%lux\n",
......
...@@ -64,6 +64,7 @@ span(void) ...@@ -64,6 +64,7 @@ span(void)
p->as = ANOP; p->as = ANOP;
} }
} }
n = 0; n = 0;
start: start:
do{ do{
...@@ -77,20 +78,29 @@ start: ...@@ -77,20 +78,29 @@ start:
} }
c = INITTEXT; c = INITTEXT;
for(p = firstp; p != P; p = p->link) { for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) if(p->as == ATEXT) {
curtext = p; curtext = p;
if(HEADTYPE == 8)
c = (c+31)&~31;
}
if(p->to.type == D_BRANCH) if(p->to.type == D_BRANCH)
if(p->back) if(p->back)
p->pc = c; p->pc = c;
if(n == 0 || p->to.type == D_BRANCH) { if(n == 0 || HEADTYPE == 8 || p->to.type == D_BRANCH) {
if(HEADTYPE == 8)
p->pc = c;
asmins(p); asmins(p);
m = andptr-and; m = andptr-and;
if(p->mark != m)
again = 1;
p->mark = m; p->mark = m;
} }
if(c != p->pc) if(HEADTYPE == 8) {
again = 1; c = p->pc + p->mark;
p->pc = c; } else {
c += p->mark; p->pc = c;
c += p->mark;
}
} }
textsize = c; textsize = c;
n++; n++;
...@@ -1292,9 +1302,35 @@ mfound: ...@@ -1292,9 +1302,35 @@ mfound:
void void
asmins(Prog *p) asmins(Prog *p)
{ {
if(HEADTYPE == 8) {
ulong npc;
andptr = and; // native client
doasm(p); // - pad indirect jump targets (aka ATEXT) to 32-byte boundary
// - instructions cannot cross 32-byte boundary
// - end of call (return address) must be on 32-byte boundary
if(p->as == ATEXT)
p->pc += 31 & -p->pc;
if(p->as == ACALL)
while((p->pc+5)&31)
p->pc++;
andptr = and;
doasm(p);
npc = p->pc + (andptr - and);
if((p->pc&~31) != ((npc-1)&~31)) {
// crossed 32-byte boundary; pad to boundary and try again
p->pc += 31 & -p->pc;
andptr = and;
doasm(p);
}
} else {
andptr = and;
doasm(p);
}
if(andptr > and+sizeof and) {
print("and[] is too short - %d byte instruction\n", andptr - and);
errorexit();
}
} }
enum{ enum{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment