summaryrefslogtreecommitdiff
path: root/src/cmd/5l
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
committerOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
commit50104cc32a498f7517a51c8dc93106c51c7a54b4 (patch)
tree47af80be259cc7c45d0eaec7d42e61fa38c8e4fb /src/cmd/5l
parentc072558b90f1bbedc2022b0f30c8b1ac4712538e (diff)
downloadgolang-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.h3
-rw-r--r--src/cmd/5l/asm.c49
-rw-r--r--src/cmd/5l/doc.go2
-rw-r--r--src/cmd/5l/l.h5
-rw-r--r--src/cmd/5l/list.c4
-rw-r--r--src/cmd/5l/noop.c24
-rw-r--r--src/cmd/5l/obj.c51
-rw-r--r--src/cmd/5l/optab.c3
-rw-r--r--src/cmd/5l/pass.c12
-rw-r--r--src/cmd/5l/span.c2
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;
}