diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-04-20 15:44:41 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-04-20 15:44:41 +0200 |
commit | 50104cc32a498f7517a51c8dc93106c51c7a54b4 (patch) | |
tree | 47af80be259cc7c45d0eaec7d42e61fa38c8e4fb /src/cmd/5l | |
parent | c072558b90f1bbedc2022b0f30c8b1ac4712538e (diff) | |
download | golang-upstream/2011.03.07.1.tar.gz |
Imported Upstream version 2011.03.07.1upstream/2011.03.07.1
Diffstat (limited to 'src/cmd/5l')
-rw-r--r-- | src/cmd/5l/5.out.h | 3 | ||||
-rw-r--r-- | src/cmd/5l/asm.c | 49 | ||||
-rw-r--r-- | src/cmd/5l/doc.go | 2 | ||||
-rw-r--r-- | src/cmd/5l/l.h | 5 | ||||
-rw-r--r-- | src/cmd/5l/list.c | 4 | ||||
-rw-r--r-- | src/cmd/5l/noop.c | 24 | ||||
-rw-r--r-- | src/cmd/5l/obj.c | 51 | ||||
-rw-r--r-- | src/cmd/5l/optab.c | 3 | ||||
-rw-r--r-- | src/cmd/5l/pass.c | 12 | ||||
-rw-r--r-- | src/cmd/5l/span.c | 2 |
10 files changed, 107 insertions, 48 deletions
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h index a25c0f71d..002b46d45 100644 --- a/src/cmd/5l/5.out.h +++ b/src/cmd/5l/5.out.h @@ -179,6 +179,9 @@ enum as ALDREX, ASTREX, + + ALDREXD, + ASTREXD, ALAST, }; diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 7163997c0..af6d1dfda 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -331,21 +331,21 @@ asmb(void) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { - case 0: - case 1: - case 4: - case 5: + case Hnoheader: + case Hrisc: + case Hixp1200: + case Hipaq: debug['s'] = 1; break; - case 2: + case Hplan9x32: OFFSET = HEADR+textsize+segdata.filelen; seek(cout, OFFSET, 0); break; - case 3: + case Hnetbsd: OFFSET += rnd(segdata.filelen, 4096); seek(cout, OFFSET, 0); break; - case 6: + case Hlinux: OFFSET += segdata.filelen; seek(cout, rnd(OFFSET, INITRND), 0); break; @@ -362,9 +362,9 @@ asmb(void) OFFSET = 0; seek(cout, OFFSET, 0); switch(HEADTYPE) { - case 0: /* no header */ + case Hnoheader: /* no header */ break; - case 1: /* aif for risc os */ + case Hrisc: /* aif for risc os */ lputl(0xe1a00000); /* NOP - decompress code */ lputl(0xe1a00000); /* NOP - relocation code */ lputl(0xeb000000 + 12); /* BL - zero init code */ @@ -394,7 +394,7 @@ asmb(void) lputl(0xe1a00000); /* NOP - zero init code */ lputl(0xe1a0f00e); /* B (R14) - zero init return */ break; - case 2: /* plan 9 */ + case Hplan9x32: /* plan 9 */ lput(0x647); /* magic */ lput(textsize); /* sizes */ lput(segdata.filelen); @@ -404,7 +404,7 @@ asmb(void) lput(0L); lput(lcsize); break; - case 3: /* boot for NetBSD */ + case Hnetbsd: /* boot for NetBSD */ lput((143<<16)|0413); /* magic */ lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(segdata.filelen, 4096)); @@ -414,15 +414,15 @@ asmb(void) lputl(0L); lputl(0L); break; - case 4: /* boot for IXP1200 */ + case Hixp1200: /* boot for IXP1200 */ break; - case 5: /* boot for ipaq */ + case Hipaq: /* boot for ipaq */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; - case 6: + case Hlinux: /* elf arm */ eh = getElfEhdr(); fo = HEADR; @@ -1463,7 +1463,7 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na aclass(&p->from); if(instoffset != 0) diag("offset must be zero in STREX"); - o1 = (0x3<<23) | (0xf9<<4); + o1 = (0x18<<20) | (0xf90); o1 |= p->from.reg << 16; o1 |= p->reg << 0; o1 |= p->to.reg << 12; @@ -1553,6 +1553,25 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 = oprrr(ACMP+AEND, p->scond); o1 |= p->from.reg<<16; break; + case 91: /* ldrexd oreg,reg */ + aclass(&p->from); + if(instoffset != 0) + diag("offset must be zero in LDREX"); + o1 = (0x1b<<20) | (0xf9f); + o1 |= p->from.reg << 16; + o1 |= p->to.reg << 12; + o1 |= (p->scond & C_SCOND) << 28; + break; + case 92: /* strexd reg,oreg,reg */ + aclass(&p->from); + if(instoffset != 0) + diag("offset must be zero in STREX"); + o1 = (0x1a<<20) | (0xf90); + o1 |= p->from.reg << 16; + o1 |= p->reg << 0; + o1 |= p->to.reg << 12; + o1 |= (p->scond & C_SCOND) << 28; + break; } out[0] = o1; diff --git a/src/cmd/5l/doc.go b/src/cmd/5l/doc.go index d266b9233..aa7ccebfc 100644 --- a/src/cmd/5l/doc.go +++ b/src/cmd/5l/doc.go @@ -23,6 +23,8 @@ Options new in this version: -F Force use of software floating point. Also implied by setting GOARM=5 in the environment. +-Hlinux + Write Linux ELF binaries (default when $GOOS is linux) -I interpreter Set the ELF dynamic linker to use. -L dir1 -L dir2 diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index e42be4e98..2e887dad7 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -35,6 +35,7 @@ enum { + thechar = '5', PtrSize = 4 }; @@ -109,6 +110,7 @@ struct Prog Prog* dlink; int32 pc; int32 line; + int32 spadj; uchar mark; uchar optab; uchar as; @@ -122,6 +124,8 @@ struct Prog #define datasize reg #define textflag reg +#define iscall(p) ((p)->as == ABL) + struct Sym { char* name; @@ -131,6 +135,7 @@ struct Sym uchar reachable; uchar dynexport; uchar leaf; + uchar stkcheck; int32 dynid; int32 plt; int32 got; diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c index b4df89587..2ae25d491 100644 --- a/src/cmd/5l/list.c +++ b/src/cmd/5l/list.c @@ -98,6 +98,10 @@ Pconv(Fmt *fp) fmtprint(fp, "(%d) DWORD %D %D", p->line, &p->from, &p->to); break; } + + if(p->spadj) + fmtprint(fp, " (spadj%+d)", p->spadj); + return 0; } diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c index a9439c27a..a5e66f038 100644 --- a/src/cmd/5l/noop.c +++ b/src/cmd/5l/noop.c @@ -227,7 +227,7 @@ noops(void) #ifdef CALLEEBX if(p->from.sym->foreign){ if(thumb) - // don't allow literal pool to seperate these + // don't allow literal pool to separate these p = adword(0xe28f7001, 0xe12fff17, p); // arm add 1, pc, r7 and bx r7 // p = aword(0xe12fff17, aword(0xe28f7001, p)); // arm add 1, pc, r7 and bx r7 else @@ -282,6 +282,7 @@ noops(void) q1->to.type = D_OREG; q1->to.offset = -autosize; q1->to.reg = REGSP; + q1->spadj = autosize; q1->link = p->link; p->link = q1; } else if (autosize < StackBig) { @@ -376,6 +377,7 @@ noops(void) p->to.type = D_OREG; p->to.offset = -autosize; p->to.reg = REGSP; + p->spadj = autosize; } else { // > StackBig // MOVW $autosize, R1 // MOVW $args, R2 @@ -424,6 +426,7 @@ noops(void) p->to.type = D_OREG; p->to.offset = -autosize; p->to.reg = REGSP; + p->spadj = autosize; } break; @@ -527,9 +530,20 @@ noops(void) p->from.reg = REGSP; p->to.type = D_REG; p->to.reg = REGPC; + // no spadj because it doesn't fall through } break; + case AADD: + if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP) + p->spadj = -p->from.offset; + break; + + case ASUB: + if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP) + p->spadj = p->from.offset; + break; + case ADIV: case ADIVU: case AMOD: @@ -635,6 +649,7 @@ noops(void) p->reg = NREG; p->to.type = D_REG; p->to.reg = REGSP; + p->spadj = -8; /* SUB $8,SP */ q1->as = ASUB; @@ -644,6 +659,7 @@ noops(void) q1->reg = NREG; q1->to.type = D_REG; q1->to.reg = REGSP; + q1->spadj = 8; break; case AMOVW: @@ -653,6 +669,12 @@ noops(void) if(a->type == D_CONST && ((a->name == D_NONE && a->reg == REGSP) || a->name == D_AUTO || a->name == D_PARAM) && (a->offset & 3)) diag("SP offset not multiple of 4"); } + if((p->scond & C_WBIT) && p->to.type == D_OREG && p->to.reg == REGSP) + p->spadj = -p->to.offset; + if((p->scond & C_PBIT) && p->from.type == D_OREG && p->from.reg == REGSP && p->to.reg != REGPC) + p->spadj = -p->from.offset; + if(p->from.type == D_CONST && p->from.reg == REGSP && p->to.type == D_REG && p->to.reg == REGSP) + p->spadj = -p->from.offset; break; case AMOVB: case AMOVBU: diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index 5b778d777..f252f9fc5 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -41,15 +41,26 @@ #endif char *noname = "<none>"; -char thechar = '5'; char *thestring = "arm"; +Header headers[] = { + "noheader", Hnoheader, + "risc", Hrisc, + "plan9", Hplan9x32, + "netbsd", Hnetbsd, + "ixp1200", Hixp1200, + "ipaq", Hipaq, + "linux", Hlinux, + 0, 0 +}; + /* - * -H1 -T0x10005000 -R4 is aif for risc os - * -H2 -T4128 -R4096 is plan9 format - * -H3 -T0xF0000020 -R4 is NetBSD format - * -H4 is IXP1200 (raw) - * -H5 -T0xC0008010 -R1024 is ipaq + * -Hrisc -T0x10005000 -R4 is aif for risc os + * -Hplan9 -T4128 -R4096 is plan9 format + * -Hnetbsd -T0xF0000020 -R4 is NetBSD format + * -Hixp1200 is IXP1200 (raw) + * -Hipaq -T0xC0008010 -R1024 is ipaq + * -Hlinux -Tx -Rx is linux elf */ static char* @@ -119,7 +130,7 @@ main(int argc, char *argv[]) rpath = EARGF(usage()); break; case 'H': - HEADTYPE = atolwhex(EARGF(usage())); + HEADTYPE = headtype(EARGF(usage())); /* do something about setting INITTEXT */ break; case 'V': @@ -133,25 +144,23 @@ main(int argc, char *argv[]) usage(); libinit(); - if(rpath == nil) - rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch); if(!debug['9'] && !debug['U'] && !debug['B']) debug[DEFAULT] = 1; if(HEADTYPE == -1) { if(debug['U']) - HEADTYPE = 0; + HEADTYPE = Hnoheader; if(debug['B']) - HEADTYPE = 1; + HEADTYPE = Hrisc; if(debug['9']) - HEADTYPE = 2; - HEADTYPE = 6; + HEADTYPE = Hplan9x32; + HEADTYPE = Hlinux; } switch(HEADTYPE) { default: diag("unknown -H option"); errorexit(); - case 0: /* no header */ + case Hnoheader: /* no header */ HEADR = 0L; if(INITTEXT == -1) INITTEXT = 0; @@ -160,7 +169,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4; break; - case 1: /* aif for risc os */ + case Hrisc: /* aif for risc os */ HEADR = 128L; if(INITTEXT == -1) INITTEXT = 0x10005000 + HEADR; @@ -169,7 +178,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4; break; - case 2: /* plan 9 */ + case Hplan9x32: /* plan 9 */ HEADR = 32L; if(INITTEXT == -1) INITTEXT = 4128; @@ -178,7 +187,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4096; break; - case 3: /* boot for NetBSD */ + case Hnetbsd: /* boot for NetBSD */ HEADR = 32L; if(INITTEXT == -1) INITTEXT = 0xF0000020L; @@ -187,7 +196,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4096; break; - case 4: /* boot for IXP1200 */ + case Hixp1200: /* boot for IXP1200 */ HEADR = 0L; if(INITTEXT == -1) INITTEXT = 0x0; @@ -196,7 +205,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4; break; - case 5: /* boot for ipaq */ + case Hipaq: /* boot for ipaq */ HEADR = 16L; if(INITTEXT == -1) INITTEXT = 0xC0008010; @@ -205,7 +214,7 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 1024; break; - case 6: /* arm elf */ + case Hlinux: /* arm elf */ debug['d'] = 1; // no dynamic linking elfinit(); HEADR = ELFRESERVE; @@ -265,11 +274,13 @@ main(int argc, char *argv[]) follow(); softfloat(); noops(); + dostkcheck(); span(); pclntab(); symtab(); dodata(); address(); + doweak(); reloc(); asmb(); undef(); diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c index 8b3135e06..625b66812 100644 --- a/src/cmd/5l/optab.c +++ b/src/cmd/5l/optab.c @@ -253,5 +253,8 @@ Optab optab[] = { ATST, C_REG, C_NONE, C_NONE, 90, 4, 0 }, + { ALDREXD, C_SOREG,C_NONE, C_REG, 91, 4, 0 }, + { ASTREXD, C_SOREG,C_REG, C_REG, 92, 4, 0 }, + { AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, }; diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c index e16b34171..7e1ba6a09 100644 --- a/src/cmd/5l/pass.c +++ b/src/cmd/5l/pass.c @@ -35,18 +35,6 @@ static void xfol(Prog*, Prog**); -void -undef(void) -{ - int i; - Sym *s; - - for(i=0; i<NHASH; i++) - for(s = hash[i]; s != S; s = s->hash) - if(s->type == SXREF) - diag("%s: not defined", s->name); -} - Prog* brchain(Prog *p) { diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c index 220140f43..482d3e90a 100644 --- a/src/cmd/5l/span.c +++ b/src/cmd/5l/span.c @@ -1054,6 +1054,8 @@ buildop(void) case ALDREX: case ASTREX: + case ALDREXD: + case ASTREXD: case ATST: break; } |