Пример #1
0
static bool
doTermScan (lineNode **pl, const char *what)
{
  const char *operand, *op1start, *op2start;
  for (; *pl; *pl = (*pl)->next)
  {
    operand = nextToken((*pl)->line);
    if(! (op1start = nextToken(NULL)) )
      continue;

    if(EQUALS(operand, "ld")
                || EQUALS(operand, "mov")
                || EQUALS(operand, "clr"))
      return(EQUALS(op1start, what));

    if(EQUALS(op1start, what))
      return(FALSE);

    /*if(op2start && EQUALS(op2start, what)) TODO: enable this (but make op2start point somewhere first)
      return(FALSE);*/

    if(EQUALS(operand, "ret") || EQUALS(operand, "iret"))
      return(FALSE);

    /* TODO */
    if(ISINST(operand, "jp") || ISINST(operand, "jr"))
      return(FALSE);

    if(ISINST(operand, "call"))
      return(FALSE);
  }
  return(FALSE);
}
Пример #2
0
static int
instructionSize(char *inst, char *op1, char *op2)
{
  #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0)
  #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0')
  #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0')
  #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7')
  #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r')

  /* Based on the current (2003-08-22) code generation for the
     small library, the top instruction probability is:

       57% mov/movx/movc
        6% push
        6% pop
        4% inc
        4% lcall
        4% add
        3% clr
        2% subb
  */
  /* mov, push, & pop are the 69% of the cases. Check them first! */
  if (ISINST ("mov"))
    {
      if (*(inst+3)=='x') return 1; /* movx */
      if (*(inst+3)=='c') return 1; /* movc */
      if (IS_C (op1) || IS_C (op2)) return 2;
      if (IS_A (op1))
        {
          if (IS_Rn (op2) || IS_atRi (op2)) return 1;
          return 2;
        }
      if (IS_Rn(op1) || IS_atRi(op1))
        {
          if (IS_A(op2)) return 1;
          return 2;
        }
      if (strcmp (op1, "dptr") == 0) return 3;
      if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2;
      return 3;
    }

  if (ISINST ("push")) return 2;
  if (ISINST ("pop")) return 2;

  if (ISINST ("lcall")) return 3;
  if (ISINST ("ret")) return 1;
  if (ISINST ("ljmp")) return 3;
  if (ISINST ("sjmp")) return 2;
  if (ISINST ("rlc")) return 1;
  if (ISINST ("rrc")) return 1;
  if (ISINST ("rl")) return 1;
  if (ISINST ("rr")) return 1;
  if (ISINST ("swap")) return 1;
  if (ISINST ("jc")) return 2;
  if (ISINST ("jnc")) return 2;
  if (ISINST ("jb")) return 3;
  if (ISINST ("jnb")) return 3;
  if (ISINST ("jbc")) return 3;
  if (ISINST ("jmp")) return 1; // always jmp @a+dptr
  if (ISINST ("jz")) return 2;
  if (ISINST ("jnz")) return 2;
  if (ISINST ("cjne")) return 3;
  if (ISINST ("mul")) return 1;
  if (ISINST ("div")) return 1;
  if (ISINST ("da")) return 1;
  if (ISINST ("xchd")) return 1;
  if (ISINST ("reti")) return 1;
  if (ISINST ("nop")) return 1;
  if (ISINST ("acall")) return 2;
  if (ISINST ("ajmp")) return 2;


  if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch"))
    {
      if (IS_Rn(op2) || IS_atRi(op2)) return 1;
      return 2;
    }
  if (ISINST ("inc") || ISINST ("dec"))
    {
      if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1;
      if (strcmp(op1, "dptr") == 0) return 1;
      return 2;
    }
  if (ISINST ("anl") || ISINST ("orl") || ISINST ("xrl"))
    {
      if (IS_C(op1)) return 2;
      if (IS_A(op1))
        {
          if (IS_Rn(op2) || IS_atRi(op2)) return 1;
          return 2;
        }
      else
        {
          if (IS_A(op2)) return 2;
          return 3;
        }
    }
  if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl"))
    {
      if (IS_A(op1) || IS_C(op1)) return 1;
      return 2;
    }
  if (ISINST ("djnz"))
    {
      if (IS_Rn(op1)) return 2;
      return 3;
    }

  /* If the instruction is unrecognized, we shouldn't try to optimize. */
  /* Return a large value to discourage optimization.                  */
  return 999;
}
Пример #3
0
int
stm8instructionSize(const lineNode *pl)
{
  char *operand;
  char *op1start;
  char *op2start;
  int i = 0;
  operand = nextToken(pl->line);
  op1start = nextToken(NULL);
  op2start = nextToken(NULL);
  //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start);
  while(op2start && isspace(*op2start)) op2start++;
  //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start);

  /* arity=1 */
  if(EQUALS(operand, "clr")
                || EQUALS(operand, "dec")
                || EQUALS(operand, "inc")
                || EQUALS(operand, "push")
                || EQUALS(operand, "swap")
                || EQUALS(operand, "jp")
                || EQUALS(operand, "cpl")
                || EQUALS(operand, "tnz"))
  {
    if(!op1start)
      return(3);
    if(op1start[0] == 'a' || op1start[1] == 'x')
      return(1);
    if(op1start[1] == 'y')
      return(2);
    if(op1start[0] == '(')
      op1start++;
    if(strstr(op1start, ",y)"))
      i++; // costs extra byte for operating with y
    if(isLabel(op1start))
      return(3);
    if(readint(op1start) <= 0xFF)
      return(2+i);
    /* op1 > 0xFF */
    if(EQUALS(operand, "jp") && !strchr(op1start, 'y'))
      return(3);
    return(4);
  }
  if(EQUALS(operand, "exg"))
  {
    if(isReg(op2start))
      return(1);
    else
      return(3);
  }
  if(EQUALS(operand, "addw") || EQUALS(operand, "subw"))
  {
    if(isImmediate(op2start) && op1start[0] == 'y')
      return(4);
    if(isImmediate(op2start))
      return(3);
    if(isSpIndexed(op2start))
      return(3);
    if(isLongoff(op2start, "x"))
      return(4);
  }
  if(EQUALS(operand, "cplw"))
  {
    if(op1start[0] == 'y')
      return(2);
    else
      return(1);
  }
  if(EQUALS(operand, "ldf"))
  {
    if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y"))
      return(5);
    else
      return(4);
  }
  /* Operations that costs 2 or 3 bytes for immediate */
  if(ISINST(operand, "ld")
                || EQUALS(operand, "cp")
                || EQUALS(operand, "cpw")
                || ISINST(operand, "adc")
                || EQUALS(operand, "add")
                || ISINST(operand, "and")
                || ISINST(operand, "bcp")
                || ISINST(operand, "call")
                || ISINST(operand, "callr")
                || ISINST(operand, "jr")
                || ISINST(operand, "or")
                || ISINST(operand, "sbc")
                || EQUALS(operand, "sub")
                || ISINST(operand, "xor"))
  {
    char suffix;

    if(!op1start || !op2start)
      return(4);
    suffix = operand[strlen(operand)-1];
    if(suffix == 'w' && isImmediate(op2start))
      i++; // costs extra byte
    if(isSpIndexed(op1start) || isSpIndexed(op2start))
      return(2);
    if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)"))
      return(1);
    if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)"))
      return(2);
    if(isLabel(op1start) || isLabel(op2start))
      return(3+i);
    if(isShortoff(op1start, "x") || isShortoff(op2start, "x"))
      return(2);
    if(isShortoff(op1start, "y") || isShortoff(op2start, "y"))
      return(3);
    if(isLongoff(op1start, "x") || isLongoff(op2start, "x"))
      return(3);
    if(isRelativeAddr(op1start, "y"))
      return(4);
    if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw")))
      i++; // costs extra byte for operating with y
    if(isReg(op1start) && isReg(op2start))
      return(1+i);
    if(op2start[0] == '#')
      return(2+i); // ld reg, #immd
    if(readint(op2start) <= 0xFF)
      return(2+i);
    return(3+i);
  }

  /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */
  if(EQUALS(operand, "mov")) {
    if(op2start && op2start[0] == '#')
      return(4);
    if(op2start && isLabel(op2start))
      return(5);
    if(op2start && readint(op2start) <= 0xFF)
      return(3);
    if(op2start && readint(op2start) > 0xFF)
      return(5);
  }

  /* Operations that always costs 1 byte */
  if(EQUALS(operand, "ccf")
                || EQUALS(operand, "divw")
                || EQUALS(operand, "exgw")
                || EQUALS(operand, "iret")
                || EQUALS(operand, "nop")
                || EQUALS(operand, "rcf")
                || EQUALS(operand, "ret")
                || EQUALS(operand, "retf")
                || EQUALS(operand, "rvf")
                || EQUALS(operand, "scf"))
  {
    return(1);
  }
  /* Operations that costs 2 or 1 bytes depending on 
     is the Y or X register used */
  if(EQUALS(operand, "clrw")
                || EQUALS(operand, "decw")
                || EQUALS(operand, "div")
                || EQUALS(operand, "incw")
                || EQUALS(operand, "mul")
                || EQUALS(operand, "negw")
                || EQUALS(operand, "popw")
                || EQUALS(operand, "pushw")
                || EQUALS(operand, "rlcw")
                || EQUALS(operand, "rlwa")
                || EQUALS(operand, "rrcw")
                || EQUALS(operand, "rrwa")
                || EQUALS(operand, "sllw")
                || EQUALS(operand, "slaw")
                || EQUALS(operand, "sraw")
                || EQUALS(operand, "srlw")
                || EQUALS(operand, "swapw")
                || EQUALS(operand, "tnzw"))
  {
    if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y")))
      return(2);
    else
      return(1);
  }
  return(4);
}