summaryrefslogtreecommitdiff
path: root/src/cmd/5l/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5l/asm.c')
-rw-r--r--src/cmd/5l/asm.c311
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);
+}