]> Cypherpunks repositories - gostls13.git/commitdiff
5l: delete dead code
authorRuss Cox <rsc@golang.org>
Thu, 9 Jun 2011 22:07:56 +0000 (18:07 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 9 Jun 2011 22:07:56 +0000 (18:07 -0400)
Thumb code and ARM pre-V4 code is unused,
unmaintained, and almost certainly wrong by now.
Every time I try to change 5l I have to sort out
what's dead code and what's not.

30% of lines of code in this directory deleted.

R=ken2
CC=golang-dev
https://golang.org/cl/4601049

12 files changed:
src/cmd/5l/5.out.h
src/cmd/5l/Makefile
src/cmd/5l/asm.c
src/cmd/5l/l.h
src/cmd/5l/list.c
src/cmd/5l/noop.c
src/cmd/5l/obj.c
src/cmd/5l/optab.c
src/cmd/5l/pass.c
src/cmd/5l/prof.c
src/cmd/5l/span.c
src/cmd/5l/thumb.c [deleted file]

index bdc2c956f843c6c943e8394aad25e3f36537e117..cf86ae48b8acdd6e5d4bae3d15ceaac36aa1bf21 100644 (file)
@@ -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
index c11ebe9908e685a7458a74d9ed6ad51f8bfa4145..9f4a192aa9c03f69093d0933a724fbd7839c3699 100644 (file)
@@ -22,7 +22,6 @@ OFILES=\
        optab.$O\
        pass.$O\
        prof.$O\
-       thumb.$O\
        softfloat.$O\
        span.$O\
        symtab.$O\
index 8dfcd946102d9e56e7525c2749e80fa86d99edb7..4afed2b8034bf95c686e0f97b922490b458a59eb 100644 (file)
@@ -377,7 +377,6 @@ asmb(void)
                        //      Bprint(&bso, "%5.2f dwarf\n", cputime());
                        // dwarfemitdebugsections();
                }
-               asmthumbmap();
                cflush();
                
        }
@@ -728,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)
 {
@@ -804,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 */
@@ -868,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;
@@ -1328,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);
@@ -1359,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);
index f3c9d839de2049dcec1370f2326f1c0be673995f..182f3e738b941df5b6c1706067fd6a74951cfedc 100644 (file)
@@ -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);
 
index 2ae25d491e7de04a6a6a3f142eaf8c1fa537bf06..fa838215b1bf039772e38bf9f1b9e56e5e3bfad9 100644 (file)
@@ -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",
index bdcc3cad897a4f42ba0139a207c00d687b1df2b1..e7c2db5f2e3f22fa86f7c824072c77281b470d31 100644 (file)
@@ -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
index 2089e8f0bd30b61cd683a2bb2b035dab339aeb29..dd3a7329a2ca9f63c1ced695f10bb98013956db3 100644 (file)
@@ -242,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;
@@ -286,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));
@@ -406,8 +403,6 @@ nopout(Prog *p)
        p->to.type = D_NONE;
 }
 
-static void puntfp(Prog *);
-
 void
 ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
 {
@@ -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)
 {
index 4816aa40f18e1da642c0331ff764f6300e7b285e..514786f85e5bbf3ea4f00699e8e42773358901c0 100644 (file)
@@ -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 },
@@ -181,34 +180,34 @@ 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 },
-       { AMOVH,        C_REG,  C_NONE, C_ADDR, 94, 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 },
-       { AMOVHU,       C_REG,  C_NONE, C_ADDR, 94, 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 },
-       { AMOVB,        C_ADDR, C_NONE, C_REG,          93, 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 },
-       { AMOVH,        C_ADDR, C_NONE, C_REG,          93, 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 },
-       { AMOVHU,       C_ADDR, C_NONE, C_REG,          93, 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 },
index 7e1ba6a09a1bc31d08cdbe99db2d7f65f6f4c363..194a1ed5f3ac783932e9f7b5211f65566e6d42ff 100644 (file)
@@ -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)
index ad115a8ca80ec939ae7f2f93651bef528069cc79..48ad2dc594ca3bbc81833d9e558d502fb20777df 100644 (file)
@@ -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(;;) {
index 0fe31059761e418d9741db47ee40b0e97814a980..eb79f6b5a2b58c94d0efd5673705f0b3c5a4a7d2 100644 (file)
@@ -49,86 +49,6 @@ isbranch(Prog *p)
        return (as >= ABEQ && as <= ABLE) || as == AB || as == ABL || as == ABX;
 }
 
-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)
 {
@@ -182,7 +102,6 @@ span(void)
        otxt = c;
        for(cursym = textp; cursym != nil; cursym = cursym->next) {
                p = cursym->text;
-               setarch(p);
                p->pc = c;
                cursym->value = c;
 
@@ -193,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);
                        }
@@ -230,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);
                }
@@ -253,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) {
@@ -298,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);
        
        /*
@@ -378,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);
        
@@ -412,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)
@@ -441,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;
@@ -461,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;
@@ -480,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;
@@ -591,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:
@@ -768,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--;
@@ -804,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;
 }
 
@@ -883,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);
@@ -903,9 +702,6 @@ ocmp(const void *a1, const void *a2)
        p1 = (Optab*)a1;
        p2 = (Optab*)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;
@@ -925,15 +721,11 @@ buildop(void)
 {
        int i, n, r;
 
-       armv4 = 1;
        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;
diff --git a/src/cmd/5l/thumb.c b/src/cmd/5l/thumb.c
deleted file mode 100644 (file)
index a6f729b..0000000
+++ /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;
-               }
-       }
-}