summaryrefslogtreecommitdiff
path: root/src/cmd/5l
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-06-30 15:34:22 +0200
committerOndřej Surý <ondrej@sury.org>2011-06-30 15:34:22 +0200
commitd39f5aa373a4422f7a5f3ee764fb0f6b0b719d61 (patch)
tree1833f8b72a4b3a8f00d0d143b079a8fcad01c6ae /src/cmd/5l
parent8652e6c371b8905498d3d314491d36c58d5f68d5 (diff)
downloadgolang-upstream/58.tar.gz
Imported Upstream version 58upstream/58
Diffstat (limited to 'src/cmd/5l')
-rw-r--r--src/cmd/5l/5.out.h4
-rw-r--r--src/cmd/5l/Makefile1
-rw-r--r--src/cmd/5l/asm.c311
-rw-r--r--src/cmd/5l/l.h25
-rw-r--r--src/cmd/5l/list.c7
-rw-r--r--src/cmd/5l/noop.c385
-rw-r--r--src/cmd/5l/obj.c33
-rw-r--r--src/cmd/5l/optab.c82
-rw-r--r--src/cmd/5l/pass.c20
-rw-r--r--src/cmd/5l/prof.c9
-rw-r--r--src/cmd/5l/softfloat.c2
-rw-r--r--src/cmd/5l/span.c236
-rw-r--r--src/cmd/5l/thumb.c1658
13 files changed, 169 insertions, 2604 deletions
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index 002b46d45..cf86ae48b 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -53,8 +53,6 @@
#define REGLINK 14
#define REGPC 15
-#define REGTMPT 7 /* used by the loader for thumb code */
-
#define NFREG 8
#define FREGRET 0
#define FREGEXT 7
@@ -126,6 +124,8 @@ enum as
AMULD,
ADIVF,
ADIVD,
+ ASQRTF,
+ ASQRTD,
ASRL,
ASRA,
diff --git a/src/cmd/5l/Makefile b/src/cmd/5l/Makefile
index c11ebe990..9f4a192aa 100644
--- a/src/cmd/5l/Makefile
+++ b/src/cmd/5l/Makefile
@@ -22,7 +22,6 @@ OFILES=\
optab.$O\
pass.$O\
prof.$O\
- thumb.$O\
softfloat.$O\
span.$O\
symtab.$O\
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);
+}
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index f3c9d839d..182f3e738 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -144,8 +144,6 @@ struct Sym
int32 sig;
int32 size;
uchar special;
- uchar thumb; // thumb code
- uchar foreign; // called by arm if thumb, by thumb if arm
uchar fnptr; // used as fn ptr
Sym* hash; // in hash table
Sym* allsym; // in all symbol list
@@ -208,7 +206,6 @@ enum
LFROM = 1<<0,
LTO = 1<<1,
LPOOL = 1<<2,
- V4 = 1<<3, /* arm v4 arch */
C_NONE = 0,
C_REG,
@@ -221,21 +218,16 @@ enum
C_RCON, /* 0xff rotated */
C_NCON, /* ~RCON */
C_SCON, /* 0xffff */
- C_BCON, /* thumb */
C_LCON,
C_ZFCON,
C_SFCON,
C_LFCON,
- C_GCON, /* thumb */
C_RACON,
- C_SACON, /* thumb */
C_LACON,
- C_GACON, /* thumb */
C_SBRA,
C_LBRA,
- C_GBRA, /* thumb */
C_HAUTO, /* halfword insn offset (-0xff to 0xff) */
C_FAUTO, /* float insn offset (0 to 0x3fc, word aligned) */
@@ -250,12 +242,10 @@ enum
C_ROREG,
C_SROREG, /* both S and R */
C_LOREG,
- C_GOREG, /* thumb */
C_PC,
C_SP,
C_HREG,
- C_OFFPC, /* thumb */
C_ADDR, /* reference to relocatable address */
@@ -287,9 +277,6 @@ EXTERN union
#define cbuf u.obuf
#define xbuf u.ibuf
-#define setarch(p) if((p)->as==ATEXT) thumb=(p)->reg&ALLTHUMBS
-#define setthumb(p) if((p)->as==ATEXT) seenthumb|=(p)->reg&ALLTHUMBS
-
#ifndef COFFCVT
EXTERN int32 HEADR; /* length of header */
@@ -319,7 +306,6 @@ EXTERN int nerrors;
EXTERN int32 instoffset;
EXTERN Opcross opcross[8];
EXTERN Oprang oprange[ALAST];
-EXTERN Oprang thumboprange[ALAST];
EXTERN char* outfile;
EXTERN int32 pc;
EXTERN uchar repop[ALAST];
@@ -333,14 +319,10 @@ EXTERN int version;
EXTERN char xcmp[C_GOK+1][C_GOK+1];
EXTERN Prog zprg;
EXTERN int dtype;
-EXTERN int armv4;
-EXTERN int thumb;
-EXTERN int seenthumb;
EXTERN int armsize;
extern char* anames[];
extern Optab optab[];
-extern Optab thumboptab[];
void addpool(Prog*, Adr*);
EXTERN Prog* blitrl;
@@ -368,17 +350,13 @@ int Oconv(Fmt*);
int Pconv(Fmt*);
int Sconv(Fmt*);
int aclass(Adr*);
-int thumbaclass(Adr*, Prog*);
void addhist(int32, int);
Prog* appendp(Prog*);
void asmb(void);
-void asmthumbmap(void);
void asmout(Prog*, Optab*, int32*);
-void thumbasmout(Prog*, Optab*);
int32 atolwhex(char*);
Prog* brloop(Prog*);
void buildop(void);
-void thumbbuildop(void);
void buildrep(int, int);
void cflush(void);
int chipzero(Ieee*);
@@ -442,9 +420,6 @@ int32 immaddr(int32);
int32 opbra(int, int);
int brextra(Prog*);
int isbranch(Prog*);
-int fnpinc(Sym *);
-int fninc(Sym *);
-void thumbcount(void);
void fnptrs(void);
void doelf(void);
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index 2ae25d491..fa838215b 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -412,7 +412,6 @@ static char*
cnames[] =
{
[C_ADDR] = "C_ADDR",
- [C_BCON] = "C_BCON",
[C_FAUTO] = "C_FAUTO",
[C_ZFCON] = "C_SFCON",
[C_SFCON] = "C_SFCON",
@@ -420,11 +419,7 @@ cnames[] =
[C_FCR] = "C_FCR",
[C_FOREG] = "C_FOREG",
[C_FREG] = "C_FREG",
- [C_GACON] = "C_GACON",
- [C_GBRA] = "C_GBRA",
- [C_GCON] = "C_GCON",
[C_GOK] = "C_GOK",
- [C_GOREG] = "C_GOREG",
[C_HAUTO] = "C_HAUTO",
[C_HFAUTO] = "C_HFAUTO",
[C_HFOREG] = "C_HFOREG",
@@ -437,7 +432,6 @@ cnames[] =
[C_LOREG] = "C_LOREG",
[C_NCON] = "C_NCON",
[C_NONE] = "C_NONE",
- [C_OFFPC] = "C_OFFPC",
[C_PC] = "C_PC",
[C_PSR] = "C_PSR",
[C_RACON] = "C_RACON",
@@ -445,7 +439,6 @@ cnames[] =
[C_REG] = "C_REG",
[C_REGREG] = "C_REGREG",
[C_ROREG] = "C_ROREG",
- [C_SACON] = "C_SACON",
[C_SAUTO] = "C_SAUTO",
[C_SBRA] = "C_SBRA",
[C_SCON] = "C_SCON",
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index bdcc3cad8..e7c2db5f2 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -47,74 +47,11 @@ static Sym* sym_modu;
static void setdiv(int);
-static Prog *
-movrr(Prog *q, int rs, int rd, Prog *p)
-{
- if(q == nil)
- q = prg();
- q->as = AMOVW;
- q->line = p->line;
- q->from.type = D_REG;
- q->from.reg = rs;
- q->to.type = D_REG;
- q->to.reg = rd;
- q->link = p->link;
- return q;
-}
-
-static Prog *
-fnret(Prog *q, int rs, int foreign, Prog *p)
-{
- q = movrr(q, rs, REGPC, p);
- if(foreign){ // BX rs
- q->as = ABXRET;
- q->from.type = D_NONE;
- q->from.reg = NREG;
- q->to.reg = rs;
- }
- return q;
-}
-
-static Prog *
-aword(int32 w, Prog *p)
-{
- Prog *q;
-
- q = prg();
- q->as = AWORD;
- q->line = p->line;
- q->from.type = D_NONE;
- q->reg = NREG;
- q->to.type = D_CONST;
- q->to.offset = w;
- q->link = p->link;
- p->link = q;
- return q;
-}
-
-static Prog *
-adword(int32 w1, int32 w2, Prog *p)
-{
- Prog *q;
-
- q = prg();
- q->as = ADWORD;
- q->line = p->line;
- q->from.type = D_CONST;
- q->from.offset = w1;
- q->reg = NREG;
- q->to.type = D_CONST;
- q->to.offset = w2;
- q->link = p->link;
- p->link = q;
- return q;
-}
-
void
noops(void)
{
- Prog *p, *q, *q1, *q2;
- int o, foreign;
+ Prog *p, *q, *q1;
+ int o;
Prog *pmorestack;
Sym *symmorestack;
@@ -140,8 +77,6 @@ noops(void)
q = P;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
-
switch(p->as) {
case ATEXT:
p->mark |= LEAF;
@@ -206,7 +141,6 @@ noops(void)
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
o = p->as;
switch(o) {
case ATEXT:
@@ -224,54 +158,12 @@ noops(void)
Bflush(&bso);
cursym->text->mark |= LEAF;
}
-#ifdef CALLEEBX
- if(p->from.sym->foreign){
- if(thumb)
- // 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
- p = aword(0x4778, p); // thumb bx pc and 2 bytes padding
- }
-#endif
if(cursym->text->mark & LEAF) {
cursym->leaf = 1;
if(!autosize)
break;
}
- if(thumb){
- if(!(p->reg & NOSPLIT))
- diag("stack splitting not supported in thumb");
- if(!(cursym->text->mark & LEAF)){
- q = movrr(nil, REGLINK, REGTMPT-1, p);
- p->link = q;
- q1 = prg();
- q1->as = AMOVW;
- q1->line = p->line;
- q1->from.type = D_REG;
- q1->from.reg = REGTMPT-1;
- q1->to.type = D_OREG;
- q1->to.name = D_NONE;
- q1->to.reg = REGSP;
- q1->to.offset = 0;
- q1->link = q->link;
- q->link = q1;
- }
- if(autosize){
- q2 = prg();
- q2->as = ASUB;
- q2->line = p->line;
- q2->from.type = D_CONST;
- q2->from.offset = autosize;
- q2->to.type = D_REG;
- q2->to.reg = REGSP;
- q2->link = p->link;
- p->link = q2;
- }
- break;
- }
-
if(p->reg & NOSPLIT) {
q1 = prg();
q1->as = AMOVW;
@@ -432,16 +324,9 @@ noops(void)
case ARET:
nocache(p);
- foreign = seenthumb && (cursym->foreign || cursym->fnptr);
-// print("%s %d %d\n", cursym->name, cursym->foreign, cursym->fnptr);
if(cursym->text->mark & LEAF) {
if(!autosize) {
- if(thumb){
- p = fnret(p, REGLINK, foreign, p);
- break;
- }
-// if(foreign) print("ABXRET 1 %s\n", cursym->name);
- p->as = foreign ? ABXRET : AB;
+ p->as = AB;
p->from = zprg.from;
p->to.type = D_OREG;
p->to.offset = 0;
@@ -449,95 +334,16 @@ noops(void)
break;
}
}
- if(thumb){
- diag("thumb not maintained");
- errorexit();
- if(cursym->text->mark & LEAF){
- if(autosize){
- p->as = AADD;
- p->from.type = D_CONST;
- p->from.offset = autosize;
- p->to.type = D_REG;
- p->to.reg = REGSP;
- q = nil;
- }
- else
- q = p;
- q = fnret(q, REGLINK, foreign, p);
- if(q != p)
- p->link = q;
- }
- else{
- p->as = AMOVW;
- p->from.type = D_OREG;
- p->from.name = D_NONE;
- p->from.reg = REGSP;
- p->from.offset = 0;
- p->to.type = D_REG;
- p->to.reg = REGTMPT-1;
- if(autosize){
- q = prg();
- q->as = AADD;
- q->from.type = D_CONST;
- q->from.offset = autosize;
- q->to.type = D_REG;
- q->to.reg = REGSP;
- q->link = p->link;
- p->link = q;
- }
- else
- q = p;
- q1 = fnret(nil, REGTMPT-1, foreign, p);
- q1->link = q->link;
- q->link = q1;
- }
- break;
- }
- if(foreign) {
- diag("foreign not maintained");
- errorexit();
-// if(foreign) print("ABXRET 3 %s\n", cursym->name);
-#define R 1
- p->as = AMOVW;
- p->from.type = D_OREG;
- p->from.name = D_NONE;
- p->from.reg = REGSP;
- p->from.offset = 0;
- p->to.type = D_REG;
- p->to.reg = R;
- q = prg();
- q->as = AADD;
- q->scond = p->scond;
- q->line = p->line;
- q->from.type = D_CONST;
- q->from.offset = autosize;
- q->to.type = D_REG;
- q->to.reg = REGSP;
- q->link = p->link;
- p->link = q;
- q1 = prg();
- q1->as = ABXRET;
- q1->scond = p->scond;
- q1->line = p->line;
- q1->to.type = D_OREG;
- q1->to.offset = 0;
- q1->to.reg = R;
- q1->link = q->link;
- q->link = q1;
-#undef R
- }
- else {
- p->as = AMOVW;
- p->scond |= C_PBIT;
- p->from.type = D_OREG;
- p->from.offset = autosize;
- p->from.reg = REGSP;
- p->to.type = D_REG;
- p->to.reg = REGPC;
- // If there are instructions following
- // this ARET, they come from a branch
- // with the same stackframe, so no spadj.
- }
+ p->as = AMOVW;
+ p->scond |= C_PBIT;
+ p->from.type = D_OREG;
+ p->from.offset = autosize;
+ p->from.reg = REGSP;
+ p->to.type = D_REG;
+ p->to.reg = REGPC;
+ // If there are instructions following
+ // this ARET, they come from a branch
+ // with the same stackframe, so no spadj.
break;
case AADD:
@@ -589,7 +395,7 @@ noops(void)
if(q1->reg == NREG)
p->from.reg = q1->to.reg;
p->to.type = D_REG;
- p->to.reg = prog_div->from.sym->thumb ? REGTMPT : REGTMP;
+ p->to.reg = REGTMP;
p->to.offset = 0;
/* CALL appropriate */
@@ -598,14 +404,7 @@ noops(void)
p->link = q;
p = q;
-#ifdef CALLEEBX
p->as = ABL;
-#else
- if(prog_div->from.sym->thumb)
- p->as = thumb ? ABL : ABX;
- else
- p->as = thumb ? ABX : ABL;
-#endif
p->line = q1->line;
p->to.type = D_BRANCH;
p->cond = p;
@@ -637,7 +436,7 @@ noops(void)
p->as = AMOVW;
p->line = q1->line;
p->from.type = D_REG;
- p->from.reg = prog_div->from.sym->thumb ? REGTMPT : REGTMP;
+ p->from.reg = REGTMP;
p->from.offset = 0;
p->to.type = D_REG;
p->to.reg = q1->to.reg;
@@ -669,12 +468,6 @@ noops(void)
break;
case AMOVW:
- if(thumb){
- Adr *a = &p->from;
-
- 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)
@@ -682,136 +475,6 @@ noops(void)
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:
- case AMOVH:
- case AMOVHU:
- if(thumb){
- if(p->from.type == D_OREG && (p->from.name == D_AUTO || p->from.name == D_PARAM || (p->from.name == D_CONST && p->from.reg == REGSP))){
- q = prg();
- *q = *p;
- if(p->from.name == D_AUTO)
- q->from.offset += autosize;
- else if(p->from.name == D_PARAM)
- q->from.offset += autosize+4;
- q->from.name = D_NONE;
- q->from.reg = REGTMPT;
- p = movrr(p, REGSP, REGTMPT, p);
- q->link = p->link;
- p->link = q;
- }
- if(p->to.type == D_OREG && (p->to.name == D_AUTO || p->to.name == D_PARAM || (p->to.name == D_CONST && p->to.reg == REGSP))){
- q = prg();
- *q = *p;
- if(p->to.name == D_AUTO)
- q->to.offset += autosize;
- else if(p->to.name == D_PARAM)
- q->to.offset += autosize+4;
- q->to.name = D_NONE;
- q->to.reg = REGTMPT;
- p = movrr(p, REGSP, REGTMPT, p);
- q->link = p->link;
- p->link = q;
- if(q->to.offset < 0 || q->to.offset > 255){ // complicated
- p->to.reg = REGTMPT+1; // mov sp, r8
- q1 = prg();
- q1->line = p->line;
- q1->as = AMOVW;
- q1->from.type = D_CONST;
- q1->from.offset = q->to.offset;
- q1->to.type = D_REG;
- q1->to.reg = REGTMPT; // mov $o, r7
- p->link = q1;
- q1->link = q;
- q1 = prg();
- q1->line = p->line;
- q1->as = AADD;
- q1->from.type = D_REG;
- q1->from.reg = REGTMPT+1;
- q1->to.type = D_REG;
- q1->to.reg = REGTMPT; // add r8, r7
- p->link->link = q1;
- q1->link = q;
- q->to.offset = 0; // mov* r, 0(r7)
- /* phew */
- }
- }
- }
- break;
- case AMOVM:
- if(thumb){
- if(p->from.type == D_OREG){
- if(p->from.offset == 0)
- p->from.type = D_REG;
- else
- diag("non-zero AMOVM offset");
- }
- else if(p->to.type == D_OREG){
- if(p->to.offset == 0)
- p->to.type = D_REG;
- else
- diag("non-zero AMOVM offset");
- }
- }
- break;
- case AB:
- if(thumb && p->to.type == D_OREG){
- if(p->to.offset == 0){
- p->as = AMOVW;
- p->from.type = D_REG;
- p->from.reg = p->to.reg;
- p->to.type = D_REG;
- p->to.reg = REGPC;
- }
- else{
- p->as = AADD;
- p->from.type = D_CONST;
- p->from.offset = p->to.offset;
- p->reg = p->to.reg;
- p->to.type = D_REG;
- p->to.reg = REGTMPT-1;
- q = prg();
- q->as = AMOVW;
- q->line = p->line;
- q->from.type = D_REG;
- q->from.reg = REGTMPT-1;
- q->to.type = D_REG;
- q->to.reg = REGPC;
- q->link = p->link;
- p->link = q;
- }
- }
- if(seenthumb && !thumb && p->to.type == D_OREG && p->to.reg == REGLINK){
- // print("warn %s: b (R%d) assuming a return\n", cursym->name, p->to.reg);
- p->as = ABXRET;
- }
- break;
- case ABL:
- case ABX:
- if(thumb && p->to.type == D_OREG){
- if(p->to.offset == 0){
- p->as = o;
- p->from.type = D_NONE;
- p->to.type = D_REG;
- }
- else{
- p->as = AADD;
- p->from.type = D_CONST;
- p->from.offset = p->to.offset;
- p->reg = p->to.reg;
- p->to.type = D_REG;
- p->to.reg = REGTMPT-1;
- q = prg();
- q->as = o;
- q->line = p->line;
- q->from.type = D_NONE;
- q->to.type = D_REG;
- q->to.reg = REGTMPT-1;
- q->link = p->link;
- p->link = q;
- }
- }
- break;
}
}
}
@@ -876,13 +539,19 @@ setdiv(int as)
Prog *p = nil;
switch(as){
- case ADIV: p = prog_div; break;
- case ADIVU: p = prog_divu; break;
- case AMOD: p = prog_mod; break;
- case AMODU: p = prog_modu; break;
+ case ADIV:
+ p = prog_div;
+ break;
+ case ADIVU:
+ p = prog_divu;
+ break;
+ case AMOD:
+ p = prog_mod;
+ break;
+ case AMODU:
+ p = prog_modu;
+ break;
}
- if(thumb != p->from.sym->thumb)
- p->from.sym->foreign = 1;
}
void
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index c4a2bfc3f..dd3a7329a 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -67,6 +67,7 @@ static char*
linkername[] =
{
"runtime.softfloat",
+ "math.sqrtGoC",
};
void
@@ -219,7 +220,7 @@ main(int argc, char *argv[])
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
- INITTEXT = 0x8000 + HEADR;
+ INITTEXT = 0x10000 + HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
@@ -241,7 +242,6 @@ main(int argc, char *argv[])
zprg.from.reg = NREG;
zprg.to = zprg.from;
buildop();
- thumbbuildop(); // could build on demand
histgen = 0;
pc = 0;
dtype = 4;
@@ -285,10 +285,8 @@ main(int argc, char *argv[])
asmb();
undef();
- if(debug['c']){
- thumbcount();
+ if(debug['c'])
print("ARM size = %d\n", armsize);
- }
if(debug['v']) {
Bprint(&bso, "%5.2f cpu time\n", cputime());
Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
@@ -405,14 +403,12 @@ nopout(Prog *p)
p->to.type = D_NONE;
}
-static void puntfp(Prog *);
-
void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{
int32 ipc;
Prog *p;
- Sym *h[NSYM], *s, *di;
+ Sym *h[NSYM], *s;
int v, o, r, skip;
uint32 sig;
char *name;
@@ -424,7 +420,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
lastp = nil;
ntext = 0;
eof = Boffset(f) + len;
- di = S;
src[0] = 0;
newloop:
@@ -622,8 +617,6 @@ loop:
else
textp = s;
etextp = s;
- setarch(p);
- setthumb(p);
p->align = 4;
autosize = (p->to.offset+3L) & ~3L;
p->to.offset = autosize;
@@ -631,7 +624,6 @@ loop:
s->type = STEXT;
s->text = p;
s->value = pc;
- s->thumb = thumb;
lastp = p;
p->pc = pc;
pc++;
@@ -673,13 +665,9 @@ loop:
case AMULD:
case ADIVF:
case ADIVD:
- if(thumb)
- puntfp(p);
goto casedef;
case AMOVF:
- if(thumb)
- puntfp(p);
if(skip)
goto casedef;
@@ -701,8 +689,6 @@ loop:
goto casedef;
case AMOVD:
- if(thumb)
- puntfp(p);
if(skip)
goto casedef;
@@ -758,17 +744,6 @@ prg(void)
return p;
}
-static void
-puntfp(Prog *p)
-{
- USED(p);
- /* floating point - punt for now */
- cursym->text->reg = NREG; /* ARM */
- cursym->thumb = 0;
- thumb = 0;
- // print("%s: generating ARM code (contains floating point ops %d)\n", curtext->from.sym->name, p->line);
-}
-
Prog*
appendp(Prog *q)
{
diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c
index 625b66812..514786f85 100644
--- a/src/cmd/5l/optab.c
+++ b/src/cmd/5l/optab.c
@@ -77,7 +77,6 @@ Optab optab[] =
{ ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0 },
{ AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0 },
- { AWORD, C_NONE, C_NONE, C_GCON, 11, 4, 0 },
{ AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0 },
{ AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0 },
@@ -117,18 +116,6 @@ Optab optab[] =
{ AMOVBU, C_SAUTO,C_NONE, C_REG, 21, 4, REGSP },
{ AMOVBU, C_SOREG,C_NONE, C_REG, 21, 4, 0 },
- { AMOVB, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP },
- { AMOVB, C_SOREG,C_NONE, C_REG, 22, 12, 0 },
- { AMOVH, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP },
- { AMOVH, C_SOREG,C_NONE, C_REG, 22, 12, 0 },
- { AMOVHU, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP },
- { AMOVHU, C_SOREG,C_NONE, C_REG, 22, 12, 0 },
-
- { AMOVH, C_REG, C_NONE, C_SAUTO, 23, 12, REGSP },
- { AMOVH, C_REG, C_NONE, C_SOREG, 23, 12, 0 },
- { AMOVHU, C_REG, C_NONE, C_SAUTO, 23, 12, REGSP },
- { AMOVHU, C_REG, C_NONE, C_SOREG, 23, 12, 0 },
-
{ AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO },
{ AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO },
{ AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO },
@@ -146,23 +133,6 @@ Optab optab[] =
{ AMOVBU, C_LOREG,C_NONE, C_REG, 31, 8, 0, LFROM },
{ AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM },
- { AMOVB, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM },
- { AMOVB, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM },
- { AMOVB, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM },
- { AMOVH, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM },
- { AMOVH, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM },
- { AMOVH, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM },
- { AMOVHU, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM },
- { AMOVHU, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM },
- { AMOVHU, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM },
-
- { AMOVH, C_REG, C_NONE, C_LAUTO, 33, 24, REGSP, LTO },
- { AMOVH, C_REG, C_NONE, C_LOREG, 33, 24, 0, LTO },
- { AMOVH, C_REG, C_NONE, C_ADDR, 67, 24, 0, LTO },
- { AMOVHU, C_REG, C_NONE, C_LAUTO, 33, 24, REGSP, LTO },
- { AMOVHU, C_REG, C_NONE, C_LOREG, 33, 24, 0, LTO },
- { AMOVHU, C_REG, C_NONE, C_ADDR, 67, 24, 0, LTO },
-
{ AMOVW, C_LACON,C_NONE, C_REG, 34, 8, REGSP, LFROM },
{ AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0 },
@@ -210,29 +180,35 @@ Optab optab[] =
{ ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0 },
{ ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0 },
- { AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, V4 },
- { AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, V4 },
- { AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, V4 },
- { AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, V4 },
-
- { AMOVB, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, V4 },
- { AMOVB, C_HOREG,C_NONE, C_REG, 71, 4, 0, V4 },
- { AMOVH, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, V4 },
- { AMOVH, C_HOREG,C_NONE, C_REG, 71, 4, 0, V4 },
- { AMOVHU, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, V4 },
- { AMOVHU, C_HOREG,C_NONE, C_REG, 71, 4, 0, V4 },
-
- { AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO|V4 },
- { AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO|V4 },
- { AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO|V4 },
- { AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO|V4 },
-
- { AMOVB, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 },
- { AMOVB, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 },
- { AMOVH, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 },
- { AMOVH, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 },
- { AMOVHU, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 },
- { AMOVHU, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 },
+ { AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0 },
+ { AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0 },
+ { AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0 },
+ { AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0 },
+
+ { AMOVB, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, 0 },
+ { AMOVB, C_HOREG,C_NONE, C_REG, 71, 4, 0, 0 },
+ { AMOVH, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, 0 },
+ { AMOVH, C_HOREG,C_NONE, C_REG, 71, 4, 0, 0 },
+ { AMOVHU, C_HAUTO,C_NONE, C_REG, 71, 4, REGSP, 0 },
+ { AMOVHU, C_HOREG,C_NONE, C_REG, 71, 4, 0, 0 },
+
+ { AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO },
+ { AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO },
+ { AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO },
+ { AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO },
+ { AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO },
+ { AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO },
+
+ { AMOVB, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
+ { AMOVB, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
+ { AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
+ { AMOVH, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
+ { AMOVH, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
+ { AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
+ { AMOVHU, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM },
+ { AMOVHU, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM },
+ { AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM },
+
{ ALDREX, C_SOREG,C_NONE, C_REG, 77, 4, 0 },
{ ASTREX, C_SOREG,C_REG, C_REG, 78, 4, 0 },
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index 7e1ba6a09..194a1ed5f 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -100,7 +100,6 @@ xfol(Prog *p, Prog **last)
loop:
if(p == P)
return;
- setarch(p);
a = p->as;
if(a == AB) {
q = p->cond;
@@ -210,14 +209,7 @@ patch(void)
vexit = s->value;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
a = p->as;
- if(seenthumb && a == ABL){
- // if((s = p->to.sym) != S && (s1 = curtext->from.sym) != S)
- // print("%s calls %s\n", s1->name, s->name);
- if((s = p->to.sym) != S && s->thumb != cursym->thumb)
- s->foreign = 1;
- }
if((a == ABL || a == ABX || a == AB || a == ARET) &&
p->to.type != D_BRANCH && p->to.sym != S) {
s = p->to.sym;
@@ -254,19 +246,7 @@ patch(void)
for(cursym = textp; cursym != nil; cursym = cursym->next) {
for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
a = p->as;
- if(seenthumb && a == ABL) {
-#ifdef CALLEEBX
- if(0)
- {}
-#else
- if((s = p->to.sym) != S && (s->foreign || s->fnptr))
- p->as = ABX;
-#endif
- else if(p->to.type == D_OREG)
- p->as = ABX;
- }
if(p->cond != P) {
p->cond = brloop(p->cond);
if(p->cond != P)
diff --git a/src/cmd/5l/prof.c b/src/cmd/5l/prof.c
index ad115a8ca..48ad2dc59 100644
--- a/src/cmd/5l/prof.c
+++ b/src/cmd/5l/prof.c
@@ -47,7 +47,6 @@ doprof1(void)
s = lookup("__mcount", 0);
n = 1;
for(p = firstp->link; p != P; p = p->link) {
- setarch(p);
if(p->as == ATEXT) {
q = prg();
q->line = p->line;
@@ -74,7 +73,7 @@ doprof1(void)
p->from.sym = s;
p->from.offset = n*4 + 4;
p->to.type = D_REG;
- p->to.reg = thumb ? REGTMPT : REGTMP;
+ p->to.reg = REGTMP;
q = prg();
q->line = p->line;
@@ -86,7 +85,7 @@ doprof1(void)
p->from.type = D_CONST;
p->from.offset = 1;
p->to.type = D_REG;
- p->to.reg = thumb ? REGTMPT : REGTMP;
+ p->to.reg = REGTMP;
q = prg();
q->line = p->line;
@@ -96,7 +95,7 @@ doprof1(void)
p = q;
p->as = AMOVW;
p->from.type = D_REG;
- p->from.reg = thumb ? REGTMPT : REGTMP;
+ p->from.reg = REGTMP;
p->to.type = D_OREG;
p->to.name = D_EXTERN;
p->to.sym = s;
@@ -143,7 +142,6 @@ doprof2(void)
ps4 = P;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
- setarch(p);
if(cursym == s2) {
ps2 = p;
p->reg = 1;
@@ -155,7 +153,6 @@ doprof2(void)
}
for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
if(p->as == ATEXT) {
if(p->reg & NOPROF) {
for(;;) {
diff --git a/src/cmd/5l/softfloat.c b/src/cmd/5l/softfloat.c
index 03d8c6d26..4f799d17e 100644
--- a/src/cmd/5l/softfloat.c
+++ b/src/cmd/5l/softfloat.c
@@ -54,6 +54,8 @@ softfloat(void)
case AMULD:
case ADIVF:
case ADIVD:
+ case ASQRTF:
+ case ASQRTD:
goto soft;
default:
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 482d3e90a..eb79f6b5a 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -50,86 +50,6 @@ isbranch(Prog *p)
}
static int
-ispad(Prog *p)
-{
- if(p->as != AMOVW)
- return 0;
- if(p->from.type != D_REG || p->from.reg != REGTMP)
- return 0;
- if(p->to.type != D_REG || p->to.reg != REGTMP)
- return 0;
- return 1;
-}
-
-int
-fninc(Sym *s)
-{
- if(thumb){
- if(s->thumb){
- if(s->foreign)
- return 8;
- else
- return 0;
- }
- else{
- if(s->foreign)
- return 0;
- else
- diag("T A !foreign in fninc");
- }
- }
- else{
- if(s->thumb){
- if(s->foreign)
- return 0;
- else
- diag("A T !foreign in fninc");
- }
- else{
- if(s->foreign)
- return 4;
- else
- return 0;
- }
- }
- return 0;
-}
-
-int
-fnpinc(Sym *s)
-{
- if(!s->fnptr){ // a simplified case BX O(R) -> BL O(R)
- if(!debug['f'])
- diag("fnptr == 0 in fnpinc");
- if(s->foreign)
- diag("bad usage in fnpinc %s %d %d", s->name, s->foreign, s->thumb);
- return 0;
- }
- /* 0, 1, 2, 3 squared */
- if(s->thumb)
- return s->foreign ? 9 : 1;
- else
- return s->foreign ? 4 : 0;
-}
-
-static Prog *
-pad(Prog *p, int pc)
-{
- Prog *q;
-
- q = prg();
- q->as = AMOVW;
- q->line = p->line;
- q->from.type = D_REG;
- q->from.reg = REGTMP;
- q->to.type = D_REG;
- q->to.reg = REGTMP;
- q->pc = pc;
- q->link = p->link;
- return q;
-}
-
-static int
scan(Prog *op, Prog *p, int c)
{
Prog *q;
@@ -168,7 +88,6 @@ span(void)
Optab *o;
int m, bflag, i, v;
int32 c, otxt, out[6];
- int lastthumb = -1;
Section *sect;
uchar *bp;
@@ -183,11 +102,9 @@ span(void)
otxt = c;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
- setarch(p);
p->pc = c;
cursym->value = c;
- lastthumb = thumb;
autosize = p->to.offset + 4;
if(p->from.sym != S)
p->from.sym->value = c;
@@ -195,19 +112,14 @@ span(void)
if(c-otxt >= 1L<<17)
bflag = 1;
otxt = c;
- if(thumb && blitrl)
- pool.extra += brextra(p);
for(op = p, p = p->link; p != P; op = p, p = p->link) {
curp = p;
- setarch(p);
p->pc = c;
o = oplook(p);
m = o->size;
// must check literal pool here in case p generates many instructions
if(blitrl){
- if(thumb && isbranch(p))
- pool.extra += brextra(p);
if(checkpool(op, p->as == ACASE ? casesz(p) : m))
c = p->pc = scan(op, p, c);
}
@@ -232,8 +144,6 @@ span(void)
c += m;
}
if(blitrl){
- if(thumb && isbranch(op))
- pool.extra += brextra(op);
if(checkpool(op, 0))
c = scan(op, P, c);
}
@@ -255,10 +165,7 @@ span(void)
cursym->value = c;
for(p = cursym->text; p != P; p = p->link) {
curp = p;
- setarch(p);
p->pc = c;
- if(thumb && isbranch(p))
- nocache(p);
o = oplook(p);
/* very large branches
if(o->type == 6 && p->cond) {
@@ -300,74 +207,6 @@ span(void)
}
}
- if(seenthumb){ // branch resolution
- int passes = 0;
- int lastc = 0;
- int again;
- Prog *oop;
-
- loop:
- passes++;
- if(passes > 100){
- diag("span looping !");
- errorexit();
- }
- c = INITTEXT;
- oop = op = nil;
- again = 0;
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- cursym->value = c;
- for(p = cursym->text; p != P; oop = op, op = p, p = p->link) {
- curp = p;
- setarch(p);
- if(p->pc != c)
- again = 1;
- p->pc = c;
- if(thumb && isbranch(p))
- nocache(p);
- o = oplook(p);
- m = o->size;
- if(passes == 1 && thumb && isbranch(p)){ // start conservative so unneeded alignment is not added
- if(p->as == ABL)
- m = 4;
- else
- m = 2;
- p->align = 0;
- }
- if(p->align){
- if((p->align == 4 && (c&3)) || (p->align == 2 && !(c&3))){
- if(ispad(op)){
- oop->link = p;
- op = oop;
- c -= 2;
- p->pc = c;
- }
- else{
- op->link = pad(op, c);
- op = op->link;
- c += 2;
- p->pc = c;
- }
- again = 1;
- }
- }
- if(m == 0) {
- if(p->as == ATEXT) {
- autosize = p->to.offset + 4;
- if(p->from.sym != S)
- p->from.sym->value = c;
- continue;
- }
- }
- c += m;
- }
- cursym->size = c - cursym->value;
- }
- if(c != lastc || again){
- lastc = c;
- goto loop;
- }
- }
c = rnd(c, 8);
/*
@@ -380,7 +219,6 @@ span(void)
*/
for(cursym = textp; cursym != nil; cursym = cursym->next) {
p = cursym->text;
- setarch(p);
autosize = p->to.offset + 4;
symgrow(cursym, cursym->size);
@@ -414,13 +252,6 @@ span(void)
int
checkpool(Prog *p, int sz)
{
- if(thumb){
- if(pool.size >= 0x3fc || (p->pc+sz+pool.extra+2+2)+(pool.size-4)-pool.start-4 >= 0x3fc)
- return flushpool(p, 1, 0);
- else if(p->link == P)
- return flushpool(p, 2, 0);
- return 0;
- }
if(pool.size >= 0xffc || immaddr((p->pc+sz+4)+4+pool.size - pool.start+8) == 0)
return flushpool(p, 1, 0);
else if(p->link == P)
@@ -443,7 +274,7 @@ flushpool(Prog *p, int skip, int force)
q->link = blitrl;
blitrl = q;
}
- else if(!force && (p->pc+pool.size-pool.start < (thumb ? 0x3fc+4-pool.extra : 2048)))
+ else if(!force && (p->pc+pool.size-pool.start < 2048))
return 0;
elitrl->link = p->link;
p->link = blitrl;
@@ -463,10 +294,7 @@ addpool(Prog *p, Adr *a)
Prog *q, t;
int c;
- if(thumb)
- c = thumbaclass(a, p);
- else
- c = aclass(a);
+ c = aclass(a);
t = zprg;
t.as = AWORD;
@@ -482,12 +310,10 @@ addpool(Prog *p, Adr *a)
case C_FOREG:
case C_SOREG:
case C_HOREG:
- case C_GOREG:
case C_FAUTO:
case C_SAUTO:
case C_LAUTO:
case C_LACON:
- case C_GACON:
t.to.type = D_CONST;
t.to.offset = instoffset;
break;
@@ -593,16 +419,6 @@ symaddr(Sym *s)
return 0;
case STEXT:
-/* TODO(rsc): what is this for?
-#ifdef CALLEEBX
- v += fnpinc(s);
-#else
- if(s->thumb)
- v++; // T bit
-#endif
-*/
- break;
-
case SELFDATA:
case SRODATA:
case SDATA:
@@ -770,35 +586,19 @@ oplook(Prog *p)
int a1, a2, a3, r;
char *c1, *c3;
Optab *o, *e;
- Optab *otab;
- Oprang *orange;
- if(thumb){
- otab = thumboptab;
- orange = thumboprange;
- }
- else{
- otab = optab;
- orange = oprange;
- }
a1 = p->optab;
if(a1)
- return otab+(a1-1);
+ return optab+(a1-1);
a1 = p->from.class;
if(a1 == 0) {
- if(thumb)
- a1 = thumbaclass(&p->from, p) + 1;
- else
- a1 = aclass(&p->from) + 1;
+ a1 = aclass(&p->from) + 1;
p->from.class = a1;
}
a1--;
a3 = p->to.class;
if(a3 == 0) {
- if(thumb)
- a3 = thumbaclass(&p->to, p) + 1;
- else
- a3 = aclass(&p->to) + 1;
+ a3 = aclass(&p->to) + 1;
p->to.class = a3;
}
a3--;
@@ -806,35 +606,35 @@ oplook(Prog *p)
if(p->reg != NREG)
a2 = C_REG;
r = p->as;
- o = orange[r].start;
+ o = oprange[r].start;
if(o == 0) {
a1 = opcross[repop[r]][a1][a2][a3];
if(a1) {
p->optab = a1+1;
- return otab+a1;
+ return optab+a1;
}
- o = orange[r].stop; /* just generate an error */
+ o = oprange[r].stop; /* just generate an error */
}
if(debug['O']) {
print("oplook %A %O %O %O\n",
(int)p->as, a1, a2, a3);
print(" %d %d\n", p->from.type, p->to.type);
}
- e = orange[r].stop;
+ e = oprange[r].stop;
c1 = xcmp[a1];
c3 = xcmp[a3];
for(; o<e; o++)
if(o->a2 == a2)
if(c1[o->a1])
if(c3[o->a3]) {
- p->optab = (o-otab)+1;
+ p->optab = (o-optab)+1;
return o;
}
diag("illegal combination %A %O %O %O, %d %d",
p->as, a1, a2, a3, p->from.type, p->to.type);
prasm(p);
if(o == 0)
- o = otab;
+ o = optab;
return o;
}
@@ -885,9 +685,6 @@ cmp(int a, int b)
if(b == C_SBRA)
return 1;
break;
- case C_GBRA:
- if(b == C_SBRA || b == C_LBRA)
- return 1;
case C_HREG:
return cmp(C_SP, b) || cmp(C_PC, b);
@@ -907,9 +704,6 @@ ocmp(const void *a1, const void *a2)
n = p1->as - p2->as;
if(n)
return n;
- n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */
- if(n)
- return n;
n = p1->a1 - p2->a1;
if(n)
return n;
@@ -927,15 +721,11 @@ buildop(void)
{
int i, n, r;
- armv4 = !debug['h'];
for(i=0; i<C_GOK; i++)
for(n=0; n<C_GOK; n++)
xcmp[i][n] = cmp(n, i);
for(n=0; optab[n].as != AXXX; n++)
- if((optab[n].flag & V4) && !armv4) {
- optab[n].as = AXXX;
- break;
- }
+ ;
qsort(optab, n, sizeof(optab[0]), ocmp);
for(i=0; i<n; i++) {
r = optab[i].as;
@@ -1025,6 +815,8 @@ buildop(void)
oprange[AMULD] = oprange[r];
oprange[ADIVF] = oprange[r];
oprange[ADIVD] = oprange[r];
+ oprange[ASQRTF] = oprange[r];
+ oprange[ASQRTD] = oprange[r];
oprange[AMOVFD] = oprange[r];
oprange[AMOVDF] = oprange[r];
break;
diff --git a/src/cmd/5l/thumb.c b/src/cmd/5l/thumb.c
deleted file mode 100644
index a6f729bed..000000000
--- a/src/cmd/5l/thumb.c
+++ /dev/null
@@ -1,1658 +0,0 @@
-// Inferno utils/5l/thumb.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5l/thumb.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "l.h"
-#include "../ld/lib.h"
-
-static int32 thumboprr(int);
-static int32 thumboprrr(int, int);
-static int32 thumbopirr(int , int);
-static int32 thumbopri(int);
-static int32 thumbophh(int);
-static int32 thumbopbra(int);
-static int32 thumbopmv(int, int);
-static void lowreg(Prog *, int);
-static void mult(Prog *, int, int);
-static void numr(Prog *, int, int, int);
-static void regis(Prog *, int, int, int);
-static void dis(int, int);
-
-// build a constant using neg, add and shift - only worth it if < 6 bytes */
-static int
-immbuildcon(int c, Prog *p)
-{
- int n = 0;
-
- USED(p);
- if(c >= 0 && c <= 255)
- return 0; // mv
- if(c >= -255 && c < 0) // mv, neg
- return 1;
- if(c >= 256 && c <= 510) // mv, add
- return 1;
- if(c < 0)
- return 0;
- while(!(c & 1)){
- n++;
- c >>= 1;
- }
- if(c >= 0 && c <= 255) // mv, lsl
- return 1;
- return 0;
-}
-
-// positive 5 bit offset from register - O(R)
-// positive 8 bit offset from register - mov O, R then [R, R]
-// otherwise O goes in literal pool - mov O1(PC), R then [R, R]
-static int
-immoreg(int off, Prog *p)
-{
- int v = 1;
- int as = p->as;
-
- if(off < 0)
- return C_GOREG;
- if(as == AMOVW)
- v = 4;
- else if(as == AMOVH || as == AMOVHU)
- v = 2;
- else if(as == AMOVB || as == AMOVBU)
- v = 1;
- else
- diag("bad op in immoreg");
- if(off/v <= 31)
- return C_SOREG;
- if(off <= 255)
- return C_LOREG;
- return C_GOREG;
-}
-
-// positive 8 bit - mov O, R then 0(R)
-// otherwise O goes in literal pool - mov O1(PC), R then 0(R)
-static int
-immacon(int off, Prog *p, int t1, int t2)
-{
- USED(p);
- if(off < 0)
- return t2;
- if(off <= 255)
- return t1;
- return t2;
-}
-
-// unsigned 8 bit in words
-static int
-immauto(int off, Prog *p)
-{
- if(p->as != AMOVW)
- diag("bad op in immauto");
- mult(p, off, 4);
- if(off >= 0 && off <= 1020)
- return C_SAUTO;
- return C_LAUTO;
-}
-
-static int
-immsmall(int off, Prog *p, int t1, int t2, int t3)
-{
- USED(p);
- if(off >= 0 && off <= 7)
- return t1;
- if(off >= 0 && off <= 255)
- return t2;
- return t3;
-}
-
-static int
-immcon(int off, Prog *p)
-{
- int as = p->as;
-
- if(as == ASLL || as == ASRL || as == ASRA)
- return C_SCON;
- if(p->to.type == D_REG && p->to.reg == REGSP){
- if(as == AADD || as == ASUB){
- if(off >= 0 && off <= 508)
- return C_SCON;
- if(as == ASUB){
- p->as = AADD;
- p->from.offset = -p->from.offset;
- }
- return C_LCON;
- }
- diag("unknown type in immcon");
- }
- if(as == AADD || as == ASUB){
- if(p->reg != NREG)
- return immsmall(off, p, C_SCON, C_LCON, C_GCON);
- return immacon(off, p, C_SCON, C_LCON);
- }
- if(as == AMOVW && p->from.type == D_CONST && p->to.type == D_REG && immbuildcon(off, p))
- return C_BCON;
- if(as == ACMP && p->from.type == D_CONST && immbuildcon(off, p))
- return C_BCON;
- if(as == ACMP || as == AMOVW)
- return immacon(off, p, C_SCON, C_LCON);
- return C_LCON;
-}
-
-int
-thumbaclass(Adr *a, Prog *p)
-{
- Sym *s;
- int t;
-
- switch(a->type) {
- case D_NONE:
- return C_NONE;
- case D_REG:
- if(a->reg == REGSP)
- return C_SP;
- if(a->reg == REGPC)
- return C_PC;
- if(a->reg >= 8)
- return C_HREG;
- return C_REG;
- case D_SHIFT:
- diag("D_SHIFT in thumbaclass");
- return C_SHIFT;
- case D_FREG:
- diag("D_FREG in thumbaclass");
- return C_FREG;
- case D_FPCR:
- diag("D_FPCR in thumbaclass");
- return C_FCR;
- case D_OREG:
- switch(a->name) {
- case D_EXTERN:
- case D_STATIC:
- if(a->sym == 0 || a->sym->name == 0) {
- print("null sym external\n");
- print("%D\n", a);
- return C_GOK;
- }
- t = a->sym->type;
- if(t == 0 || t == SXREF) {
- diag("undefined external: %s in %s\n",
- a->sym->name, TNAME);
- a->sym->type = SDATA;
- }
- instoffset = a->sym->value + a->offset;
- return C_ADDR; /* INITDAT unknown at this stage */
- case D_AUTO:
- instoffset = autosize + a->offset;
- return immauto(instoffset, p);
- case D_PARAM:
- instoffset = autosize + a->offset + 4L;
-// print("D_PARAM %s %d+%d+%d = %d\n", a->sym != S ? a->sym->name : "noname", autosize, a->offset, 4, autosize+a->offset+4);
- return immauto(instoffset, p);
- case D_NONE:
- instoffset = a->offset;
- if(a->reg == REGSP)
- return immauto(instoffset, p);
- else
- return immoreg(instoffset, p);
- }
- return C_GOK;
- case D_PSR:
- diag("D_PSR in thumbaclass");
- return C_PSR;
- case D_OCONST:
- switch(a->name) {
- case D_EXTERN:
- case D_STATIC:
- s = a->sym;
- t = s->type;
- if(t == 0 || t == SXREF) {
- diag("undefined external: %s in %s\n",
- s->name, TNAME);
- s->type = SDATA;
- }
- instoffset = s->value + a->offset;
- if(s->type == STEXT){
- instoffset = s->value + a->offset;
-#ifdef CALLEEBX
- instoffset += fnpinc(s);
-#else
- if(s->thumb)
- instoffset++; // T bit
-#endif
- return C_LCON;
- }
- return C_LCON; /* INITDAT unknown at this stage */
- // return immcon(instoffset, p);
- }
- return C_GOK;
- case D_FCONST:
- diag("D_FCONST in thumaclass");
- return C_LFCON;
- case D_CONST:
- switch(a->name) {
- case D_NONE:
- instoffset = a->offset;
- if(a->reg != NREG)
- goto aconsize;
- return immcon(instoffset, p);
- case D_EXTERN:
- case D_STATIC:
- s = a->sym;
- if(s == S)
- break;
- t = s->type;
- switch(t) {
- case 0:
- case SXREF:
- diag("undefined external: %s in %s\n",
- s->name, TNAME);
- s->type = SDATA;
- break;
- case SCONST:
- case STEXT:
- instoffset = s->value + a->offset;
-#ifdef CALLEEBX
- instoffset += fnpinc(s);
-#else
- if(s->thumb)
- instoffset++; // T bit
-#endif
- return C_LCON;
- }
- instoffset = s->value + a->offset;
- return C_LCON; /* INITDAT unknown at this stage */
- // return immcon(instoffset, p);
- case D_AUTO:
- instoffset = autosize + a->offset;
- goto aconsize;
- case D_PARAM:
- instoffset = autosize + a->offset + 4L;
- aconsize:
- if(p->from.reg == REGSP || p->from.reg == NREG)
- return instoffset >= 0 && instoffset < 1024 ? C_SACON : C_GACON;
- else if(p->from.reg == p->to.reg)
- return immacon(instoffset, p, C_SACON, C_GACON);
- return immsmall(instoffset, p, C_SACON, C_LACON, C_GACON);
- }
- return C_GOK;
- case D_BRANCH: {
- int v, va;
-
- p->align = 0;
- v = -4;
- va = 0;
- if(p->cond != P){
- v = (p->cond->pc - p->pc) - 4;
- va = p->cond->pc;
- }
- instoffset = v;
- if(p->as == AB){
- if(v >= -2048 && v <= 2046)
- return C_SBRA;
- p->align = 4;
- instoffset = va;
- return C_LBRA;
- }
- if(p->as == ABL){
-#ifdef CALLEEBX
- int e;
-
- if((e = fninc(p->to.sym))) {
- v += e;
- va += e;
- instoffset += e;
- }
-#endif
- if(v >= -4194304 && v <= 4194302)
- return C_SBRA;
- p->align = 2;
- instoffset = va;
- return C_LBRA;
- }
- if(p->as == ABX){
- v = va;
- if(v >= 0 && v <= 255)
- return C_SBRA;
- p->align = 2;
- instoffset = va;
- return C_LBRA;
- }
- if(v >= -256 && v <= 254)
- return C_SBRA;
- if(v >= -(2048-2) && v <= (2046+2))
- return C_LBRA;
- p->align = 2;
- instoffset = va;
- return C_GBRA;
- }
- }
- return C_GOK;
-}
-
-// as a1 a2 a3 type size param lit vers
-Optab thumboptab[] =
-{
- { ATEXT, C_ADDR, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_REG, C_LCON, 0, 0, 0 },
- { AMVN, C_REG, C_NONE, C_REG, 1, 2, 0 },
- { ASRL, C_REG, C_NONE, C_REG, 1, 2, 0 },
- { ACMP, C_REG, C_REG, C_NONE, 1, 2, 0 },
- { ACMN, C_REG, C_REG, C_NONE, 1, 2, 0 },
- { AADD, C_REG, C_REG, C_REG, 2, 2, 0 },
- { AADD, C_REG, C_NONE, C_REG, 2, 2, 0 },
- { AADD, C_SCON, C_REG, C_REG, 3, 2, 0 },
- { AADD, C_LCON, C_REG, C_REG, 49, 4, 0 },
- { AADD, C_GCON, C_REG, C_REG, 36, 4, 0, LFROM },
- // { AADD, C_LCON, C_NONE, C_REG, 3, 2, 0, LFROM },
- { ASRL, C_SCON, C_REG, C_REG, 4, 2, 0 },
- { ASRL, C_SCON, C_NONE, C_REG, 4, 2, 0 },
- { AADD, C_SCON, C_NONE, C_REG, 5, 2, 0 },
- { AADD, C_LCON, C_NONE, C_REG, 37, 4, 0, LFROM },
- { ACMP, C_SCON, C_REG, C_NONE, 5, 2, 0 },
- { ACMP, C_BCON, C_REG, C_NONE, 48, 6, 0 },
- { ACMP, C_LCON, C_REG, C_NONE, 39, 4, 0, LFROM },
- { AMOVW, C_SCON, C_NONE, C_REG, 5, 2, 0 },
- { AMOVW, C_BCON, C_NONE, C_REG, 47, 4, 0 },
- { AMOVW, C_LCON, C_NONE, C_REG, 38, 2, 0, LFROM },
- // { AADD, C_LCON, C_PC, C_REG, 6, 2, 0, LFROM },
- // { AADD, C_LCON, C_SP, C_REG, 6, 2, 0, LFROM },
- { AADD, C_SCON, C_NONE, C_SP, 7, 2, 0 },
- { AADD, C_LCON, C_NONE, C_SP, 40, 4, 0, LFROM },
- { AADD, C_REG, C_NONE, C_HREG, 8, 2, 0 },
- { AADD, C_HREG, C_NONE, C_REG, 8, 2, 0 },
- { AADD, C_HREG, C_NONE, C_HREG, 8, 2, 0 },
- { AMOVW, C_REG, C_NONE, C_HREG, 8, 2, 0 },
- { AMOVW, C_HREG, C_NONE, C_REG, 8, 2, 0 },
- { AMOVW, C_HREG, C_NONE, C_HREG, 8, 2, 0 },
- { ACMP, C_REG, C_HREG, C_NONE, 8, 2, 0 },
- { ACMP, C_HREG, C_REG, C_NONE, 8, 2, 0 },
- { ACMP, C_HREG, C_HREG, C_NONE, 8, 2, 0 },
- { AB, C_NONE, C_NONE, C_SBRA, 9, 2, 0, LPOOL },
- { ABEQ, C_NONE, C_NONE, C_SBRA, 10, 2, 0 },
- { ABL, C_NONE, C_NONE, C_SBRA, 11, 4, 0 },
- { ABX, C_NONE, C_NONE, C_SBRA, 12, 10, 0 },
- { AB, C_NONE, C_NONE, C_LBRA, 41, 8, 0, LPOOL },
- { ABEQ, C_NONE, C_NONE, C_LBRA, 46, 4, 0 },
- { ABL, C_NONE, C_NONE, C_LBRA, 43, 14, 0 },
- { ABX, C_NONE, C_NONE, C_LBRA, 44, 14, 0 },
- { ABEQ, C_NONE, C_NONE, C_GBRA, 42, 10, 0 },
- // { AB, C_NONE, C_NONE, C_SOREG, 13, 0, 0 },
- // { ABL, C_NONE, C_NONE, C_SOREG, 14, 0, 0 },
- { ABL, C_NONE, C_NONE, C_REG, 51, 4, 0 },
- { ABX, C_NONE, C_NONE, C_REG, 15, 8, 0 },
- { ABX, C_NONE, C_NONE, C_HREG, 15, 8, 0 },
- { ABXRET, C_NONE, C_NONE, C_REG, 45, 2, 0 },
- { ABXRET, C_NONE, C_NONE, C_HREG, 45, 2, 0 },
- { ASWI, C_NONE, C_NONE, C_LCON, 16, 2, 0 },
- { AWORD, C_NONE, C_NONE, C_LCON, 17, 4, 0 },
- { AWORD, C_NONE, C_NONE, C_GCON, 17, 4, 0 },
- { AWORD, C_NONE, C_NONE, C_ADDR, 17, 4, 0 },
- { ADWORD, C_LCON, C_NONE, C_LCON, 50, 8, 0 },
- { AMOVW, C_SAUTO, C_NONE, C_REG, 18, 2, REGSP },
- { AMOVW, C_LAUTO, C_NONE, C_REG, 33, 6, 0, LFROM },
- // { AMOVW, C_OFFPC, C_NONE, C_REG, 18, 2, REGPC, LFROM },
- { AMOVW, C_SOREG, C_NONE, C_REG, 19, 2, 0 },
- { AMOVHU, C_SOREG, C_NONE, C_REG, 19, 2, 0 },
- { AMOVBU, C_SOREG, C_NONE, C_REG, 19, 2, 0 },
- { AMOVW, C_REG, C_NONE, C_SAUTO, 20, 2, 0 },
- { AMOVW, C_REG, C_NONE, C_LAUTO, 34, 6, 0, LTO },
- { AMOVW, C_REG, C_NONE, C_SOREG, 21, 2, 0 },
- { AMOVH, C_REG, C_NONE, C_SOREG, 21, 2, 0 },
- { AMOVB, C_REG, C_NONE, C_SOREG, 21, 2, 0 },
- { AMOVHU, C_REG, C_NONE, C_SOREG, 21, 2, 0 },
- { AMOVBU, C_REG, C_NONE, C_SOREG, 21, 2, 0 },
- { AMOVW, C_REG, C_NONE, C_REG, 22, 2, 0 },
- { AMOVB, C_REG, C_NONE, C_REG, 23, 4, 0 },
- { AMOVH, C_REG, C_NONE, C_REG, 23, 4, 0 },
- { AMOVBU, C_REG, C_NONE, C_REG, 23, 4, 0 },
- { AMOVHU, C_REG, C_NONE, C_REG, 23, 4, 0 },
- { AMOVH, C_SOREG, C_NONE, C_REG, 24, 4, 0 },
- { AMOVB, C_SOREG, C_NONE, C_REG, 24, 4, 0 },
- { AMOVW, C_SACON, C_NONE, C_REG, 25, 2, 0 },
- { AMOVW, C_LACON, C_NONE, C_REG, 35, 4, 0 },
- { AMOVW, C_GACON, C_NONE, C_REG, 35, 4, 0, LFROM },
- { AMOVM, C_LCON, C_NONE, C_REG, 26, 2, 0 },
- { AMOVM, C_REG, C_NONE, C_LCON, 27, 2, 0 },
- { AMOVW, C_LOREG, C_NONE, C_REG, 28, 4, 0 },
- { AMOVH, C_LOREG, C_NONE, C_REG, 28, 4, 0 },
- { AMOVB, C_LOREG, C_NONE, C_REG, 28, 4, 0 },
- { AMOVHU, C_LOREG, C_NONE, C_REG, 28, 4, 0 },
- { AMOVBU, C_LOREG, C_NONE, C_REG, 28, 4, 0 },
- { AMOVW, C_REG, C_NONE, C_LOREG, 29, 4, 0 },
- { AMOVH, C_REG, C_NONE, C_LOREG, 29, 4, 0 },
- { AMOVB, C_REG, C_NONE, C_LOREG, 29, 4, 0 },
- { AMOVHU, C_REG, C_NONE, C_LOREG, 29, 4, 0 },
- { AMOVBU, C_REG, C_NONE, C_LOREG, 29, 4, 0 },
- { AMOVW, C_GOREG, C_NONE, C_REG, 28, 4, 0, LFROM },
- { AMOVH, C_GOREG, C_NONE, C_REG, 28, 4, 0, LFROM },
- { AMOVB, C_GOREG, C_NONE, C_REG, 28, 4, 0, LFROM },
- { AMOVHU, C_GOREG, C_NONE, C_REG, 28, 4, 0, LFROM },
- { AMOVBU, C_GOREG, C_NONE, C_REG, 28, 4, 0, LFROM },
- { AMOVW, C_REG, C_NONE, C_GOREG, 29, 4, 0, LTO },
- { AMOVH, C_REG, C_NONE, C_GOREG, 29, 4, 0, LTO },
- { AMOVB, C_REG, C_NONE, C_GOREG, 29, 4, 0, LTO },
- { AMOVHU, C_REG, C_NONE, C_GOREG, 29, 4, 0, LTO },
- { AMOVBU, C_REG, C_NONE, C_GOREG, 29, 4, 0, LTO },
- { AMOVW, C_ADDR, C_NONE, C_REG, 30, 4, 0, LFROM },
- { AMOVH, C_ADDR, C_NONE, C_REG, 32, 6, 0, LFROM },
- { AMOVB, C_ADDR, C_NONE, C_REG, 32, 6, 0, LFROM },
- { AMOVHU, C_ADDR, C_NONE, C_REG, 30, 4, 0, LFROM },
- { AMOVBU, C_ADDR, C_NONE, C_REG, 30, 4, 0, LFROM },
- { AMOVW, C_REG, C_NONE, C_ADDR, 31, 4, 0, LTO },
- { AMOVH, C_REG, C_NONE, C_ADDR, 31, 4, 0, LTO },
- { AMOVB, C_REG, C_NONE, C_ADDR, 31, 4, 0, LTO },
- { AMOVHU, C_REG, C_NONE, C_ADDR, 31, 4, 0, LTO },
- { AMOVBU, C_REG, C_NONE, C_ADDR, 31, 4, 0, LTO },
-
- { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 },
-};
-
-#define OPCNTSZ 52
-int opcount[OPCNTSZ];
-
-// is this too pessimistic ?
-int
-brextra(Prog *p)
-{
- int c;
-
- // +2 is for padding
- if(p->as == ATEXT)
- return 0-0+2;
- if(!isbranch(p))
- diag("bad op in brextra()");
- c = thumbaclass(&p->to, p);
- switch(p->as){
- case AB:
- if(c != C_SBRA)
- return 0;
- return 8-2+2;
- case ABL:
- if(c != C_SBRA)
- return 0;
- return 14-4+2;
- case ABX:
- if(c == C_REG || c == C_HREG)
- return 0;
-#ifdef CALLEEBX
- diag("ABX $I in brextra");
-#endif
- if(c != C_SBRA)
- return 0;
- return 14-10+2;
- default:
- if(c == C_GBRA)
- return 0;
- if(c == C_LBRA)
- return 10-4+2;
- return 10-2+2;
- }
- return 0;
-}
-
-#define high(r) ((r)>=8)
-
-static int32
-mv(Prog *p, int r, int off)
-{
- int v, o;
- if(p != nil && p->cond != nil){ // in literal pool
- v = p->cond->pc - p->pc - 4;
- if(p->cond->pc & 3)
- diag("mv: bad literal pool alignment");
- if(v & 3)
- v += 2; // ensure M(4) offset
- mult(p, v, 4);
- off = v/4;
- numr(p, off, 0, 255);
- o = 0x9<<11;
- }
- else{
- numr(p, off, 0, 255);
- o = 0x4<<11;
- }
- o |= (r<<8) | off;
- return o;
-}
-
-static void
-mvcon(Prog *p, int r, int c, int32 *o1, int32 *o2)
-{
- int op = 0, n = 0;
-
- if(c >= 0 && c <= 255)
- diag("bad c in mvcon");
- if(c >= -255 && c < 0) // mv, neg
- c = -c;
- else if(c >= 256 && c <= 510){ // mv, add
- n = rand()%(511-c) + (c-255);
- c -= n;
- // n = c-255;
- // c = 255;
- op = AADD;
- }
- else{
- if(c < 0)
- diag("-ve in mvcon");
- while(!(c & 1)){
- n++;
- c >>= 1;
- }
- if(c >= 0 && c <= 255) // mv, lsl
- op = ASLL;
- else
- diag("bad shift in mvcon");
- }
- *o1 = mv(p, r, c);
- switch(op){
- case 0:
- *o2 = (1<<14) | (9<<6) | (r<<3) | r;
- break;
- case AADD:
- *o2 = (6<<11) | (r<<8) | n;
- break;
- case ASLL:
- *o2 = (n<<6) | (r<<3) | r;
- break;
- }
-}
-
-static int32
-mvlh(int rs, int rd)
-{
- int o = 0x46<<8;
-
- if(high(rs)){
- rs -= 8;
- o |= 1<<6;
- }
- if(high(rd)){
- rd -= 8;
- o |= 1<<7;
- }
- o |= (rs<<3) | rd;
- return o;
-}
-
-void
-thumbbuildop()
-{
- int i, n, r;
- Optab *optab = thumboptab;
- Oprang *oprange = thumboprange;
-
- for(n=0; optab[n].as != AXXX; n++)
- ;
- qsort(optab, n, sizeof(optab[0]), ocmp);
- for(i=0; i<n; i++) {
- r = optab[i].as;
- oprange[r].start = optab+i;
- while(optab[i].as == r)
- i++;
- oprange[r].stop = optab+i;
- i--;
-
- switch(r)
- {
- default:
- break;
- case ABEQ:
- oprange[ABNE] = oprange[r];
- oprange[ABCS] = oprange[r];
- oprange[ABHS] = oprange[r];
- oprange[ABCC] = oprange[r];
- oprange[ABLO] = oprange[r];
- oprange[ABMI] = oprange[r];
- oprange[ABPL] = oprange[r];
- oprange[ABVS] = oprange[r];
- oprange[ABVC] = oprange[r];
- oprange[ABHI] = oprange[r];
- oprange[ABLS] = oprange[r];
- oprange[ABGE] = oprange[r];
- oprange[ABLT] = oprange[r];
- oprange[ABGT] = oprange[r];
- oprange[ABLE] = oprange[r];
- break;
- case AMVN:
- oprange[AADC] = oprange[r];
- oprange[ASBC] = oprange[r];
- oprange[AMUL] = oprange[r];
- oprange[AAND] = oprange[r];
- oprange[AEOR] = oprange[r];
- oprange[AORR] = oprange[r];
- oprange[ABIC] = oprange[r];
- oprange[AMULU] = oprange[r];
- break;
- case ACMN:
- oprange[ATST] = oprange[r];
- break;
- case ASRL:
- oprange[ASRA] = oprange[r];
- oprange[ASLL] = oprange[r];
- break;
- case AADD:
- oprange[ASUB] = oprange[r];
- break;
- }
- }
-}
-
-void
-thumbasmout(Prog *p, Optab *o)
-{
- int32 o1, o2, o3, o4, o5, o6, o7, v;
- int r, rf, rt;
-
- rf = p->from.reg;
- rt = p->to.reg;
- r = p->reg;
- o1 = o2 = o3 = o4 = o5 = o6 = o7 = 0;
-if(debug['P']) print("%ux: %P type %d %d\n", (uint32)(p->pc), p, o->type, p->align);
- opcount[o->type] += o->size;
- switch(o->type) {
- default:
- diag("unknown asm %d", o->type);
- prasm(p);
- break;
- case 0: /* pseudo ops */
-if(debug['G']) print("%ux: %s: thumb\n", (uint32)(p->pc), p->from.sym->name);
- break;
- case 1: /* op R, -, R or op R, R, - */
- o1 = thumboprr(p->as);
- if(rt == NREG)
- rt = r;
- lowreg(p, rf);
- lowreg(p, rt);
- o1 |= (0x10<<10) | (rf<<3) | rt;
- break;
- case 2: /* add/sub R, R, R or add/sub R, -, R */
- o1 = p->as == AADD ? 0x0<<9 : 0x1<<9;
- if(r == NREG)
- r = rt;
- lowreg(p, rf);
- lowreg(p, r);
- lowreg(p, rt);
- o1 |= (0x6<<10) | (rf<<6) | (r<<3) | rt;
- break;
- case 3: /* add/sub $I, R, R or add/sub $I, -, R */
- thumbaclass(&p->from, p);
- o1 = p->as == AADD ? 0x0<<9 : 0x1<<9;
- if(r == NREG)
- r = rt;
- numr(p, instoffset, 0, 7);
- lowreg(p, r);
- lowreg(p, rt);
- o1 |= (0x7<<10) | (instoffset<<6) | (r<<3) | rt;
- break;
- case 4: /* shift $I, R, R or shift $I, -, R */
- thumbaclass(&p->from, p);
- if(instoffset < 0)
- diag("negative shift in thumbasmout");
- instoffset %= 32;
- o1 = thumbopri(p->as);
- if(r == NREG)
- r = rt;
- numr(p, instoffset, 0, 31);
- lowreg(p, r);
- lowreg(p, rt);
- o1 |= (0x0<<13) | (instoffset<<6) | (r<<3) | rt;
- break;
- case 5: /* add/sub/mov $I, -, R or cmp $I, R, - */
- thumbaclass(&p->from, p);
- o1 = thumbopri(p->as);
- if(rt == NREG)
- rt = r;
- numr(p, instoffset, 0, 255);
- lowreg(p, rt);
- o1 |= (0x1<<13) | (rt<<8) | instoffset;
- break;
- case 6: /* add $I, PC/SP, R */
- if(p->as == ASUB)
- diag("subtract in add $I, PC/SP, R");
- thumbaclass(&p->from, p);
- o1 = r == REGSP ? 0x1<<11 : 0x0<<11;
- numr(p, instoffset, 0, 255);
- regis(p, r, REGSP, REGPC);
- lowreg(p, rt);
- o1 |= (0xa<<12) | (rt<<8) | instoffset;
- break;
- case 7: /* add, sub $I, SP */
- thumbaclass(&p->from, p);
- o1 = p->as == AADD ? 0x0<<7 : 0x1<<7;
- numr(p, instoffset, 0, 508);
- mult(p, instoffset, 4);
- regis(p, rt, REGSP, REGSP);
- o1 |= (0xb0<<8) | (instoffset>>2);
- break;
- case 8: /* add/mov/cmp R, R where at least 1 reg is high */
- o1 = 0;
- if(rt == NREG)
- rt = r;
- if(high(rf)){
- o1 |= 1<<6;
- rf -= 8;
- }
- if(high(rt)){
- o1 |= 2<<6;
- rt -= 8;
- }
- if(o1 == 0)
- diag("no high register(%P)", p);
- o1 |= thumbophh(p->as);
- o1 |= (0x11<<10) | (rf<<3) | rt;
- break;
- case 9: /* B $I */
- thumbaclass(&p->to, p);
- numr(p, instoffset, -2048, 2046);
- o1 = (0x1c<<11) | ((instoffset>>1)&0x7ff);
- break;
- case 10: /* Bcc $I */
- thumbaclass(&p->to, p);
- numr(p, instoffset, -256, 254);
- o1 = thumbopbra(p->as);
- o1 |= (0xd<<12) | ((instoffset>>1)&0xff);
- break;
- case 11: /* BL $I */
- thumbaclass(&p->to, p);
- numr(p, instoffset, -4194304, 4194302);
- o1 = (0x1e<<11) | ((instoffset>>12)&0x7ff);
- o2 = (0x1f<<11) | ((instoffset>>1)&0x7ff);
- break;
- case 12: /* BX $I */
-#ifdef CALLEEBX
- diag("BX $I case");
-#endif
- thumbaclass(&p->to, p);
- if(p->to.sym->thumb)
- instoffset |= 1; // T bit
- o1 = mvlh(REGPC, REGTMPT);
- o2 = (0x6<<11) | (REGTMPT<<8) | 7; // add 7, RTMP (T bit + PC offset)
- o3 = mvlh(REGTMPT, REGLINK);
- o4 = mv(nil, REGTMPT, instoffset);
- o5 = (0x11c<<6) | (REGTMPT<<3);
- // o1 = mv(nil, REGTMPT, v);
- // o2 = (0x11b<<6) | (REGPC<<3) | REGLINK;
- // o3 = (0x11c<<6) | (REGTMPT<<3);
- break;
- case 13: /* B O(R) */
- diag("B O(R)");
- break;
- case 14: /* BL O(R) */
- diag("BL O(R)");
- break;
- case 15: /* BX R */
- o1 = mvlh(REGPC, REGTMPT);
- o2 = (0x6<<11) | (REGTMPT<<8) | 5; // add 5, RTMP (T bit + PC offset)
- o3 = mvlh(REGTMPT, REGLINK);
- o4 = 0;
- if(high(rt)){
- rt -= 8;
- o4 |= 1<<6;
- }
- o4 |= (0x8e<<7) | (rt<<3);
- // o1 = (0x11c<<6) | (rt<<3);
- break;
- case 16: /* SWI $I */
- thumbaclass(&p->to, p);
- numr(p, instoffset, 0, 255);
- o1 = (0xdf<<8) | instoffset;
- break;
- case 17: /* AWORD */
- thumbaclass(&p->to, p);
- o1 = instoffset&0xffff;
- o2 = (instoffset>>16)&0xffff;
- break;
- case 18: /* AMOVW O(SP), R and AMOVW O(PC), R */
- thumbaclass(&p->from, p);
- rf = o->param;
- o1 = rf == REGSP ? 0x13<<11 : 0x9<<11;
- regis(p, rf, REGSP, REGPC);
- lowreg(p, rt);
- mult(p, instoffset, 4);
- numr(p, instoffset/4, 0, 255);
- o1 |= (rt<<8) | (instoffset/4);
- break;
- case 19: /* AMOVW... O(R), R */
- thumbaclass(&p->from, p);
- o1 = thumbopmv(p->as, 1);
- v = 4;
- if(p->as == AMOVHU)
- v = 2;
- else if(p->as == AMOVBU)
- v = 1;
- mult(p, instoffset, v);
- lowreg(p, rf);
- lowreg(p, rt);
- numr(p, instoffset/v, 0, 31);
- o1 |= ((instoffset/v)<<6) | (rf<<3) | rt;
- break;
- case 20: /* AMOVW R, O(SP) */
- thumbaclass(&p->to, p);
- o1 = 0x12<<11;
- if(rt != NREG) regis(p, rt, REGSP, REGSP);
- lowreg(p, rf);
- mult(p, instoffset, 4);
- numr(p, instoffset/4, 0, 255);
- o1 |= (rf<<8) | (instoffset/4);
- break;
- case 21: /* AMOVW... R, O(R) */
- thumbaclass(&p->to, p);
- o1 = thumbopmv(p->as, 0);
- v = 4;
- if(p->as == AMOVHU || p->as == AMOVH)
- v = 2;
- else if(p->as == AMOVBU || p->as == AMOVB)
- v = 1;
- lowreg(p, rf);
- lowreg(p, rt);
- mult(p, instoffset, v);
- numr(p, instoffset/v, 0, 31);
- o1 |= ((instoffset/v)<<6) | (rt<<3) | rf;
- break;
- case 22: /* AMOVW R, R -> ASLL $0, R, R */
- o1 = thumbopri(ASLL);
- lowreg(p, rf);
- lowreg(p, rt);
- o1 |= (0x0<<13) | (rf<<3) | rt;
- break;
- case 23: /* AMOVB/AMOVH/AMOVBU/AMOVHU R, R */
- o1 = thumbopri(ASLL);
- o2 = p->as == AMOVB || p->as == AMOVH ? thumbopri(ASRA) : thumbopri(ASRL);
- v = p->as == AMOVB || p->as == AMOVBU ? 24 : 16;
- lowreg(p, rf);
- lowreg(p, rt);
- o1 |= (0x0<<13) | (v<<6) | (rf<<3) | rt;
- o2 |= (0x0<<13) | (v<<6) | (rt<<3) | rt;
- break;
- case 24: /* AMOVH/AMOVB O(R), R -> AMOVH/AMOVB [R, R], R */
- thumbaclass(&p->from, p);
- lowreg(p, rf);
- lowreg(p, rt);
- if(rf == rt)
- r = REGTMPT;
- else
- r = rt;
- if(p->as == AMOVB)
- numr(p, instoffset, 0, 31);
- else{
- mult(p, instoffset, 2);
- numr(p, instoffset, 0, 62);
- }
- o1 = mv(p, r, instoffset);
- o2 = p->as == AMOVH ? 0x2f<<9 : 0x2b<<9;
- o2 |= (r<<6) | (rf<<3) | rt;
- break;
- case 25: /* MOVW $sacon, R */
- thumbaclass(&p->from, p);
-// print("25: %d %d %d %d\n", instoffset, rf, r, rt);
- if(rf == NREG)
- rf = REGSP;
- lowreg(p, rt);
- if(rf == REGSP){
- mult(p, instoffset, 4);
- numr(p, instoffset>>2, 0, 255);
- o1 = (0x15<<11) | (rt<<8) | (instoffset>>2); // add $O, SP, R
- }
- else if(rf == rt){
- numr(p, instoffset, 0, 255);
- o1 = (0x6<<11) | (rt<<8) | instoffset; // add $O, R
- }
- else{
- lowreg(p, rf);
- numr(p, instoffset, 0, 7);
- o1 = (0xe<<9) | (instoffset<<6) | (rf<<3) | rt; // add $O, Rs, Rd
- }
- break;
- case 26: /* AMOVM $c, oreg -> stmia */
- lowreg(p, rt);
- numr(p, p->from.offset, -256, 255);
- o1 = (0x18<<11) | (rt<<8) | (p->from.offset&0xff);
- break;
- case 27: /* AMOVM oreg, $c ->ldmia */
- lowreg(p, rf);
- numr(p, p->to.offset, -256, 256);
- o1 = (0x19<<11) | (rf<<8) | (p->to.offset&0xff);
- break;
- case 28: /* AMOV* O(R), R -> AMOV* [R, R], R (offset large) */
- thumbaclass(&p->from, p);
- lowreg(p, rf);
- lowreg(p, rt);
- if(rf == rt)
- r = REGTMPT;
- else
- r = rt;
- o1 = mv(p, r, instoffset);
- o2 = thumboprrr(p->as, 1);
- o2 |= (r<<6) | (rf<<3) | rt;
- break;
- case 29: /* AMOV* R, O(R) -> AMOV* R, [R, R] (offset large) */
- thumbaclass(&p->to, p);
- lowreg(p, rf);
- lowreg(p, rt);
- if(rt == REGTMPT){ // used as tmp reg
- if(instoffset >= 0 && instoffset <= 255){
- o1 = (1<<13) | (2<<11) | (rt<<8) | instoffset; // add $O, R7
- o2 = thumbopirr(p->as, 0);
- o2 |= (0<<6) | (rt<<3) | rf; // mov* R, 0(R)
- }
- else
- diag("big offset - case 29");
- }
- else{
- o1 = mv(p, REGTMPT, instoffset);
- o2 = thumboprrr(p->as, 0);
- o2 |= (REGTMPT<<6) | (rt<<3) | rf;
- }
- break;
- case 30: /* AMOVW... *addr, R */
- diag("likely broken"); // does this still refer to SB?
- thumbaclass(&p->from, p);
- o1 = mv(p, rt, instoffset); // MOV addr, rtmp
- o2 = thumbopmv(p->as, 1);
- lowreg(p, rt);
- o2 |= (rt<<3) | rt; // MOV* 0(rtmp), R
- break;
- case 31: /* AMOVW... R, *addr */
- diag("likely broken"); // does this still refer to SB?
- thumbaclass(&p->to, p);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = thumbopmv(p->as, 0);
- lowreg(p, rf);
- o2 |= (REGTMPT<<3) | rf;
- break;
- case 32: /* AMOVH/AMOVB *addr, R -> AMOVH/AMOVB [R, R], R */
- thumbaclass(&p->from, p);
- o1 = mv(p, rt, instoffset);
- lowreg(p, rt);
- o2 = mv(nil, REGTMPT, 0);
- o3 = p->as == AMOVH ? 0x2f<<9 : 0x2b<<9;
- o3 |= (REGTMPT<<6) | (rt<<3) | rt;
- break;
- case 33: /* AMOVW O(SP), R (O large) */
- thumbaclass(&p->from, p);
- lowreg(p, rt);
- o1 = mv(p, rt, instoffset);
- o2 = (0x111<<6) | (REGSP-8)<<3 | rt; // add SP, rt
- o3 = thumbopmv(p->as, 1);
- o3 |= (rt<<3) | rt;
- break;
- case 34: /* AMOVW R, O(SP) (O large) */
- thumbaclass(&p->to, p);
- lowreg(p, rf);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = (0x111<<6) | (REGSP-8)<<3 | REGTMPT; // add SP, REGTMP
- o3 = thumbopmv(p->as, 0);
- o3 |= (REGTMPT<<3) | rf;
- break;
- case 35: /* AMOVW $lacon, R */
- thumbaclass(&p->from, p);
- lowreg(p, rt);
- if(rf == NREG)
- rf = REGSP;
- if(rf == rt)
- rf = r = REGTMPT;
- else
- r = rt;
-// print("35: io=%d rf=%d rt=%d\n", instoffset, rf, rt);
- o1 = mv(p, r, instoffset); // mov O, Rd
- if(high(rf))
- o2 = (0x44<<8) | (0x1<<6) | ((rf-8)<<3) | rt; // add Rs, Rd
- else
- o2 = (0x6<<10) | (rf<<6) | (rt<<3) | rt; // add Rs, Rd
- break;
- case 36: /* AADD/ASUB $i, r, r when $i too big */
- thumbaclass(&p->from, p);
- lowreg(p, r);
- lowreg(p, rt);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = p->as == AADD ? 0xc<<9 : 0xd<<9;
- o2 |= (REGTMPT<<6) | (r<<3) | rt;
- break;
- case 37: /* AADD/ASUB $i, r when $i too big */
- thumbaclass(&p->from, p);
- lowreg(p, rt);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = p->as == AADD ? 0xc<<9 : 0xd<<9;
- o2 |= (REGTMPT<<6) | (rt<<3) | rt;
- break;
- case 38: /* AMOVW $i, r when $i too big */
- thumbaclass(&p->from, p);
- lowreg(p, rt);
- o1 = mv(p, rt, instoffset);
- break;
- case 39: /* ACMP $i, r when $i too big */
- thumbaclass(&p->from, p);
- lowreg(p, r);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = (0x10a<<6) | (REGTMPT<<3) | r;
- break;
- case 40: /* add, sub $I, SP when $I large*/
- thumbaclass(&p->from, p);
- if(p->as == ASUB)
- instoffset = -instoffset;
- o1 = mv(p, REGTMPT, instoffset);
- o2 = (0x112<<6) | (REGTMPT<<3) | (REGSP-8);
- regis(p, rt, REGSP, REGSP);
- break;
- case 41: /* BL LBRA */
- thumbaclass(&p->to, p);
- o1 = (0x9<<11) | (REGTMPT<<8); // mov 0(pc), r7
- o2 = mvlh(REGTMPT, REGPC); // mov r7, pc
- o3 = instoffset&0xffff; // $lab
- o4 = (instoffset>>16)&0xffff;
- break;
- case 42: /* Bcc GBRA */
- thumbaclass(&p->to, p);
- o1 = (0xd<<12) | thumbopbra(relinv(p->as)) | (6>>1); // bccnot
- // ab lbra
- o2 = (0x9<<11) | (REGTMPT<<8); // mov 0(pc), r7
- o3 = mvlh(REGTMPT, REGPC); // mov r7, pc
- o4 = instoffset&0xffff; // $lab
- o5 = (instoffset>>16)&0xffff;
- break;
- case 43: /* BL LBRA */
- thumbaclass(&p->to, p);
- o1 = mvlh(REGPC, REGTMPT); // mov pc, r7
- o2 = (0x6<<11) | (REGTMPT<<8) | 10; // add 10, r7
- o3 = mvlh(REGTMPT, REGLINK); // mov r7, lr
- o4 = (0x9<<11) | (REGTMPT<<8); // mov o(pc), r7
- o5 = mvlh(REGTMPT, REGPC); // mov r7, pc
- o6 = instoffset&0xffff; // $lab
- o7 = (instoffset>>16)&0xffff;
- break;
- case 44: /* BX LBRA */
-#ifdef CALLEEBX
- diag("BX LBRA case");
-#endif
- thumbaclass(&p->to, p);
- if(p->to.sym->thumb)
- instoffset |= 1; // T bit
- o1 = mvlh(REGPC, REGTMPT); // mov pc, r7
- o2 = (0x6<<11) | (REGTMPT<<8) | 11; // add 11, r7
- o3 = mvlh(REGTMPT, REGLINK); // mov r7, lr
- o4 = (0x9<<11) | (REGTMPT<<8); // mov o(pc), r7
- o5 = (0x11c<<6) | (REGTMPT<<3); // bx r7
- o6 = instoffset&0xffff; // $lab
- o7 = (instoffset>>16)&0xffff;
- break;
- case 45: /* BX R when returning from fn */
- o1 = 0;
- if(high(rt)){
- rt -= 8;
- o1 |= 1<<6;
- }
- o1 |= (0x8e<<7) | (rt<<3);
- break;
- case 46: /* Bcc LBRA */
- thumbaclass(&p->to, p);
- o1 = (0xd<<12) | thumbopbra(relinv(p->as)) | (0>>1); // bccnot
- // ab lbra
- instoffset -= 2;
- numr(p, instoffset, -2048, 2046);
- o2 = (0x1c<<11) | ((instoffset>>1)&0x7ff);
- break;
- case 47: /* mov $i, R where $i can be built */
- thumbaclass(&p->from, p);
- mvcon(p, rt, instoffset, &o1, &o2);
- break;
- case 48: /* ACMP $i, r when $i built up */
- thumbaclass(&p->from, p);
- lowreg(p, r);
- mvcon(p, REGTMPT, instoffset, &o1, &o2);
- o3 = (0x10a<<6) | (REGTMPT<<3) | r;
- break;
- case 49: /* AADD $i, r, r when $i is between 0 and 255 - could merge with case 36 */
- thumbaclass(&p->from, p);
- lowreg(p, r);
- lowreg(p, rt);
- numr(p, instoffset, 0, 255);
- o1 = mv(p, REGTMPT, instoffset);
- o2 = p->as == AADD ? 0xc<<9 : 0xd<<9;
- o2 |= (REGTMPT<<6) | (r<<3) | rt;
- break;
- case 50: /* ADWORD */
- thumbaclass(&p->from, p);
- o1 = instoffset&0xffff;
- o2 = (instoffset>>16)&0xffff;
- thumbaclass(&p->to, p);
- o3 = instoffset&0xffff;
- o4 = (instoffset>>16)&0xffff;
- break;
- case 51: /* BL r */
- o1 = mvlh(REGPC, REGLINK); // mov pc, lr
- o2 = mvlh(rt, REGPC); // mov r, pc
- break;
- }
-
- v = p->pc;
- switch(o->size) {
- default:
- if(debug['a'])
- Bprint(&bso, " %.8ux:\t\t%P\n", v, p);
- break;
- case 2:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux\t%P\n", v, o1, p);
- hputl(o1);
- break;
- case 4:
- if(debug['a'])
- Bprint(&bso, " %.8ux: %.8ux %.8ux\t%P\n", v, o1, o2, p);
- hputl(o1);
- hputl(o2);
- break;
- case 6:
- if(debug['a'])
- Bprint(&bso, "%.8ux: %.8ux %.8ux %.8ux\t%P\n", v, o1, o2, o3, p);
- hputl(o1);
- hputl(o2);
- hputl(o3);
- break;
- case 8:
- if(debug['a'])
- Bprint(&bso, "%.8ux: %.8ux %.8ux %.8ux %.8ux\t%P\n", v, o1, o2, o3, o4, p);
- hputl(o1);
- hputl(o2);
- hputl(o3);
- hputl(o4);
- break;
- case 10:
- if(debug['a'])
- Bprint(&bso, "%.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux\t%P\n", v, o1, o2, o3, o4, o5, p);
- hputl(o1);
- hputl(o2);
- hputl(o3);
- hputl(o4);
- hputl(o5);
- break;
- case 12:
- if(debug['a'])
- Bprint(&bso, "%.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux\t%P\n", v, o1, o2, o3, o4, o5, o6, p);
- hputl(o1);
- hputl(o2);
- hputl(o3);
- hputl(o4);
- hputl(o5);
- hputl(o6);
- break;
- case 14:
- if(debug['a'])
- Bprint(&bso, "%.8ux: %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux\t%P\n", v, o1, o2, o3, o4, o5, o6, o7, p);
- hputl(o1);
- hputl(o2);
- hputl(o3);
- hputl(o4);
- hputl(o5);
- hputl(o6);
- hputl(o7);
- break;
- }
- if(debug['G']){
- if(o->type == 17){
- print("%x: word %d\n", p->pc, (o2<<16)+o1);
- return;
- }
- if(o->type == 50){
- print("%x: word %d\n", p->pc, (o2<<16)+o1);
- print("%x: word %d\n", p->pc, (o4<<16)+o3);
- return;
- }
- if(o->size > 0) dis(o1, p->pc);
- if(o->size > 2) dis(o2, p->pc+2);
- if(o->size > 4) dis(o3, p->pc+4);
- if(o->size > 6) dis(o4, p->pc+6);
- if(o->size > 8) dis(o5, p->pc+8);
- if(o->size > 10) dis(o6, p->pc+10);
- if(o->size > 12) dis(o7, p->pc+12);
- // if(o->size > 14) dis(o8, p->pc+14);
- }
-}
-
-static int32
-thumboprr(int a)
-{
- switch(a) {
- case AMVN: return 0xf<<6;
- case ACMP: return 0xa<<6;
- case ACMN: return 0xb<<6;
- case ATST: return 0x8<<6;
- case AADC: return 0x5<<6;
- case ASBC: return 0x6<<6;
- case AMUL:
- case AMULU: return 0xd<<6;
- case AAND: return 0x0<<6;
- case AEOR: return 0x1<<6;
- case AORR: return 0xc<<6;
- case ABIC: return 0xe<<6;
- case ASRL: return 0x3<<6;
- case ASRA: return 0x4<<6;
- case ASLL: return 0x2<<6;
- }
- diag("bad thumbop oprr %d", a);
- prasm(curp);
- return 0;
-}
-
-static int32
-thumbopirr(int a, int ld)
-{
- if(ld)
- diag("load in thumbopirr");
- switch(a){
- case AMOVW: return 0xc<<11;
- case AMOVH:
- case AMOVHU: return 0x10<<11;
- case AMOVB:
- case AMOVBU: return 0xe<<11;
- }
- return 0;
-}
-
-static int32
-thumboprrr(int a, int ld)
-{
- if(ld){
- switch(a){
- case AMOVW: return 0x2c<<9;
- case AMOVH: return 0x2f<<9;
- case AMOVB: return 0x2b<<9;
- case AMOVHU: return 0x2d<<9;
- case AMOVBU: return 0x2e<<9;
- }
- }
- else{
- switch(a){
- case AMOVW: return 0x28<<9;
- case AMOVHU:
- case AMOVH: return 0x29<<9;
- case AMOVBU:
- case AMOVB: return 0x2a<<9;
- }
- }
- diag("bad thumbop oprrr %d", a);
- prasm(curp);
- return 0;
-}
-
-static int32
-thumbopri(int a)
-{
- switch(a) {
- case ASRL: return 0x1<<11;
- case ASRA: return 0x2<<11;
- case ASLL: return 0x0<<11;
- case AADD: return 0x2<<11;
- case ASUB: return 0x3<<11;
- case AMOVW: return 0x0<<11;
- case ACMP: return 0x1<<11;
- }
- diag("bad thumbop opri %d", a);
- prasm(curp);
- return 0;
-}
-
-static int32
-thumbophh(int a)
-{
- switch(a) {
- case AADD: return 0x0<<8;
- case AMOVW: return 0x2<<8;
- case ACMP: return 0x1<<8;
- }
- diag("bad thumbop ophh %d", a);
- prasm(curp);
- return 0;
-}
-
-static int32
-thumbopbra(int a)
-{
- switch(a) {
- case ABEQ: return 0x0<<8;
- case ABNE: return 0x1<<8;
- case ABCS: return 0x2<<8;
- case ABHS: return 0x2<<8;
- case ABCC: return 0x3<<8;
- case ABLO: return 0x3<<8;
- case ABMI: return 0x4<<8;
- case ABPL: return 0x5<<8;
- case ABVS: return 0x6<<8;
- case ABVC: return 0x7<<8;
- case ABHI: return 0x8<<8;
- case ABLS: return 0x9<<8;
- case ABGE: return 0xa<<8;
- case ABLT: return 0xb<<8;
- case ABGT: return 0xc<<8;
- case ABLE: return 0xd<<8;
- }
- diag("bad thumbop opbra %d", a);
- prasm(curp);
- return 0;
-}
-
-static int32
-thumbopmv(int a, int ld)
-{
- switch(a) {
- case AMOVW: return (ld ? 0xd : 0xc)<<11;
- case AMOVH:
- case AMOVHU: return (ld ? 0x11: 0x10)<<11;
- case AMOVB:
- case AMOVBU: return (ld ? 0xf : 0xe)<<11;
- }
- diag("bad thumbop opmv %d", a);
- prasm(curp);
- return 0;
-}
-
-static void
-lowreg(Prog *p, int r)
-{
- if(high(r))
- diag("high reg [%P]", p);
-}
-
-static void
-mult(Prog *p, int n, int m)
-{
- if(m*(n/m) != n)
- diag("%d not M(%d) [%P]", n, m, p);
-}
-
-static void
-numr(Prog *p, int n, int min, int max)
-{
- if(n < min || n > max)
- diag("%d not in %d-%d [%P]", n, min, max, p);
-}
-
-static void
-regis(Prog *p, int r, int r1, int r2)
-{
- if(r != r1 && r != r2)
- diag("reg %d not %d or %d [%P]", r, r1, r2, p);
-}
-
-void
-hputl(int n)
-{
- cbp[1] = n>>8;
- cbp[0] = n;
- cbp += 2;
- cbc -= 2;
- if(cbc <= 0)
- cflush();
-}
-
-void
-thumbcount()
-{
- int i, c = 0, t = 0;
-
- for (i = 0; i < OPCNTSZ; i++)
- t += opcount[i];
- if(t == 0)
- return;
- for (i = 0; i < OPCNTSZ; i++){
- c += opcount[i];
- print("%d: %d %d %d%%\n", i, opcount[i], c, (opcount[i]*100+t/2)/t);
- }
-}
-
-char *op1[] = { "lsl", "lsr", "asr" };
-char *op2[] = { "add", "sub" };
-char *op3[] = { "movw", "cmp", "add", "sub" };
-char *op4[] = { "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror",
- "tst", "neg", "cmp", "cmpn", "or", "mul", "bitc", "movn" };
-char *op5[] = { "add", "cmp", "movw", "bx" };
-char *op6[] = { "smovw", "smovh", "smovb", "lmovb", "lmovw", "lmovhu", "lmovbu", "lmovh" };
-char *op7[] = { "smovw", "lmovw", "smovb", "lmovbu" };
-char *op8[] = { "smovh", "lmovhu" };
-char *op9[] = { "smovw", "lmovw" };
-char *op10[] = { "push", "pop" };
-char *op11[] = { "stmia", "ldmia" };
-
-char *cond[] = { "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" };
-
-#define B(h, l) bits(i, h, l)
-#define IMM(h, l) B(h, l)
-#define REG(h, l) reg(B(h, l))
-#define LHREG(h, l, lh) lhreg(B(h, l), B(lh, lh))
-#define COND(h, l) cond[B(h, l)]
-#define OP1(h, l) op1[B(h, l)]
-#define OP2(h, l) op2[B(h, l)]
-#define OP3(h, l) op3[B(h, l)]
-#define OP4(h, l) op4[B(h, l)]
-#define OP5(h, l) op5[B(h, l)]
-#define OP6(h, l) op6[B(h, l)]
-#define OP7(h, l) op7[B(h, l)]
-#define OP8(h, l) op8[B(h, l)]
-#define OP9(h, l) op9[B(h, l)]
-#define OP10(h, l) op10[B(h, l)]
-#define OP11(h, l) op11[B(h, l)]
-#define SBZ(h, l) if(IMM(h, l) != 0) diag("%x: %x bits %d,%d not zero", pc, i, h, l)
-#define SNBZ(h, l) if(IMM(h, l) == 0) diag("%x: %x bits %d,%d zero", pc, i, h, l)
-#define SBO(h, l) if(IMM(h, l) != 1) diag("%x: %x bits %d,%d not one", pc, i, h, l)
-
-static int
-bits(int i, int h, int l)
-{
- if(h < l)
- diag("h < l in bits");
- return (i&(((1<<(h-l+1))-1)<<l))>>l;
-}
-
-static char *
-reg(int r)
-{
- static char s[4][4];
- static int i = 0;
-
- if(r < 0 || r > 7)
- diag("register %d out of range", r);
- i++;
- if(i == 4)
- i = 0;
- sprint(s[i], "r%d", r);
- return s[i];
-}
-
-static char *regnames[] = { "sp", "lr", "pc" };
-
-static char *
-lhreg(int r, int lh)
-{
- static char s[4][4];
- static int i = 0;
-
- if(lh == 0)
- return reg(r);
- if(r < 0 || r > 7)
- diag("high register %d out of range", r);
- i++;
- if(i == 4)
- i = 0;
- if(r >= 5)
- sprint(s[i], "%s", regnames[r-5]);
- else
- sprint(s[i], "r%d", r+8);
- return s[i];
-}
-
-static void
-illegal(int i, int pc)
-{
- diag("%x: %x illegal instruction", pc, i);
-}
-
-static void
-dis(int i, int pc)
-{
- static int lasto;
- int o, l;
- char *op;
-
- print("%x: %x: ", pc, i);
- if(i&0xffff0000)
- illegal(i, pc);
- o = B(15, 13);
- switch(o){
- case 0:
- o = B(12, 11);
- switch(o){
- case 0:
- case 1:
- case 2:
- print("%s %d, %s, %s\n", OP1(12, 11), IMM(10, 6), REG(5, 3), REG(2, 0));
- return;
- case 3:
- if(B(10, 10) == 0)
- print("%s %s, %s, %s\n", OP2(9, 9), REG(8, 6), REG(5, 3), REG(2, 0));
- else
- print("%s %d, %s, %s\n", OP2(9, 9), IMM(8, 6), REG(5, 3), REG(2, 0));
- return;
- }
- case 1:
- print("%s %d, %s\n", OP3(12, 11), IMM(7, 0), REG(10, 8));
- return;
- case 2:
- o = B(12, 10);
- if(o == 0){
- print("%s %s, %s\n", OP4(9, 6), REG(5, 3), REG(2, 0));
- return;
- }
- if(o == 1){
- o = B(9, 8);
- if(o == 3){
- SBZ(7, 7);
- SBZ(2, 0);
- print("%s %s\n", OP5(9, 8), LHREG(5, 3, 6));
- return;
- }
- SNBZ(7, 6);
- print("%s %s, %s\n", OP5(9, 8), LHREG(5, 3, 6), LHREG(2, 0, 7));
- return;
- }
- if(o == 2 || o == 3){
- print("movw %d(pc)[%x], %s\n", 4*IMM(7, 0), 4*IMM(7, 0)+pc+4, REG(10, 8));
- return;
- }
- op = OP6(11, 9);
- if(*op == 'l')
- print("%s [%s, %s], %s\n", op+1, REG(8, 6), REG(5, 3), REG(2, 0));
- else
- print("%s %s, [%s, %s]\n", op+1, REG(2, 0), REG(8, 6), REG(5, 3));
- return;
- case 3:
- op = OP7(12, 11);
- if(B(12, 11) == 0 || B(12,11) == 1)
- l = 4;
- else
- l = 1;
- if(*op == 'l')
- print("%s %d(%s), %s\n", op+1, l*IMM(10, 6), REG(5, 3), REG(2, 0));
- else
- print("%s %s, %d(%s)\n", op+1, REG(2, 0), l*IMM(10, 6), REG(5, 3));
- return;
- case 4:
- if(B(12, 12) == 0){
- op = OP8(11, 11);
- if(*op == 'l')
- print("%s %d(%s), %s\n", op+1, 2*IMM(10, 6), REG(5, 3), REG(2, 0));
- else
- print("%s %s, %d(%s)\n", op+1, REG(2, 0), 2*IMM(10, 6), REG(5, 3));
- return;
- }
- op = OP9(11, 11);
- if(*op == 'l')
- print("%s %d(sp), %s\n", op+1, 4*IMM(7, 0), REG(10, 8));
- else
- print("%s %s, %d(sp)\n", op+1, REG(10, 8), 4*IMM(7, 0));
- return;
- case 5:
- if(B(12, 12) == 0){
- if(B(11, 11) == 0)
- print("add %d, pc, %s\n", 4*IMM(7, 0), REG(10, 8));
- else
- print("add %d, sp, %s\n", 4*IMM(7, 0), REG(10, 8));
- return;
- }
- if(B(11, 8) == 0){
- print("%s %d, sp\n", OP2(7, 7), 4*IMM(6, 0));
- return;
- }
- SBO(10, 10);
- SBZ(9, 9);
- if(B(8, 8) == 0)
- print("%s sp, %d\n", OP10(11, 11), IMM(7, 0));
- else
- print("%s sp, %d|15\n", OP10(11, 11), IMM(7, 0));
- return;
- case 6:
- if(B(12, 12) == 0){
- print("%s %s, %d\n", OP11(11, 11), REG(10, 8), IMM(7, 0));
- return;
- }
- if(B(11, 8) == 0xf){
- print("swi %d\n", IMM(7, 0));
- return;
- }
- o = IMM(7, 0);
- if(o&0x80)
- o |= 0xffffff00;
- o = pc+4+(o<<1);
- print("b%s %x\n", COND(11, 8), o);
- return;
- case 7:
- o = B(12, 11);
- switch(o){
- case 0:
- o = IMM(10, 0);
- if(o&0x400)
- o |= 0xfffff800;
- o = pc+4+(o<<1);
- print("b %x\n", o);
- return;
- case 1:
- illegal(i, pc);
- return;
- case 2:
- lasto = IMM(10, 0);
- print("bl\n");
- return;
- case 3:
- if(lasto&0x400)
- lasto |= 0xfffff800;
- o = IMM(10, 0);
- o = (pc-2)+4+(o<<1)+(lasto<<12);
- print("bl %x\n", o);
- return;
- }
- }
-}