~lsof/antcc

50d9dfe5a55d0a3a2fd21dfb961d347be8a3a854 — lemon 9 months ago f453b31
misc bugfixs
4 files changed, 98 insertions(+), 29 deletions(-)

M amd64/emit.c
M amd64/isel.c
M elf.c
M regalloc.c
M amd64/emit.c => amd64/emit.c +90 -19
@@ 189,6 189,7 @@ enum operenc {
   EN_MI16,   /* mem, imm16 with /x */
   EN_MI32,   /* mem, imm32 with /x */
   EN_OI,     /* reg, imm32 with op + reg */
   EN_I8,     /* imm8 */
   EN_I32,    /* imm32 */
   EN_R32,    /* rel32 */
};


@@ 315,7 316,7 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
            objreloc(xcon2sym(mem.con), REL_ABS32S, Stext, *pcode - objout.textbegin, mem.disp);
         }
         I32(0);
         break;
         goto Imm;
      }
      if (mem.index == NOINDEX && mem.shift == 0) sib = 0;
      else sib = 1;


@@ 332,6 333,7 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
      else if (mod == 2 || (mod == 0 && mem.base == RBP/*RIP-rel*/)) {
         I32(mem.disp);
      }
   Imm:
      if (en->operenc == EN_MI8) B(src.imm);
      if (en->operenc == EN_MI16) I16(src.imm);
      if (en->operenc == EN_MI32) I32(src.imm);


@@ 353,6 355,11 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
      D(opc, nopc - 1);
      I32(src.imm);
      break;
   case EN_I8:
      if (rex) B(0x40 | rex);
      D(opc, nopc);
      B(src.imm);
      break;
   case EN_I32:
      if (rex) B(0x40 | rex);
      D(opc, nopc);


@@ 470,6 477,13 @@ DEFINSTR2(Xsubf,
   {4, PFPR, PMEM, "\xF3\x0F\x5C", EN_RM}, /* SUBSS xmm, m32 */
   {8, PFPR, PMEM, "\xF2\x0F\x5C", EN_RM}, /* SUBSD xmm, m64 */
)
DEFINSTR2(Xand,
   {4|8, PGPR, PGPR, "\x23", EN_RR},           /* AND r32/64, r32/64 */
   {4|8, PGPR, PI8,  "\x83", EN_RI8, .ext=4},  /* AND r32/64, imm8 */
   {4|8, PRAX, PI32, "\x25", EN_I32},          /* AND eax/rax, imm */
   {4|8, PGPR, PI32, "\x81", EN_RI32, .ext=4}, /* AND r32/64, imm */
   {  8, PGPR, PMEM, "\x23", EN_RM},           /* AND r64, m64 */
)
DEFINSTR2(Xxor,
   {4|8, PGPR, PGPR, "\x33", EN_RR},           /* XOR r32/64, r32/64 */
   {4|8, PGPR, PI8,  "\x83", EN_RI8, .ext=6},  /* XOR r32/64, imm8 */


@@ 493,6 507,9 @@ DEFINSTR1(Xinc,
DEFINSTR1(Xdec,
   {4|8, PGPR, 0, "\xFF", EN_R, .ext=1} /* DEC r32/64 */
)
DEFINSTR1(Xneg,
   {4|8, PGPR, 0, "\xF7", EN_R, .ext=3} /* NEG r32/64 */
)
DEFINSTR1(Xidiv,
   {4|8, PGPR, 0, "\xF7", EN_R, .ext=7}, /* IDIV r32/64 */
   {4|8, PMEM, 0, "\xF7", EN_M, .ext=7}, /* IDIV m32/64 */


@@ 510,8 527,42 @@ DEFINSTR2(Xcmp,
   {  8, PGPR, PMEM, "\x3B", EN_RM},           /* CMP r64, m64 */
)
DEFINSTR2(Xtest,
   {4|8, PGPR, PGPR, "\x85", EN_RR}, /* TEST r32/64, r32/64 */
   {4|8, PRAX, PI8,  "\xA8", EN_I8},  /* TEST AL, imm8 */
   {4,   PRAX, PI32, "\xA9", EN_I32}, /* TEST EAX, imm32 */
   {  8, PRAX, PU32, "\xA9", EN_I32}, /* TEST EAX, imm32 */
   {  8, PRAX, PI32, "\xA9", EN_I32}, /* TEST RAX, imm32 */
   {4|8, PGPR, PI8,  "\xF6", EN_RI8, .r8=1},  /* TEST r8, imm8 */
   {4|8, PGPR, PGPR, "\x85", EN_RR},   /* TEST r32/64, r32/64 */
   {4|8, PGPR, PMEM, "\x85", EN_RM},   /* TEST r32/64, m32/64 */
)

DEFINSTR2(Ximul2,
   {4|8, PGPR, PGPR, "\x0F\xAF", EN_RR}, /* MUL r32/64, r32/64 */
   {4|8, PGPR, PMEM, "\x0F\xAF", EN_RM}, /* MUL r32/64, m32/64 */
)
static void
Xmul(uchar **pcode, enum irclass k, struct oper dst, struct oper s1, struct oper s2)
{
   static const struct desc imm8tab[] = {
      {4|8, PGPR, PGPR, "\x6B", EN_RR}, /* MUL r32/64, r32/64, (imm8) */
      {4|8, PGPR, PMEM, "\x6B", EN_RM}, /* MUL r32/64, m32/64, (imm8) */
   }, imm32tab[] = {
      {4|8, PGPR, PGPR, "\x69", EN_RR}, /* MUL r32/64, r32/64, (imm32) */
      {4|8, PGPR, PMEM, "\x69", EN_RM}, /* MUL r32/64, m32/64, (imm32) */
   };
   if (!memcmp(&dst, &s1, sizeof dst) && s2.t != OIMM) {
      Ximul2(pcode, k, dst, s2);
      return;
   }
   assert(s2.t == OIMM);
   if ((uint)(s2.imm + 128) < 256) {
      encode(pcode, imm8tab, arraylength(imm8tab), k, dst, s1);
      B(s2.imm);
   } else {
      encode(pcode, imm32tab, arraylength(imm32tab), k, dst, s1);
      I32(s2.imm);
   }
}

enum cc {
   CCO   = 0x0, /* OF = 1*/


@@ 685,6 736,7 @@ static const uchar icmpop2cc[] = {
   [Oequ]  = CCE, [Oneq]  = CCNE,
   [Olth]  = CCL, [Ogth]  = CCG, [Olte]  = CCLE, [Ogte]  = CCGE,
   [Oulth] = CCB, [Ougth] = CCA, [Oulte] = CCBE, [Ougte] = CCGE,
   [Oand] = CCNE, [Osub] = CCNE,
};
/* condition code for TEST reg,reg (compare with zero) */
static const uchar icmpzero2cc[] = {


@@ 747,8 799,26 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
         Xlea(pcode, cls, dst, mem);
      }
      break;
   case Osub: X = kisint(cls) ? Xsub : Xsubf; goto ALU2;
   case Osub:
      dst = mkregoper(ins->l);
      if (kisflt(cls)) {
         Xsubf(pcode, cls, dst, mkimmdatregoper(ins->r));
      } else if (ins->reg-1 == dst.reg) { /* two-address */
         Xsub(pcode, cls, dst, mkimmdatregoper(ins->r));
      } else {
         assert(isintcon(ins->r));
         Xlea(pcode, cls, dst,
              mkoper(OMEM, .base = mkregoper(ins->l).reg, .index = NOINDEX, .disp = -intconval(ins->r)));
      }
      break;
   case Oshl: X = Xshl; goto ALU2;
   case Oand:
      if (!ins->reg) {
         Xtest(pcode, cls, mkregoper(ins->l), mkimmdatregoper(ins->r));
         break;
      }
      X = Xand;
      goto ALU2;
   case Oxor: X = Xxor; goto ALU2;
   ALU2:
      dst = mkregoper(ins->l);


@@ 757,11 827,17 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
      break;
   case Oxinc: X1 = Xinc; goto ALU1;
   case Oxdec: X1 = Xdec; goto ALU1;
   case Oneg: X1 = Xneg; goto ALU1;
   ALU1:
      dst = mkregoper(ins->l);
      assert(ins->reg-1 == dst.reg);
      X1(pcode, cls, dst);
      break;
   case Omul: 
      if (kisint(cls)) {
         Xmul(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r));
      } else assert(0);
      break;
   case Odiv:
      switch (cls) {
      default: assert(0);


@@ 837,22 913,17 @@ emitbranch(uchar **pcode, struct block *blk)
   if (blk->s2) {
      /* conditional branch.. */
      union ref arg = blk->jmp.arg[0];

      if (!arg.bits) /* implicit by ZF */
         cc = CCNZ;
      else {
         struct instr *ins;
         assert(arg.t == RTMP);
         ins = &instrtab[arg.i];
         assert(oiscmp(ins->op));
         /* TODO handle float cmps */
         if (ins->r.bits != ZEROREF.bits) {
            /* for CMP instr */
            cc = icmpop2cc[ins->op];
         } else {
            /* for TEST instr, which modifies ZF and SF and sets CF = OF = 0 */
            cc = icmpzero2cc[ins->op];
         }
      struct instr *ins;
      assert(arg.t == RTMP);
      ins = &instrtab[arg.i];
      assert(oiscmp(ins->op) || ins->op == Oand || ins->op == Osub);
      /* TODO handle float cmps */
      if (ins->r.bits != ZEROREF.bits) {
         /* for CMP instr */
         cc = icmpop2cc[ins->op];
      } else {
         /* for TEST instr, which modifies ZF and SF and sets CF = OF = 0 */
         cc = icmpzero2cc[ins->op];
      }
      if (blk->s1 == blk->lnext) {
         /* if s1 is next adjacent block, swap s1,s2 and flip condition to emit a

M amd64/isel.c => amd64/isel.c +2 -4
@@ 397,10 397,8 @@ seljmp(struct function *fn, struct block *blk)
         c = insertinstr(blk, blk->ins.n, mkinstr(Ocopy, cls, c));
         sel(fn, &instrtab[c.i], blk, &curi);
      }
      if (iflagsrc == c.i) {
         if (!oiscmp(instrtab[c.i].op)) {
            blk->jmp.arg[0] = NOREF; /* implicit by zero flag */
         }
      if (iflagsrc == c.i             /*           test                   cmp              */
       && (oiscmp(instrtab[c.i].op) || instrtab[c.i].op == Oand || instrtab[c.i].op == Osub)) {
         instrtab[c.i].keep = 1;
      } else {
         if (!(opflags[instrtab[c.i].op] & ZF) || c.i != blk->ins.p[blk->ins.n - 1]) {

M elf.c => elf.c +0 -1
@@ 449,7 449,6 @@ elffini(struct wbuf *out)
      putsym(out, sym);
   }


   /* rel.* */
   assert(relocs.n == ntextrel + nrodatarel + ndatarel);
   for (enum section s = Stext; s <= Sbss; ++s) {

M regalloc.c => regalloc.c +6 -5
@@ 416,8 416,8 @@ emitmove(enum irclass k, struct alloc dst, struct alloc src, struct block *blk, 
      case KF4: mv.op = Oloadf4; break;
      case KF8: mv.op = Oloadf8; break;
      }
      mv.l = mkref(RICON, dst.a*8);
      mv.reg = src.a;
      mv.l = mkref(RICON, src.a*8);
      mv.reg = dst.a+1;
      addstkslotref(insertinstr(blk, curi, mv));
   }
}


@@ 563,8 563,9 @@ resolve(struct function *fn, struct bbrm *bbrm, struct block *blk, struct block 
         }
         pmadd(insrescls(instrtab[var]), *alloc, *alloc2);
      }
      if (!instrtab[var].reg && alloc->t == AREG)
      if (!instrtab[var].reg && alloc->t == AREG) {
         instrtab[var].reg = alloc->a + 1;
      }
   }
   if (n) emitpm(n);



@@ 656,7 657,7 @@ regalloc(struct function *fn)
      for (int i = 0; i < 2; ++i) {
         if (!blk->jmp.arg[i].bits) break;
         /* do not allocate a reg for a cmp op used a branch argument, since it's a pseudo op */
         if (blk->jmp.t == Jb && blk->jmp.arg[i].t == RTMP && oiscmp(instrtab[blk->jmp.arg[i].i].op))
         if (blk->jmp.t == Jb && blk->jmp.arg[i].t == RTMP && instrtab[blk->jmp.arg[i].i].keep)
            break;
         use(&ra, blk, curi, -blk->jmp.t,
                  blk->jmp.t == Jret ? fn->abiret[i].reg : -1,


@@ 717,7 718,7 @@ regalloc(struct function *fn)
            goto Nop;
         } else if (ins->op == Ocopy && ins->l.t == RREG && ins->reg-1 == ins->l.i) {
            goto Nop;
         } else if (ins->inplace && ins->l.t == RREG && ins->reg-1 != ins->l.i) {
         } else if (ins->inplace && ins->l.t == RREG && ins->reg && ins->reg-1 != ins->l.i) {
            /* fixup in-place (two-address) instructions */
            allnops = 0;
            insertinstr(blk, i++, mkmove(ins->cls, ins->reg-1, ins->l.i));