]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/7l/span.c
aux/realemu: run cpuproc in same fd group as fileserver
[plan9front.git] / sys / src / cmd / 7l / span.c
old mode 100755 (executable)
new mode 100644 (file)
index 65ba2df..17f57d6
 #include       "l.h"
 
+#define        BIT(n)  ((uvlong)1<<(n))
+
+static struct {
+       ulong   start;
+       ulong   size;
+} pool;
+
+static void    checkpool(Prog*, int);
+static void    flushpool(Prog*, int);
+static int     ispcdisp(long);
+
+static Optab *badop;
+static Oprang  oprange[ALAST];
+
 void
 span(void)
 {
        Prog *p;
-       Sym *setext;
+       Sym *setext, *s;
        Optab *o;
-       int m;
-       long c;
+       int m, bflag, i;
+       long c, otxt, v;
 
        if(debug['v'])
                Bprint(&bso, "%5.2f span\n", cputime());
        Bflush(&bso);
+
+       bflag = 0;
        c = INITTEXT;
+       otxt = c;
        for(p = firstp; p != P; p = p->link) {
+               if(p->as == ADWORD && (c&7) != 0)
+                       c += 4;
                p->pc = c;
                o = oplook(p);
                m = o->size;
                if(m == 0) {
                        if(p->as == ATEXT) {
                                curtext = p;
-                               autosize = p->to.offset + 8;
+                               autosize = p->to.offset + PCSZ;
                                if(p->from.sym != S)
                                        p->from.sym->value = c;
+                               /* need passes to resolve branches */
+                               if(c-otxt >= 1L<<20)
+                                       bflag = 1;
+                               otxt = c;
                                continue;
                        }
                        diag("zero-width instruction\n%P", p);
                        continue;
                }
+               switch(o->flag & (LFROM|LTO)) {
+               case LFROM:
+                       addpool(p, &p->from);
+                       break;
+               case LTO:
+                       addpool(p, &p->to);
+                       break;
+               }
+               if(p->as == AB || p->as == ARET || p->as == AERET || p->as == ARETURN)  /* TO DO: other unconditional operations */
+                       checkpool(p, 0);
                c += m;
+               if(blitrl)
+                       checkpool(p, 1);
        }
+
+       /*
+        * if any procedure is large enough to
+        * generate a large SBRA branch, then
+        * generate extra passes putting branches
+        * around jmps to fix. this is rare.
+        */
+       while(bflag) {
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f span1\n", cputime());
+               bflag = 0;
+               c = INITTEXT;
+               for(p = firstp; p != P; p = p->link) {
+                       if(p->as == ADWORD && (c&7) != 0)
+                               c += 4;
+                       p->pc = c;
+                       o = oplook(p);
+/* very large branches
+                       if(o->type == 6 && p->cond) {
+                               otxt = p->cond->pc - c;
+                               if(otxt < 0)
+                                       otxt = -otxt;
+                               if(otxt >= (1L<<17) - 10) {
+                                       q = prg();
+                                       q->link = p->link;
+                                       p->link = q;
+                                       q->as = AB;
+                                       q->to.type = D_BRANCH;
+                                       q->cond = p->cond;
+                                       p->cond = q;
+                                       q = prg();
+                                       q->link = p->link;
+                                       p->link = q;
+                                       q->as = AB;
+                                       q->to.type = D_BRANCH;
+                                       q->cond = q->link->link;
+                                       bflag = 1;
+                               }
+                       }
+ */
+                       m = o->size;
+                       if(m == 0) {
+                               if(p->as == ATEXT) {
+                                       curtext = p;
+                                       autosize = p->to.offset + PCSZ;
+                                       if(p->from.sym != S)
+                                               p->from.sym->value = c;
+                                       continue;
+                               }
+                               diag("zero-width instruction\n%P", p);
+                               continue;
+                       }
+                       c += m;
+               }
+       }
+
+       if(debug['t']) {
+               /* 
+                * add strings to text segment
+                */
+               c = rnd(c, 8);
+               for(i=0; i<NHASH; i++)
+               for(s = hash[i]; s != S; s = s->link) {
+                       if(s->type != SSTRING)
+                               continue;
+                       v = s->value;
+                       while(v & 3)
+                               v++;
+                       s->value = c;
+                       c += v;
+               }
+       }
+
        c = rnd(c, 8);
 
        setext = lookup("etext", 0);
@@ -40,10 +148,148 @@ span(void)
        if(INITRND)
                INITDAT = rnd(c, INITRND);
        if(debug['v'])
-               Bprint(&bso, "tsize = %lux\n", textsize);
+               Bprint(&bso, "tsize = %#llux\n", textsize);
        Bflush(&bso);
 }
-               
+
+/*
+ * when the first reference to the literal pool threatens
+ * to go out of range of a 1Mb PC-relative offset
+ * drop the pool now, and branch round it.
+ */
+static void
+checkpool(Prog *p, int skip)
+{
+       if(pool.size >= 0xffff0 || !ispcdisp(p->pc+4+pool.size - pool.start+8))
+               flushpool(p, skip);
+       else if(p->link == P)
+               flushpool(p, 2);
+}
+
+static void
+flushpool(Prog *p, int skip)
+{
+       Prog *q;
+
+       if(blitrl) {
+               if(skip){
+                       if(debug['v'] && skip == 1)
+                               print("note: flush literal pool at %#llux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);
+                       q = prg();
+                       q->as = AB;
+                       q->to.type = D_BRANCH;
+                       q->cond = p->link;
+                       q->link = blitrl;
+                       blitrl = q;
+               }
+               else if(p->pc+pool.size-pool.start < 1024*1024)
+                       return;
+               elitrl->link = p->link;
+               p->link = blitrl;
+               blitrl = 0;     /* BUG: should refer back to values until out-of-range */
+               elitrl = 0;
+               pool.size = 0;
+               pool.start = 0;
+       }
+}
+
+/*
+ * TO DO: hash
+ */
+void
+addpool(Prog *p, Adr *a)
+{
+       Prog *q, t;
+       int sz;
+
+
+       t = zprg;
+       t.as = AWORD;
+       sz = 4;
+       switch(aclass(a)) {
+       default:
+               if(p->as == AMOV && (a->name == D_EXTERN || a->name == D_STATIC)
+               || (a->offset >> 32) != 0 && (a->offset >> 31) != -1){
+                       t.as = ADWORD;
+                       sz = 8;
+               }
+               t.to = *a;
+               break;
+       case C_PSAUTO:
+       case C_PPAUTO:
+       case C_UAUTO4K:
+       case C_UAUTO8K:
+       case C_UAUTO16K:
+       case C_UAUTO32K:
+       case C_UAUTO64K:
+       case C_NSAUTO:
+       case C_NPAUTO:
+       case C_LAUTO:
+       case C_PPOREG:
+       case C_PSOREG:
+       case C_UOREG4K:
+       case C_UOREG8K:
+       case C_UOREG16K:
+       case C_UOREG32K:
+       case C_UOREG64K:
+       case C_NSOREG:
+       case C_NPOREG:
+       case C_LOREG:
+       case C_LACON:
+               if((instoffset >> 32) != 0 && (instoffset >> 31) != -1)
+                       diag("offset too large\n%P", p);
+               t.to.type = D_CONST;
+               t.to.offset = instoffset;
+               break;
+       }
+
+       for(q = blitrl; q != P; q = q->link)    /* could hash on t.t0.offset */
+               if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
+                       p->cond = q;
+                       return;
+               }
+
+       q = prg();
+       *q = t;
+       q->pc = pool.size;
+
+       if(blitrl == P) {
+               blitrl = q;
+               pool.start = p->pc;
+       } else
+               elitrl->link = q;
+       elitrl = q;
+       pool.size = rnd(pool.size, sz);
+       pool.size += sz;
+
+       p->cond = q;
+}
+
+int
+relinv(int a)
+{
+       switch(a) {
+       case ABEQ:      return ABNE;
+       case ABNE:      return ABEQ;
+       case ABCS:      return ABCC;
+       case ABHS:      return ABLO;
+       case ABCC:      return ABCS;
+       case ABLO:      return ABHS;
+       case ABMI:      return ABPL;
+       case ABPL:      return ABMI;
+       case ABVS:      return ABVC;
+       case ABVC:      return ABVS;
+       case ABHI:      return ABLS;
+       case ABLS:      return ABHI;
+       case ABGE:      return ABLT;
+       case ABLT:      return ABGE;
+       case ABGT:      return ABLE;
+       case ABLE:      return ABGT;
+       }
+       diag("unknown relation: %A", a);
+       return a;
+}
+
 void
 xdefine(char *p, int t, long v)
 {
@@ -56,25 +302,202 @@ xdefine(char *p, int t, long v)
        }
 }
 
-vlong          /* BUG? */
+long
 regoff(Adr *a)
 {
 
-       offset = 0;
+       instoffset = 0;
        aclass(a);
-       return offset;
+       return instoffset;
+}
+
+static int
+ispcdisp(long v)
+{
+       /* pc-relative addressing will reach? */
+       return v >= -0xfffff && v <= 0xfffff && (v&3) == 0;
+}
+
+static int
+isaddcon(vlong v)
+{
+       /* uimm12 or uimm24? */
+       if(v < 0)
+               return 0;
+       if((v & 0xFFF) == 0)
+               v >>= 12;
+       return v <= 0xFFF;
 }
 
+static int
+isbitcon64(uvlong v)
+{
+       return findmask(v) != nil;
+}
+
+static int
+isbitcon32(uvlong v)
+{
+       return (v >> 32) == 0 && findmask(v | v<<32) != nil;
+}
+
+static int
+isbitcon(uvlong v)
+{
+       Mask *m;
+
+       if((v >> 32) != 0)
+               return 0;
+       m = findmask(v);
+       if(m == nil)
+               return 0;
+       if(m->s >= 32)
+               return 0;
+       return 1;
+}
+
+static int
+maxstr1(uvlong x)
+{
+       int i;
+
+       for(i = 0; x != 0; i++)
+               x &= x<<1;
+       return i;
+}
+
+static uvlong
+findrotl(uvlong x, int *l)
+{
+       int i;
+
+       for(i = 0; (x&1) == 0 || (x&BIT(63)) != 0; i++)
+               x = (x<<1) | ((x&BIT(63))!=0);
+       *l = i;
+       return x;
+}
+
+static int
+findmask64(Mask *m, uvlong v)
+{
+       uvlong x, f, fm;
+       int i, lr, l0, l1, e;
+
+       if(v == 0 || v == ~(uvlong)0)
+               return 0;
+       x = findrotl(v, &lr);
+       l1 = maxstr1(x);
+       l0 = maxstr1(~x);
+       e = l0+l1;
+       if(e == 0 || l1 == 64 || l0 == 64 || 64%e != 0)
+               return 0;
+       if(e != 64){
+               f = BIT(l1)-1;
+               fm = BIT(e)-1;
+               if(e > 32 && x != f)
+                       return 0;
+               for(i = 0; i < 64; i += e)
+                       if(((x>>i) & fm) != f)
+                               return 0;
+       }
+       print("%#llux   %#llux 1:%d 0:%d r:%d\n", v, x, l1, l0, lr%e);
+       m->v = v;
+       m->s = l1;
+       m->e = e;
+       m->r = lr%e;
+       return 1;
+}
+
+/*
+ * internal class codes for different constant classes:
+ * they partition the constant/offset range into disjoint ranges that
+ * are somehow treated specially by one or more load/store instructions.
+ */
+static int     autoclass[] = {C_PSAUTO, C_NSAUTO, C_NPAUTO, C_PSAUTO, C_PPAUTO, C_UAUTO4K, C_UAUTO8K, C_UAUTO16K, C_UAUTO32K, C_UAUTO64K, C_LAUTO};
+static int     oregclass[] = {C_ZOREG, C_NSOREG, C_NPOREG, C_PSOREG, C_PPOREG, C_UOREG4K, C_UOREG8K, C_UOREG16K, C_UOREG32K, C_UOREG64K, C_LOREG};
+static int     sextclass[] = {C_SEXT1, C_LEXT, C_LEXT, C_SEXT1, C_SEXT1, C_SEXT1, C_SEXT2, C_SEXT4, C_SEXT8, C_SEXT16, C_LEXT};
+
 /*
- * note that we can't generate every 32 bit constant with MOVQA+MOVQAH, hence the
- * comparison with 0x7fff8000.  offset >= this value gets incorrectly sign extended in
- * the 64 bit register.
+ * return appropriate index into tables above
  */
+static int
+constclass(vlong l)
+{
+       if(l == 0)
+               return 0;
+       if(l < 0){
+               if(l >= -256)
+                       return 1;
+               if(l >= -512 && (l&7) == 0)
+                       return 2;
+               return 10;
+       }
+       if(l <= 255)
+               return 3;
+       if(l <= 504 && (l&7) == 0)
+               return 4;
+       if(l <= 4095)
+               return 5;
+       if(l <= 8190 && (l&1) == 0)
+               return 6;
+       if(l <= 16380 && (l&3) == 0)
+               return 7;
+       if(l <= 32760 && (l&7) == 0)
+               return 8;
+       if(l <= 65520 && (l&0xF) == 0)
+               return 9;
+       return 10;
+}
+
+/*
+ * given an offset v and a class c (see above)
+ * return the offset value to use in the instruction,
+ * scaled if necessary
+ */
+vlong
+offsetshift(vlong v, int c)
+{
+       vlong vs;
+       int s;
+       static int shifts[] = {0, 1, 2, 3, 4};
+
+       s = 0;
+       if(c >= C_SEXT1 && c <= C_SEXT16)
+               s = shifts[c-C_SEXT1];
+       else if(c >= C_UAUTO4K && c <= C_UAUTO64K)
+               s = shifts[c-C_UAUTO4K];
+       else if(c >= C_UOREG4K && c <= C_UOREG64K)
+               s = shifts[c-C_UOREG4K];
+       vs = v>>s;
+       if(vs<<s != v)
+               diag("odd offset: %lld\n%P", v, curp);
+       return vs;
+}
+
+/*
+ * if v contains a single 16-bit value aligned
+ * on a 16-bit field, and thus suitable for movk/movn,
+ * return the field index 0 to 3; otherwise return -1
+ */
+int
+movcon(vlong v)
+{
+       int s;
+
+       for(s = 0; s < 64; s += 16)
+               if((v & ~((uvlong)0xFFFF<<s)) == 0)
+                       return s/16;
+       return -1;
+}
+
+int
 aclass(Adr *a)
 {
+       vlong v;
        Sym *s;
        int t;
 
+       instoffset = 0;
        switch(a->type) {
        case D_NONE:
                return C_NONE;
@@ -82,145 +505,184 @@ aclass(Adr *a)
        case D_REG:
                return C_REG;
 
-       case D_FREG:
-               return C_FREG;
+       case D_VREG:
+               return C_VREG;
+
+       case D_SP:
+               return C_RSP;
+
+       case D_COND:
+               return C_COND;
 
-       case D_FCREG:
-               return C_FCREG;
+       case D_SHIFT:
+               return C_SHIFT;
 
-       case D_PREG:
-               return C_PREG;
+       case D_EXTREG:
+               return C_EXTREG;
 
-       case D_PCC:
-               return C_PCC;
+       case D_ROFF:
+               return C_ROFF;
+
+       case D_XPOST:
+               return C_XPOST;
+
+       case D_XPRE:
+               return C_XPRE;
+
+       case D_FREG:
+               return C_FREG;
 
        case D_OREG:
                switch(a->name) {
                case D_EXTERN:
                case D_STATIC:
-                       if(a->sym == 0) {
+                       if(a->sym == 0 || a->sym->name == 0) {
                                print("null sym external\n");
                                print("%D\n", a);
                                return C_GOK;
                        }
-                       t = a->sym->type;
+                       s = a->sym;
+                       t = s->type;
                        if(t == 0 || t == SXREF) {
                                diag("undefined external: %s in %s",
-                                       a->sym->name, TNAME);
-                               a->sym->type = SDATA;
+                                       s->name, TNAME);
+                               s->type = SDATA;
                        }
-                       offset = a->sym->value + a->offset - BIG;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SEXT;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LEXT;
-               badoff:
-                       diag("offset out of range: %#llux", offset);
-                       return C_GOK;
+                       if(dlm) {
+                               switch(t) {
+                               default:
+                                       instoffset = s->value + a->offset + INITDAT;
+                                       break;
+                               case SUNDEF:
+                               case STEXT:
+                               case SCONST:
+                               case SLEAF:
+                               case SSTRING:
+                                       instoffset = s->value + a->offset;
+                                       break;
+                               }
+                               return C_ADDR;
+                       }
+                       instoffset = s->value + a->offset;
+                       if(instoffset >= 0)
+                               return sextclass[constclass(instoffset)];
+                       return C_LEXT;
+
                case D_AUTO:
-                       offset = autosize + a->offset;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SAUTO;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LAUTO;
-                       goto badoff;
+                       instoffset = autosize + a->offset;
+                       return autoclass[constclass(instoffset)];
+
                case D_PARAM:
-                       offset = autosize + a->offset + 8L;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SAUTO;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LAUTO;
-                       goto badoff;
+                       instoffset = autosize + a->offset + PCSZ;
+                       return autoclass[constclass(instoffset)];
+
                case D_NONE:
-                       offset = a->offset;
-                       if(offset == 0)
-                               return C_ZOREG;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SOREG;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LOREG;
-                       goto badoff;
+                       instoffset = a->offset;
+                       return oregclass[constclass(instoffset)];
                }
                return C_GOK;
 
+       case D_SPR:
+               return C_SPR;
+
+       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",
+                                       s->name, TNAME);
+                               s->type = SDATA;
+                       }
+                       instoffset = s->value + a->offset + INITDAT;
+                       if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)
+                               instoffset = s->value + a->offset;
+                       return C_LCON;
+               }
+               return C_GOK;
+
+       case D_FCONST:
+               return C_FCON;
+
        case D_CONST:
                switch(a->name) {
 
                case D_NONE:
-                       offset = a->offset;
-                       if(offset > 0) {
-                               if(offset <= 0xffLL)
-                                       return C_BCON;
-                               if(offset <= 0x7fffLL)
-                                       return C_SCON;
-                               if((offset & 0xffffLL) == 0 && offset <= 0x7fff0000LL)
-                                       return C_UCON;
-                               if (offset < 0x7fff8000LL)
-                                       return C_LCON;
-                               return C_QCON;
-                       }
-                       if(offset == 0)
+                       instoffset = a->offset;
+                       if(a->reg != NREG && a->reg != REGZERO)
+                               goto aconsize;
+
+                       v = instoffset;
+                       if(v == 0)
                                return C_ZCON;
-                       if(offset >= -0x100LL)
-                               return C_NCON;
-                       if(offset >= -0x8000LL)
-                               return C_SCON;
-                       if((offset & 0xffffLL) == 0 && offset >= -0x80000000LL)
-                               return C_UCON;
-                       if (offset >= -0x80000000LL)
-                               return C_LCON;
-                       return C_QCON;
+                       if(isaddcon(v)){
+                               if(isbitcon(v))
+                                       return C_ABCON;
+                               if(v <= 0xFFF)
+                                       return C_ADDCON0;
+                               return C_ADDCON;
+                       }
+                       t = movcon(v);
+                       if(t >= 0){
+                               if(isbitcon(v))
+                                       return C_MBCON;
+                               return C_MOVCON;
+                       }
+                       t = movcon(~v);
+                       if(t >= 0){
+                               if(isbitcon(v))
+                                       return C_MBCON;
+                               return C_MOVCON;
+                       }
+                       if(isbitcon(v))
+                               return C_BITCON;
+                       if(isbitcon64(v))
+                               return C_BITCON64;
+                       if(isbitcon32(v))
+                               return C_BITCON32;
+                       return C_LCON;
 
                case D_EXTERN:
                case D_STATIC:
                        s = a->sym;
-                       if(s == 0) {
-                               print("null sym const\n");
-                               print("%D\n", a);
-                               return C_GOK;
-                       }
+                       if(s == S)
+                               break;
                        t = s->type;
-                       if(t == 0 || t == SXREF) {
+                       switch(t) {
+                       case 0:
+                       case SXREF:
                                diag("undefined external: %s in %s",
                                        s->name, TNAME);
                                s->type = SDATA;
-                       }
-                       if(s->type == STEXT || s->type == SLEAF) {
-                               offset = s->value + a->offset;
+                               break;
+                       case SUNDEF:
+                       case STEXT:
+                       case SSTRING:
+                       case SCONST:
+                       case SLEAF:
+                               instoffset = s->value + a->offset;
                                return C_LCON;
                        }
-                       offset = s->value + a->offset - BIG;
-                       if (offset == 0L) {
-                               offset = s->value + a->offset + INITDAT;
-                               return C_LCON;          /* botch */
+                       if(!dlm) {
+                               instoffset = s->value + a->offset;
+                               if(instoffset != 0 && isaddcon(instoffset))
+                                       return C_AECON;
                        }
-                       if(offset >= -BIG && offset < BIG && offset != 0L)
-                               return C_SECON;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000L && offset != 0LL /*&& offset >= -INITDAT*/)
-                               return C_LECON;
-                       /*offset = s->value + a->offset + INITDAT;*/
-/*                     if (offset >= -BIG && offset < BIG)
-                               return C_SCON;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LCON; */
-                       goto badoff;
-                       /*return C_QCON;*/
+                       instoffset = s->value + a->offset + INITDAT;
+                       return C_LCON;
 
                case D_AUTO:
-                       offset = autosize + a->offset;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SACON;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LACON;
-                       goto badoff;
+                       instoffset = autosize + a->offset;
+                       goto aconsize;
 
                case D_PARAM:
-                       offset = autosize + a->offset + 8L;
-                       if(offset >= -BIG && offset < BIG)
-                               return C_SACON;
-                       if (offset >= -0x80000000LL && offset < 0x7fff8000LL)
-                               return C_LACON;
-                       goto badoff;
+                       instoffset = autosize + a->offset + PCSZ;
+               aconsize:
+                       if(isaddcon(instoffset))
+                               return C_AACON;
+                       return C_LACON;
                }
                return C_GOK;
 
@@ -234,7 +696,7 @@ Optab*
 oplook(Prog *p)
 {
        int a1, a2, a3, r;
-       char *c1, *c3;
+       char *c1, *c2, *c3;
        Optab *o, *e;
 
        a1 = p->optab;
@@ -265,22 +727,31 @@ oplook(Prog *p)
                }
                o = oprange[r].stop; /* just generate an error */
        }
+       if(0) {
+               print("oplook %A %d %d %d\n",
+                       (int)p->as, a1, a2, a3);
+               print("         %d %d\n", p->from.type, p->to.type);
+       }
        e = oprange[r].stop;
        c1 = xcmp[a1];
+       c2 = xcmp[a2];
        c3 = xcmp[a3];
        for(; o<e; o++)
-               if(o->a2 == a2)
+               if(o->a2 == a2 || c2[o->a2])
                if(c1[o->a1])
                if(c3[o->a3]) {
+                       if(0)
+                               print("%P\t-> %d (%d %d %d)\n", p, o->type,
+                                       o->a1, o->a2, o->a3);
                        p->optab = (o-optab)+1;
                        return o;
                }
-       diag("illegal combination %A %d %d %d (opcross %d)",
-               p->as, p->from.class-1, a2, a3, a1);
-       if(!debug['a'])
-               prasm(p);
-       o = optab;
-       p->optab = (o-optab)+1;
+       diag("illegal combination %A %R %R %R",
+               p->as, a1, a2, a3);
+       prasm(p);
+       o = badop;
+       if(o == 0)
+               errorexit();
        return o;
 }
 
@@ -291,66 +762,156 @@ cmp(int a, int b)
        if(a == b)
                return 1;
        switch(a) {
-       case C_QCON:
-               if(b == C_ZCON || b == C_BCON || b == C_NCON || b == C_SCON || b == C_UCON || b == C_LCON)
+       case C_RSP:
+               if(b == C_REG)
                        return 1;
                break;
-       case C_LCON:
-               if(b == C_ZCON || b == C_BCON || b == C_NCON || b == C_SCON || b == C_UCON)
+
+       case C_REG:
+               if(b == C_ZCON)
                        return 1;
                break;
-       case C_UCON:
+
+       case C_ADDCON0:
                if(b == C_ZCON)
                        return 1;
                break;
-       case C_SCON:
-               if(b == C_ZCON || b == C_BCON || b == C_NCON)
+
+       case C_ADDCON:
+               if(b == C_ZCON || b == C_ADDCON0 || b == C_ABCON)
                        return 1;
                break;
-       case C_BCON:
-               if(b == C_ZCON)
+
+       case C_BITCON32:
+       case C_BITCON64:
+               if(b == C_BITCON)
+                       return 1;
+               /* wet floor */
+       case C_BITCON:
+               if(b == C_ABCON || b == C_MBCON)
                        return 1;
                break;
+
+       case C_MOVCON:
+               if(b == C_MBCON || b == C_ZCON || b == C_ADDCON0)
+                       return 1;
+               break;
+
+       case C_LCON:
+               if(b == C_ZCON || b == C_BITCON || b == C_BITCON32 || b == C_BITCON64 || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON)
+                       return 1;
+               break;
+
+       case C_VCON:
+               return cmp(C_LCON, b);
+
        case C_LACON:
-               if(b == C_SACON)
+               if(b == C_AACON)
                        return 1;
                break;
-       case C_LBRA:
-               if(b == C_SBRA)
+
+       case C_SEXT2:
+               if(b == C_SEXT1)
+                       return 1;
+               break;
+
+       case C_SEXT4:
+               if(b == C_SEXT1 || b == C_SEXT2)
+                       return 1;
+               break;
+
+       case C_SEXT8:
+               if(b >= C_SEXT1 && b <= C_SEXT4)
                        return 1;
                break;
+
+       case C_SEXT16:
+               if(b >= C_SEXT1 && b <= C_SEXT8)
+                       return 1;
+               break;
+
        case C_LEXT:
-               if(b == C_SEXT)
+               if(b >= C_SEXT1 && b <= C_SEXT16)
+                       return 1;
+               break;
+
+       case C_PPAUTO:
+               if(b == C_PSAUTO)
+                       return 1;
+               break;
+
+       case C_UAUTO4K:
+               if(b == C_PSAUTO || b == C_PPAUTO)
                        return 1;
                break;
+
+       case C_UAUTO8K:
+               return cmp(C_UAUTO4K, b);
+
+       case C_UAUTO16K:
+               return cmp(C_UAUTO8K, b);
+
+       case C_UAUTO32K:
+               return cmp(C_UAUTO16K, b);
+
+       case C_UAUTO64K:
+               return cmp(C_UAUTO32K, b);
+
+       case C_NPAUTO:
+               return cmp(C_NSAUTO, b);
+
        case C_LAUTO:
-               if(b == C_SAUTO)
+               return cmp(C_NPAUTO, b) || cmp(C_UAUTO64K, b);
+
+       case C_PSOREG:
+               if(b == C_ZOREG)
                        return 1;
                break;
-       case C_REG:
-/*             if(b == C_ZCON)
-                       return 1; */
+
+       case C_PPOREG:
+               if(b == C_ZOREG || b == C_PSOREG)
+                       return 1;
                break;
-       case C_LOREG:
-               if(b == C_ZOREG || b == C_SOREG)
+
+       case C_UOREG4K:
+               if(b == C_ZOREG || b == C_PSAUTO || b == C_PSOREG || b == C_PPAUTO || b == C_PPOREG)
                        return 1;
                break;
-       case C_SOREG:
-               if(b == C_ZOREG)
+
+       case C_UOREG8K:
+               return cmp(C_UOREG4K, b);
+
+       case C_UOREG16K:
+               return cmp(C_UOREG8K, b);
+
+       case C_UOREG32K:
+               return cmp(C_UOREG16K, b);
+
+       case C_UOREG64K:
+               return cmp(C_UOREG32K, b);
+
+       case C_NPOREG:
+               return cmp(C_NSOREG, b);
+
+       case C_LOREG:
+               return cmp(C_NPOREG, b) || cmp(C_UOREG64K, b);
+
+       case C_LBRA:
+               if(b == C_SBRA)
                        return 1;
                break;
        }
        return 0;
 }
 
-int
-ocmp(void *a1, void *a2)
+static int
+ocmp(const void *a1, const void *a2)
 {
        Optab *p1, *p2;
        int n;
 
-       p1 = a1;
-       p2 = a2;
+       p1 = (Optab*)a1;
+       p2 = (Optab*)a2;
        n = p1->as - p2->as;
        if(n)
                return n;
@@ -370,12 +931,14 @@ void
 buildop(void)
 {
        int i, n, r;
+       Oprang t;
 
-       for(i=0; i<32; i++)
-               for(n=0; n<32; n++)
+       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++)
                ;
+       badop = optab+n;
        qsort(optab, n, sizeof(optab[0]), ocmp);
        for(i=0; i<n; i++) {
                r = optab[i].as;
@@ -384,201 +947,411 @@ buildop(void)
                        i++;
                oprange[r].stop = optab+i;
                i--;
-               
-               switch(r)
-               {
+
+               t = oprange[r];
+               switch(r){
                default:
                        diag("unknown op in build: %A", r);
                        errorexit();
-               case AADDQ:
-                       oprange[AS4ADDQ] = oprange[r];
-                       oprange[AS8ADDQ] = oprange[r];
-                       oprange[ASUBQ] = oprange[r];
-                       oprange[AS4SUBQ] = oprange[r];
-                       oprange[AS8SUBQ] = oprange[r];
-                       break;
-               case AADDL:
-                       oprange[AADDLV] = oprange[r];
-                       oprange[AS4ADDL] = oprange[r];
-                       oprange[AS8ADDL] = oprange[r];
-                       oprange[AADDQV] = oprange[r];
-                       oprange[ASUBQV] = oprange[r];
-                       oprange[ASUBL] = oprange[r];
-                       oprange[ASUBLV] = oprange[r];
-                       oprange[AS4SUBL] = oprange[r];
-                       oprange[AS8SUBL] = oprange[r];
-                       break;
-               case AAND:
-                       oprange[AANDNOT] = oprange[r];
-                       oprange[AOR] = oprange[r];
-                       oprange[AORNOT] = oprange[r];
-                       oprange[AXOR] = oprange[r];
-                       oprange[AXORNOT] = oprange[r];
-                       break;
-               case AMULQ:
-                       oprange[ACMPEQ] = oprange[r];
-                       oprange[ACMPGT] = oprange[r];
-                       oprange[ACMPGE] = oprange[r];
-                       oprange[ACMPUGT] = oprange[r];
-                       oprange[ACMPUGE] = oprange[r];
-                       oprange[ACMPBLE] = oprange[r];
-                       oprange[ACMOVEQ] = oprange[r];
-                       oprange[ACMOVNE] = oprange[r];
-                       oprange[ACMOVLT] = oprange[r];
-                       oprange[ACMOVGE] = oprange[r];
-                       oprange[ACMOVLE] = oprange[r];
-                       oprange[ACMOVGT] = oprange[r];
-                       oprange[ACMOVLBS] = oprange[r];
-                       oprange[ACMOVLBC] = oprange[r];
-                       oprange[AMULL] = oprange[r];
-                       oprange[AMULLV] = oprange[r];
-                       oprange[AMULQV] = oprange[r];
-                       oprange[AUMULH] = oprange[r];
-                       oprange[ASLLQ] = oprange[r];
-                       oprange[ASRLQ] = oprange[r];
-                       oprange[ASRAQ] = oprange[r];
-                       oprange[AEXTBL] = oprange[r];
-                       oprange[AEXTWL] = oprange[r];
-                       oprange[AEXTLL] = oprange[r];
-                       oprange[AEXTQL] = oprange[r];
-                       oprange[AEXTWH] = oprange[r];
-                       oprange[AEXTLH] = oprange[r];
-                       oprange[AEXTQH] = oprange[r];
-                       oprange[AINSBL] = oprange[r];
-                       oprange[AINSWL] = oprange[r];
-                       oprange[AINSLL] = oprange[r];
-                       oprange[AINSQL] = oprange[r];
-                       oprange[AINSWH] = oprange[r];
-                       oprange[AINSLH] = oprange[r];
-                       oprange[AINSQH] = oprange[r];
-                       oprange[AMSKBL] = oprange[r];
-                       oprange[AMSKWL] = oprange[r];
-                       oprange[AMSKLL] = oprange[r];
-                       oprange[AMSKQL] = oprange[r];
-                       oprange[AMSKWH] = oprange[r];
-                       oprange[AMSKLH] = oprange[r];
-                       oprange[AMSKQH] = oprange[r];
-                       oprange[AZAP] = oprange[r];
-                       oprange[AZAPNOT] = oprange[r];
+               case AXXX:
+                       break;
+               case AADD:
+                       oprange[AADDS] = t;
+                       oprange[ASUB] = t;
+                       oprange[ASUBS] = t;
+                       oprange[AADDW] = t;
+                       oprange[AADDSW] = t;
+                       oprange[ASUBW] = t;
+                       oprange[ASUBSW] = t;
+                       break;
+               case AAND:      /* logical immediate, logical shifted register */
+                       oprange[AANDS] = t;
+                       oprange[AEOR] = t;
+                       oprange[AORR] = t;
+                       break;
+               case AANDW:
+                       oprange[AANDSW] = t;
+                       oprange[AANDW] = t;
+                       oprange[AEORW] = t;
+                       oprange[AORRW] = t;
+                       break;
+               case ABIC:      /* only logical shifted register */
+                       oprange[ABICS] = t;
+                       oprange[AEON] = t;
+                       oprange[AORN] = t;
+                       break;
+               case ABICW:
+                       oprange[ABICSW] = t;
+                       oprange[ABICW] = t;
+                       oprange[AEONW] = t;
+                       oprange[AORNW] = t;
+                       break;
+               case ANEG:
+                       oprange[ANEGS] = t;
+                       oprange[ANEGSW] = t;
+                       oprange[ANEGW] = t;
+                       break;
+               case AADC:      /* rn=Rd */
+                       oprange[AADCW] = t;
+                       oprange[AADCS] = t;
+                       oprange[AADCSW] = t;
+                       oprange[ASBC] = t;
+                       oprange[ASBCW] = t;
+                       oprange[ASBCS] = t;
+                       oprange[ASBCSW] = t;
+                       break;
+               case ANGC:      /* rn=REGZERO */
+                       oprange[ANGCW] = t;
+                       oprange[ANGCS] = t;
+                       oprange[ANGCSW] = t;
+                       break;
+               case ACMP:
+                       oprange[ACMPW] = t;
+                       oprange[ACMN] = t;
+                       oprange[ACMNW] = t;
+                       break;
+               case ATST:
+                       oprange[ATSTW] = t;
+                       break;
+               case AMVN:
+                       /* register/register, and shifted */
+                       oprange[AMVNW] = t;
+                       break;
+               case AMOVK:
+                       oprange[AMOVKW] = t;
+                       oprange[AMOVN] = t;
+                       oprange[AMOVNW] = t;
+                       oprange[AMOVZ] = t;
+                       oprange[AMOVZW] = t;
                        break;
                case ABEQ:
-                       oprange[ABNE] = oprange[r];
-                       oprange[ABGE] = oprange[r];
-                       oprange[ABLE] = oprange[r];
-                       oprange[ABGT] = oprange[r];
-                       oprange[ABLT] = oprange[r];
-                       break;
-               case AFBEQ:
-                       oprange[AFBNE] = oprange[r];
-                       oprange[AFBGE] = oprange[r];
-                       oprange[AFBLE] = oprange[r];
-                       oprange[AFBGT] = oprange[r];
-                       oprange[AFBLT] = oprange[r];
-                       break;
-               case AMOVQ:
-                       oprange[AMOVL] = oprange[r];
-                       oprange[AMOVLU] = oprange[r];
-                       oprange[AMOVQU] = oprange[r];
-                       oprange[AMOVA] = oprange[r];
-                       oprange[AMOVAH] = oprange[r];
-
-                       oprange[AMOVBU] = oprange[r];
-                       oprange[AMOVWU] = oprange[r];
-                       oprange[AMOVB] = oprange[r];
-                       oprange[AMOVW] = oprange[r];
-                       break;
-               case AMOVT:
-                       oprange[AMOVS] = oprange[r];
-                       break;
-               case AADDT:
-                       oprange[AADDS] = oprange[r];
-                       oprange[ACMPTEQ] = oprange[r];
-                       oprange[ACMPTGT] = oprange[r];
-                       oprange[ACMPTGE] = oprange[r];
-                       oprange[ACMPTUN] = oprange[r];
-                       oprange[ADIVS] = oprange[r];
-                       oprange[ADIVT] = oprange[r];
-                       oprange[AMULS] = oprange[r];
-                       oprange[AMULT] = oprange[r];
-                       oprange[ASUBS] = oprange[r];
-                       oprange[ASUBT] = oprange[r];
-                       oprange[ACPYS] = oprange[r];
-                       oprange[ACPYSN] = oprange[r];
-                       oprange[ACPYSE] = oprange[r];
-                       oprange[ACVTLQ] = oprange[r];
-                       oprange[ACVTQL] = oprange[r];
-                       oprange[AFCMOVEQ] = oprange[r];
-                       oprange[AFCMOVNE] = oprange[r];
-                       oprange[AFCMOVLT] = oprange[r];
-                       oprange[AFCMOVGE] = oprange[r];
-                       oprange[AFCMOVLE] = oprange[r];
-                       oprange[AFCMOVGT] = oprange[r];
-                       break;
-               case ACVTTQ:
-                       oprange[ACVTQT] = oprange[r];
-                       oprange[ACVTTS] = oprange[r];
-                       oprange[ACVTQS] = oprange[r];
-                       break;
-               case AJMP:
-               case AJSR:
-                       break;
-               case ACALL_PAL:
-                       break;
-               case AMOVQL:
-                       oprange[AMOVLL] = oprange[r];
-                       break;
-               case AMOVQC:
-                       oprange[AMOVLC] = oprange[r];
-                       break;
-               case AMOVQP:
-                       oprange[AMOVLP] = oprange[r];
-                       break;
-               case AREI:
-                       oprange[AMB] = oprange[r];
-                       oprange[ATRAPB] = oprange[r];
-                       break;
-               case AFETCH:
-                       oprange[AFETCHM] = oprange[r];
+                       oprange[ABNE] = t;
+                       oprange[ABCS] = t;
+                       oprange[ABHS] = t;
+                       oprange[ABCC] = t;
+                       oprange[ABLO] = t;
+                       oprange[ABMI] = t;
+                       oprange[ABPL] = t;
+                       oprange[ABVS] = t;
+                       oprange[ABVC] = t;
+                       oprange[ABHI] = t;
+                       oprange[ABLS] = t;
+                       oprange[ABGE] = t;
+                       oprange[ABLT] = t;
+                       oprange[ABGT] = t;
+                       oprange[ABLE] = t;
+                       break;
+               case ALSL:
+                       oprange[ALSLW] = t;
+                       oprange[ALSR] = t;
+                       oprange[ALSRW] = t;
+                       oprange[AASR] = t;
+                       oprange[AASRW] = t;
+                       oprange[AROR] = t;
+                       oprange[ARORW] = t;
+                       break;
+               case ACLS:
+                       oprange[ACLSW] = t;
+                       oprange[ACLZ] = t;
+                       oprange[ACLZW] = t;
+                       oprange[ARBIT] = t;
+                       oprange[ARBITW] = t;
+                       oprange[AREV] = t;
+                       oprange[AREVW] = t;
+                       oprange[AREV16] = t;
+                       oprange[AREV16W] = t;
+                       oprange[AREV32] = t;
+                       break;
+               case ASDIV:
+                       oprange[ASDIVW] = t;
+                       oprange[AUDIV] = t;
+                       oprange[AUDIVW] = t;
+                       oprange[ACRC32B] = t;
+                       oprange[ACRC32CB] = t;
+                       oprange[ACRC32CH] = t;
+                       oprange[ACRC32CW] = t;
+                       oprange[ACRC32CX] = t;
+                       oprange[ACRC32H] = t;
+                       oprange[ACRC32W] = t;
+                       oprange[ACRC32X] = t;
+                       break;
+               case AMADD:
+                       oprange[AMADDW] = t;
+                       oprange[AMSUB] = t;
+                       oprange[AMSUBW] = t;
+                       oprange[ASMADDL] = t;
+                       oprange[ASMSUBL] = t;
+                       oprange[AUMADDL] = t;
+                       oprange[AUMSUBL] = t;
+                       break;
+               case AREM:
+                       oprange[AREMW] = t;
+                       oprange[AUREM] = t;
+                       oprange[AUREMW] = t;
                        break;
+               case AMUL:
+                       oprange[AMULW] = t;
+                       oprange[AMNEG] = t;
+                       oprange[AMNEGW] = t;
+                       oprange[ASMNEGL] = t;
+                       oprange[ASMULL] = t;
+                       oprange[ASMULH] = t;
+                       oprange[AUMNEGL] = t;
+                       oprange[AUMULH] = t;
+                       oprange[AUMULL] = t;
+                       break;
+               case AMOVH:
+                       oprange[AMOVHU] = t;
+                       break;
+               case AMOVW:
+                       oprange[AMOVWU] = t;
+                       break;
+               case ABFM:
+                       oprange[ABFMW] = t;
+                       oprange[ASBFM] = t;
+                       oprange[ASBFMW] = t;
+                       oprange[AUBFM] = t;
+                       oprange[AUBFMW] = t;
+                       break;
+               case ABFI:
+                       oprange[ABFIW] = t;
+                       oprange[ABFXIL] = t;
+                       oprange[ABFXILW] = t;
+                       oprange[ASBFIZ] = t;
+                       oprange[ASBFIZW] = t;
+                       oprange[ASBFX] = t;
+                       oprange[ASBFXW] = t;
+                       oprange[AUBFIZ] = t;
+                       oprange[AUBFIZW] = t;
+                       oprange[AUBFX] = t;
+                       oprange[AUBFXW] = t;
+                       break;
+               case AEXTR:
+                       oprange[AEXTRW] = t;
+                       break;
+               case ASXTB:
+                       oprange[ASXTBW] = t;
+                       oprange[ASXTH] = t;
+                       oprange[ASXTHW] = t;
+                       oprange[ASXTW] = t;
+                       oprange[AUXTB] = t;
+                       oprange[AUXTH] = t;
+                       oprange[AUXTW] = t;
+                       oprange[AUXTBW] = t;
+                       oprange[AUXTHW] = t;
+                       break;
+               case ACCMN:
+                       oprange[ACCMNW] = t;
+                       oprange[ACCMP] = t;
+                       oprange[ACCMPW] = t;
+                       break;
+               case ACSEL:
+                       oprange[ACSELW] = t;
+                       oprange[ACSINC] = t;
+                       oprange[ACSINCW] = t;
+                       oprange[ACSINV] = t;
+                       oprange[ACSINVW] = t;
+                       oprange[ACSNEG] = t;
+                       oprange[ACSNEGW] = t;
+                       // aliases Rm=Rn, !cond
+                       oprange[ACINC] = t;
+                       oprange[ACINCW] = t;
+                       oprange[ACINV] = t;
+                       oprange[ACINVW] = t;
+                       oprange[ACNEG] = t;
+                       oprange[ACNEGW] = t;
+                       break;
+               case ACSET:
+                       // aliases, Rm=Rn=REGZERO, !cond
+                       oprange[ACSETW] = t;
+                       oprange[ACSETM] = t;
+                       oprange[ACSETMW] = t;
+                       break;
+               case AMOV:
+               case AMOVB:
+               case AMOVBU:
+               case AB:
+               case ABL:
                case AWORD:
+               case ADWORD:
+               case ARET:
                case ATEXT:
+               case ACASE:
+               case ABCASE:
+                       break;
+               case AERET:
+                       oprange[ANOP] = t;
+                       oprange[AWFE] = t;
+                       oprange[AWFI] = t;
+                       oprange[AYIELD] = t;
+                       oprange[ASEV] = t;
+                       oprange[ASEVL] = t;
+                       oprange[ADRPS] = t;
+                       break;
+               case ACBZ:
+                       oprange[ACBZW] = t;
+                       oprange[ACBNZ] = t;
+                       oprange[ACBNZW] = t;
+                       break;
+               case ATBZ:
+                       oprange[ATBNZ] = t;
+                       break;
+               case AADR:
+               case AADRP:
+                       break;
+               case ACLREX:
+                       break;
+               case ASVC:
+                       oprange[AHLT] = t;
+                       oprange[AHVC] = t;
+                       oprange[ASMC] = t;
+                       oprange[ABRK] = t;
+                       oprange[ADCPS1] = t;
+                       oprange[ADCPS2] = t;
+                       oprange[ADCPS3] = t;
+                       break;
+               case AFADDS:
+                       oprange[AFADDD] = t;
+                       oprange[AFSUBS] = t;
+                       oprange[AFSUBD] = t;
+                       oprange[AFMULS] = t;
+                       oprange[AFMULD] = t;
+                       oprange[AFNMULS] = t;
+                       oprange[AFNMULD] = t;
+                       oprange[AFDIVS] = t;
+                       oprange[AFMAXD] = t;
+                       oprange[AFMAXS] = t;
+                       oprange[AFMIND] = t;
+                       oprange[AFMINS] = t;
+                       oprange[AFMAXNMD] = t;
+                       oprange[AFMAXNMS] = t;
+                       oprange[AFMINNMD] = t;
+                       oprange[AFMINNMS] = t;
+                       oprange[AFDIVD] = t;
+                       break;
+               case AFCVTSD:
+                       oprange[AFCVTDS] = t;
+                       oprange[AFABSD] = t;
+                       oprange[AFABSS] = t;
+                       oprange[AFNEGD] = t;
+                       oprange[AFNEGS] = t;
+                       oprange[AFSQRTD] = t;
+                       oprange[AFSQRTS] = t;
+                       oprange[AFRINTNS] = t;
+                       oprange[AFRINTND] = t;
+                       oprange[AFRINTPS] = t;
+                       oprange[AFRINTPD] = t;
+                       oprange[AFRINTMS] = t;
+                       oprange[AFRINTMD] = t;
+                       oprange[AFRINTZS] = t;
+                       oprange[AFRINTZD] = t;
+                       oprange[AFRINTAS] = t;
+                       oprange[AFRINTAD] = t;
+                       oprange[AFRINTXS] = t;
+                       oprange[AFRINTXD] = t;
+                       oprange[AFRINTIS] = t;
+                       oprange[AFRINTID] = t;
+                       oprange[AFCVTDH] = t;
+                       oprange[AFCVTHS] = t;
+                       oprange[AFCVTHD] = t;
+                       oprange[AFCVTSH] = t;
+                       break;
+               case AFCMPS:
+                       oprange[AFCMPD] = t;
+                       oprange[AFCMPES] = t;
+                       oprange[AFCMPED] = t;
+                       break;
+               case AFCCMPS:
+                       oprange[AFCCMPD] = t;
+                       oprange[AFCCMPES] = t;
+                       oprange[AFCCMPED] = t;
+                       break;
+               case AFCSELD:
+                       oprange[AFCSELS] = t;
                        break;
-               }
-       }
-}
 
-void
-buildrep(int x, int as)
-{
-       Opcross *p;
-       Optab *e, *s, *o;
-       int a1, a2, a3, n;
+               case AFMOVS:
+               case AFMOVD:
+                       break;
 
-       if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
-               diag("assumptions fail in buildrep");
-               errorexit();
-       }
-       repop[as] = x;
-       p = (opcross + x);
-       s = oprange[as].start;
-       e = oprange[as].stop;
-       for(o=e-1; o>=s; o--) {
-               n = o-optab;
-               for(a2=0; a2<2; a2++) {
-                       if(a2) {
-                               if(o->a2 == C_NONE)
-                                       continue;
-                       } else
-                               if(o->a2 != C_NONE)
-                                       continue;
-                       for(a1=0; a1<32; a1++) {
-                               if(!xcmp[a1][o->a1])
-                                       continue;
-                               for(a3=0; a3<32; a3++)
-                                       if(xcmp[a3][o->a3])
-                                               (*p)[a1][a2][a3] = n;
-                       }
+               case AFCVTZSD:
+                       oprange[AFCVTZSDW] = t;
+                       oprange[AFCVTZSS] = t;
+                       oprange[AFCVTZSSW] = t;
+                       oprange[AFCVTZUD] = t;
+                       oprange[AFCVTZUDW] = t;
+                       oprange[AFCVTZUS] = t;
+                       oprange[AFCVTZUSW] = t;
+                       break;
+               case ASCVTFD:
+                       oprange[ASCVTFS] = t;
+                       oprange[ASCVTFWD] = t;
+                       oprange[ASCVTFWS] = t;
+                       oprange[AUCVTFD] = t;
+                       oprange[AUCVTFS] = t;
+                       oprange[AUCVTFWD] = t;
+                       oprange[AUCVTFWS] = t;
+                       break;
+
+               case ASYS:
+                       oprange[AAT] = t;
+                       oprange[ADC] = t;
+                       oprange[AIC] = t;
+                       oprange[ATLBI] = t;
+                       break;
+
+               case ASYSL:
+               case AHINT:
+                       break;
+
+               case ADMB:
+                       oprange[ADSB] = t;
+                       oprange[AISB] = t;
+                       break;
+
+               case AMRS:
+               case AMSR:
+                       break;
+
+               case ALDXR:
+                       oprange[ALDXRB] = t;
+                       oprange[ALDXRH] = t;
+                       oprange[ALDXRW] = t;
+                       break;
+               case ALDXP:
+                       oprange[ALDXPW] = t;
+                       break;
+               case ASTXR:
+                       oprange[ASTXRB] = t;
+                       oprange[ASTXRH] = t;
+                       oprange[ASTXRW] = t;
+                       break;
+               case ASTXP:
+                       oprange[ASTXPW] = t;
+                       break;
+
+               case AAESD:
+                       oprange[AAESE] = t;
+                       oprange[AAESMC] = t;
+                       oprange[AAESIMC] = t;
+                       oprange[ASHA1H] = t;
+                       oprange[ASHA1SU1] = t;
+                       oprange[ASHA256SU0] = t;
+                       break;
+
+               case ASHA1C:
+                       oprange[ASHA1P] = t;
+                       oprange[ASHA1M] = t;
+                       oprange[ASHA1SU0] = t;
+                       oprange[ASHA256H] = t;
+                       oprange[ASHA256H2] = t;
+                       oprange[ASHA256SU1] = t;
+                       break;
+
+               case AMOVP:
+                       oprange[AMOVPW] = t;
+                       oprange[AMOVPSW] = t;
+                       break;
                }
        }
-       oprange[as].start = 0;
 }