diff options
Diffstat (limited to 'src/cmd/5l/asm.c')
-rw-r--r-- | src/cmd/5l/asm.c | 311 |
1 files changed, 88 insertions, 223 deletions
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index e2583e7c3..4afed2b80 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -34,8 +34,6 @@ #include "../ld/lib.h" #include "../ld/elf.h" -int32 OFFSET; - static Prog *PP; char linuxdynld[] = "/lib/ld-linux.so.2"; @@ -73,6 +71,8 @@ enum { ElfStrGosymcounts, ElfStrGosymtab, ElfStrGopclntab, + ElfStrSymtab, + ElfStrStrtab, ElfStrShstrtab, ElfStrRelPlt, ElfStrPlt, @@ -87,6 +87,9 @@ needlib(char *name) char *p; Sym *s; + if(*name == '\0') + return 0; + /* reuse hash code in symbol table */ p = smprint(".dynlib.%s", name); s = lookup(p, 0); @@ -163,6 +166,8 @@ doelf(void) elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); + elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab"); + elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab"); } elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab"); @@ -288,15 +293,12 @@ asmb(void) { int32 t; int a, dynsym; - uint32 va, fo, w, startva; - int strtabsize; + uint32 fo, symo, startva; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; Section *sect; - strtabsize = 0; - if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); @@ -322,15 +324,30 @@ asmb(void) seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0); datblk(sect->vaddr, sect->len); + if(iself) { + /* index of elf text section; needed by asmelfsym, double-checked below */ + /* !debug['d'] causes extra sections before the .text section */ + elftextsh = 1; + if(!debug['d']) { + elftextsh += 10; + if(elfverneed) + elftextsh += 2; + } + } + /* output symbol table */ symsize = 0; lcsize = 0; + symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { + default: + if(iself) + goto ElfSym; case Hnoheader: case Hrisc: case Hixp1200: @@ -338,29 +355,37 @@ asmb(void) debug['s'] = 1; break; case Hplan9x32: - OFFSET = HEADR+textsize+segdata.filelen; - seek(cout, OFFSET, 0); + symo = HEADR+segtext.len+segdata.filelen; break; case Hnetbsd: - OFFSET += rnd(segdata.filelen, 4096); - seek(cout, OFFSET, 0); + symo = rnd(segdata.filelen, 4096); break; - case Hlinux: - OFFSET += segdata.filelen; - seek(cout, rnd(OFFSET, INITRND), 0); + ElfSym: + symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; + symo = rnd(symo, INITRND); break; } - if(!debug['s']) - asmthumbmap(); + seek(cout, symo, 0); + if(iself) { + if(debug['v']) + Bprint(&bso, "%5.2f elfsym\n", cputime()); + asmelfsym(); + cflush(); + ewrite(cout, elfstrdat, elfstrsize); + + // if(debug['v']) + // Bprint(&bso, "%5.2f dwarf\n", cputime()); + // dwarfemitdebugsections(); + } cflush(); + } cursym = nil; if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); - OFFSET = 0; - seek(cout, OFFSET, 0); + seek(cout, 0L, 0); switch(HEADTYPE) { case Hnoheader: /* no header */ break; @@ -426,9 +451,7 @@ asmb(void) /* elf arm */ eh = getElfEhdr(); fo = HEADR; - va = INITTEXT; startva = INITTEXT - fo; /* va of byte 0 of file */ - w = textsize; /* This null SHdr must appear before all others */ sh = newElfShdr(elfstr[ElfStrEmpty]); @@ -541,6 +564,8 @@ asmb(void) ph->flags = PF_W+PF_R; ph->align = 4; + if(elftextsh != eh->shnum) + diag("elftextsh = %d, want %d", elftextsh, eh->shnum); for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) @@ -558,6 +583,22 @@ asmb(void) sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup("pclntab", 0)); + + sh = newElfShdr(elfstr[ElfStrSymtab]); + sh->type = SHT_SYMTAB; + sh->off = symo; + sh->size = symsize; + sh->addralign = 4; + sh->entsize = 16; + sh->link = eh->shnum; // link to strtab + + sh = newElfShdr(elfstr[ElfStrStrtab]); + sh->type = SHT_STRTAB; + sh->off = symo+symsize; + sh->size = elfstrsize; + sh->addralign = 1; + + // dwarfaddelfheaders(); } sh = newElfShstrtab(elfstr[ElfStrShstrtab]); @@ -686,59 +727,6 @@ nopstat(char *f, Count *c) (double)(c->outof - c->count)/c->outof); } -static void -outt(int32 f, int32 l) -{ - if(debug['L']) - Bprint(&bso, "tmap: %ux-%ux\n", f, l); - lput(f); - lput(l); -} - -void -asmthumbmap(void) -{ - int32 pc, lastt; - Prog *p; - - if(!seenthumb) - return; - pc = 0; - lastt = -1; - for(cursym = textp; cursym != nil; cursym = cursym->next) { - p = cursym->text; - pc = p->pc - INITTEXT; - setarch(p); - if(thumb){ - if(p->from.sym->foreign){ // 8 bytes of ARM first - if(lastt >= 0){ - outt(lastt, pc-1); - lastt = -1; - } - pc += 8; - } - if(lastt < 0) - lastt = pc; - } - else{ - if(p->from.sym->foreign){ // 4 bytes of THUMB first - if(lastt < 0) - lastt = pc; - pc += 4; - } - if(lastt >= 0){ - outt(lastt, pc-1); - lastt = -1; - } - } - if(cursym->next == nil) - for(; p != P; p = p->link) - pc = p->pc = INITTEXT; - } - if(lastt >= 0) - outt(lastt, pc+1); -} - void asmout(Prog *p, Optab *o, int32 *out) { @@ -762,7 +750,7 @@ if(debug['P']) print("%ux: %P type %d\n", (uint32)(p->pc), p, o->type); break; case 0: /* pseudo ops */ -if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->name, p->from.sym->thumb, p->from.sym->foreign, p->from.sym->fnptr); +if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p->from.sym->fnptr); break; case 1: /* op R,[R],R */ @@ -826,10 +814,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na v = -8; if(p->cond != P) v = (p->cond->pc - pc) - 8; -#ifdef CALLEEBX - if(p->as == ABL) - v += fninc(p->to.sym); -#endif o1 = opbra(p->as, p->scond); o1 |= (v >> 2) & 0xffffff; break; @@ -990,40 +974,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 |= 1<<22; break; - case 22: /* movb/movh/movhu O(R),R -> lr,shl,shr */ - aclass(&p->from); - r = p->from.reg; - if(r == NREG) - r = o->param; - o1 = olr(instoffset, r, p->to.reg, p->scond); - - o2 = oprrr(ASLL, p->scond); - o3 = oprrr(ASRA, p->scond); - r = p->to.reg; - if(p->as == AMOVB) { - o2 |= (24<<7)|(r)|(r<<12); - o3 |= (24<<7)|(r)|(r<<12); - } else { - o2 |= (16<<7)|(r)|(r<<12); - if(p->as == AMOVHU) - o3 = oprrr(ASRL, p->scond); - o3 |= (16<<7)|(r)|(r<<12); - } - break; - - case 23: /* movh/movhu R,O(R) -> sb,sb */ - aclass(&p->to); - r = p->to.reg; - if(r == NREG) - r = o->param; - o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond); - - o2 = oprrr(ASRL, p->scond); - o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12); - - o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond); - break; - case 30: /* mov/movb/movbu R,L(R) */ o1 = omvl(p, &p->to, REGTMP); if(!o1) @@ -1037,7 +987,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na break; case 31: /* mov/movbu L(R),R -> lr[b] */ - case 32: /* movh/movb L(R),R -> lr[b] */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; @@ -1047,53 +996,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o2 = olrr(REGTMP,r, p->to.reg, p->scond); if(p->as == AMOVBU || p->as == AMOVB) o2 |= 1<<22; - if(o->type == 31) - break; - - o3 = oprrr(ASLL, p->scond); - - if(p->as == AMOVBU || p->as == AMOVHU) - o4 = oprrr(ASRL, p->scond); - else - o4 = oprrr(ASRA, p->scond); - - r = p->to.reg; - o3 |= (r)|(r<<12); - o4 |= (r)|(r<<12); - if(p->as == AMOVB || p->as == AMOVBU) { - o3 |= (24<<7); - o4 |= (24<<7); - } else { - o3 |= (16<<7); - o4 |= (16<<7); - } - break; - - case 33: /* movh/movhu R,L(R) -> sb, sb */ - o1 = omvl(p, &p->to, REGTMP); - if(!o1) - break; - r = p->to.reg; - if(r == NREG) - r = o->param; - o2 = osrr(p->from.reg, REGTMP, r, p->scond); - o2 |= (1<<22) ; - - o3 = oprrr(ASRL, p->scond); - o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); - o3 |= (1<<6); /* ROR 8 */ - - o4 = oprrr(AADD, p->scond); - o4 |= (REGTMP << 12) | (REGTMP << 16); - o4 |= immrot(1); - - o5 = osrr(p->from.reg, REGTMP,r,p->scond); - o5 |= (1<<22); - - o6 = oprrr(ASRL, p->scond); - o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); - o6 |= (1<<6); /* ROL 8 */ - break; case 34: /* mov $lacon,R */ @@ -1226,7 +1128,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na r = p->reg; if(r == NREG) { r = rt; - if(p->as == AMOVF || p->as == AMOVD) + if(p->as == AMOVF || p->as == AMOVD || p->as == ASQRTF || p->as == ASQRTD) r = 0; } o1 |= rf | (r<<16) | (rt<<12); @@ -1304,54 +1206,12 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na break; case 65: /* mov/movbu addr,R */ - case 66: /* movh/movhu/movb addr,R */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; o2 = olr(0, REGTMP, p->to.reg, p->scond); if(p->as == AMOVBU || p->as == AMOVB) o2 |= 1<<22; - if(o->type == 65) - break; - - o3 = oprrr(ASLL, p->scond); - - if(p->as == AMOVBU || p->as == AMOVHU) - o4 = oprrr(ASRL, p->scond); - else - o4 = oprrr(ASRA, p->scond); - - r = p->to.reg; - o3 |= (r)|(r<<12); - o4 |= (r)|(r<<12); - if(p->as == AMOVB || p->as == AMOVBU) { - o3 |= (24<<7); - o4 |= (24<<7); - } else { - o3 |= (16<<7); - o4 |= (16<<7); - } - break; - - case 67: /* movh/movhu R,addr -> sb, sb */ - o1 = omvl(p, &p->to, REGTMP); - if(!o1) - break; - o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); - - o3 = oprrr(ASRL, p->scond); - o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); - o3 |= (1<<6); /* ROR 8 */ - - o4 = oprrr(AADD, p->scond); - o4 |= (REGTMP << 12) | (REGTMP << 16); - o4 |= immrot(1); - - o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); - - o6 = oprrr(ASRL, p->scond); - o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); - o6 |= (1<<6); /* ROL 8 */ break; case 68: /* floating point store -> ADDR */ @@ -1410,19 +1270,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o2 ^= (1<<6); break; case 74: /* bx $I */ -#ifdef CALLEEBX - diag("bx $i case (arm)"); -#endif - if(!seenthumb) - diag("ABX $I and seenthumb==0"); - v = p->cond->pc; - if(p->to.sym->thumb) - v |= 1; // T bit - o1 = olr(8, REGPC, REGTMP, p->scond&C_SCOND); // mov 8(PC), Rtmp - o2 = oprrr(AADD, p->scond) | immrot(8) | (REGPC<<16) | (REGLINK<<12); // add 8,PC, LR - o3 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | REGTMP; // bx Rtmp - o4 = opbra(AB, 14); // B over o6 - o5 = v; + diag("ABX $I"); break; case 75: /* bx O(R) */ aclass(&p->to); @@ -1441,14 +1289,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o3 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | REGTMP; // BX Rtmp break; case 76: /* bx O(R) when returning from fn*/ - if(!seenthumb) - diag("ABXRET and seenthumb==0"); - aclass(&p->to); -// print("ARM BXRET %d(R%d)\n", instoffset, p->to.reg); - if(instoffset != 0) - diag("non-zero offset in ABXRET"); - // o1 = olr(instoffset, p->to.reg, REGTMP, p->scond); // mov O(R), Rtmp - o1 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | p->to.reg; // BX R + diag("ABXRET"); break; case 77: /* ldrex oreg,reg */ aclass(&p->from); @@ -1572,6 +1413,22 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 |= p->to.reg << 12; o1 |= (p->scond & C_SCOND) << 28; break; + case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ + o1 = omvl(p, &p->from, REGTMP); + if(!o1) + break; + o2 = olhr(0, REGTMP, p->to.reg, p->scond); + if(p->as == AMOVB) + o2 ^= (1<<5)|(1<<6); + else if(p->as == AMOVH) + o2 ^= (1<<6); + break; + case 94: /* movh/movhu R,addr -> strh */ + o1 = omvl(p, &p->to, REGTMP); + if(!o1) + break; + o2 = oshr(p->from.reg, 0, REGTMP, p->scond); + break; } out[0] = o1; @@ -1686,6 +1543,8 @@ oprrr(int a, int sc) case AMULF: return o | (0xe<<24) | (0x2<<20) | (0xa<<8) | (0<<4); case ADIVD: return o | (0xe<<24) | (0x8<<20) | (0xb<<8) | (0<<4); case ADIVF: return o | (0xe<<24) | (0x8<<20) | (0xa<<8) | (0<<4); + case ASQRTD: return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xb<<8) | (0xc<<4); + case ASQRTF: return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xa<<8) | (0xc<<4); case ACMPD: return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xb<<8) | (0xc<<4); case ACMPF: return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xa<<8) | (0xc<<4); @@ -2031,3 +1890,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) Bprint(&bso, "symsize = %ud\n", symsize); Bflush(&bso); } + +void +setpersrc(Sym *s) +{ + USED(s); +} |