コード例 #1
0
static int parse_unary(struct _asm_context *asm_context, int64_t *num, int operation)
{
  char token[TOKENLEN];
  int token_type;
  int64_t temp;
  struct _var var;

  var_set_int(&var, 0);

  token_type = tokens_get(asm_context, token, TOKENLEN);

//printf("parse_unary: %s token_type=%d(%d)\n", token, token_type, TOKEN_NUMBER);

  if (IS_TOKEN(token,'-'))
  {
    if (parse_unary(asm_context, &temp, OPER_MINUS) == -1) { return -1; }
  }
    else
  if (IS_TOKEN(token,'~'))
  {
    if (parse_unary(asm_context, &temp, OPER_NOT) != 0) { return -1; }
  }
    else
  if (token_type == TOKEN_NUMBER)
  {
    temp = atoll(token);
  }
    else
  if (IS_TOKEN(token, '('))
  {
    if (eval_expression_ex(asm_context, &var) != 0) { return -1; }
    if (var.type != VAR_INT)
    {
      print_error("Non-integer number in expression", asm_context);
      return -1;
    }

    temp = var_get_int64(&var);

    token_type = tokens_get(asm_context, token, TOKENLEN);
    if (IS_NOT_TOKEN(token,')'))
    {
      print_error_unexp(token, asm_context);
      return -1;
    }
  }
    else
  {
    print_error_unexp(token, asm_context);
    return -1;
  }

  if (operation == OPER_NOT) { *num = ~temp; }
  else if (operation == OPER_MINUS) { *num = -temp; }
  else { print_error_internal(NULL, __FILE__, __LINE__); return -1; }

  return 0;
}
コード例 #2
0
ファイル: ifdef_expression.c プロジェクト: zhevak/naken
static int get_operator(char *token, struct _operator *operator)
{
  if (IS_TOKEN(token,'>'))
  {
    operator->operation=OPER_GT;
    operator->precedence=PREC_EQUAL;
  }
    else
  if (IS_TOKEN(token,'<'))
  {
    operator->operation=OPER_LT;
    operator->precedence=PREC_EQUAL;
  }
    else
  if (strcmp(token,"==")==0)
  {
    operator->operation=OPER_EQUAL;
    operator->precedence=PREC_EQUAL;
  }
    else
  if (strcmp(token,">=")==0)
  {
    operator->operation=OPER_GT_EQUAL;
    operator->precedence=PREC_EQUAL;
  }
    else
  if (strcmp(token,"<=")==0)
  {
    operator->operation=OPER_LT_EQUAL;
    operator->precedence=PREC_EQUAL;
  }
    else
  if (strcmp(token,"||")==0)
  {
    operator->operation=OPER_OR;
    operator->precedence=PREC_OR;
  }
    else
  if (strcmp(token,"&&")==0)
  {
    operator->operation=OPER_AND;
    operator->precedence=PREC_AND;
  }
    else
  {
    printf("Internal Error: Unknown equals_type %s:%d\n", __FILE__, __LINE__);
    return -1;
  }

  return 0;
}
コード例 #3
0
ファイル: sip_parser.c プロジェクト: DastanIqbal/FreeSWITCH
/** Parse SIP version.
 *
 * Parse a SIP version string. Update the
 * pointer at @a ss to first non-LWS character after the version string.
 *
 * @param ss   string to be parsed [IN/OUT]
 * @param ver  value result for version [OUT]
 *
 * @retval 0 when successful,
 * @retval -1 upon an error.
 */
int sip_version_d(char **ss, char const **ver)
{
  char *s = *ss;
  char const *result;
  size_t const version_size = sizeof(sip_version_2_0) - 1;

  if (su_casenmatch(s, sip_version_2_0, version_size) &&
      !IS_TOKEN(s[version_size])) {
    result = sip_version_2_0;
    s += version_size;
  }
  else {
    /* Version consists of two tokens, separated by / */
    size_t l1 = 0, l2 = 0, n;

    result = s;

    l1 = span_token(s);
    for (n = l1; IS_LWS(s[n]); n++)
      {}
    if (s[n] == '/') {
      for (n++; IS_LWS(s[n]); n++)
        {}
      l2 = span_token(s + n);
      n += l2;
    }

    if (l1 == 0 || l2 == 0)
      return -1;

    /* If there is extra ws between tokens, compact version */
    if (n > l1 + 1 + l2) {
      s[l1] = '/';
      memmove(s + l1 + 1, s + n - l2, l2);
      s[l1 + 1 + l2] = 0;

      /* Compare again with compacted version */
      if (su_casematch(s, sip_version_2_0))
	result = sip_version_2_0;
    }

    s += n;
  }

  while (IS_WS(*s)) *s++ = '\0';

  *ss = s;

  if (ver)
    *ver = result;

  return 0;
}
コード例 #4
0
ファイル: lnParseMsg.c プロジェクト: mrpossoms/libNEMA
/*---------------------------------------------------------------------------*/
static int GGA(gpsState_t* state, char* msgData){
	int timeDone = 0;
	int qualityDone = 0;
	int HDOPDone = 0;
	int satellitesDone = 0;
	int altitudeDone = 0;
	int latDone = 0, lonDone = 0;

	START_PARSE()

	if(!timeDone){
		char  hour[3] = {0};
		char  min[3] = {0};
		char* sec;
		float seconds = 0;
		int minute, hr;

		memcpy(hour, token, 2);
		memcpy(min, token + 2, 2);
		sec = token + 4;

		sscanf(sec,  "%f", &seconds);
		sscanf(min,  "%d", &minute);
		sscanf(hour, "%d", &hr);

		state->Second = (unsigned char)seconds;
		state->Minute = (unsigned char)minute;
		state->Hour   = (unsigned char)hr;

		timeDone = 1;
	}
	else if(IS_TOKEN("N") || IS_TOKEN("S")){
		char* min = lastToken + 2;
		char  deg[3] = {0};
		float minutes = 0;

		memcpy(deg, lastToken, 2);
		sscanf(min, "%f", &minutes);
		sscanf(deg, "%f", &state->Lat);
#ifdef DEBUG
		printf("Token='%s' lastToken='%s'\n", token, lastToken);
#endif

		state->Lat += (MIN2DEG * minutes);

		// negate the coordinate if in southern hemisphere
		if(IS_TOKEN("S")){
			state->Lat *= -1;
		}

		latDone = 1;
	}
	else if(IS_TOKEN("W") || IS_TOKEN("E")){
		char* min = lastToken + 3;
		char  deg[4] = {0};
		float minutes = 0;

		memcpy(deg, lastToken, 3);
		sscanf(min, "%f", &minutes);
		sscanf(deg, "%f", &state->Lon);
#ifdef DEBUG
		printf("Token='%s' lastToken='%s'\n", token, lastToken);
#endif

		state->Lon += (MIN2DEG * minutes);

		// negate the coordinate if in the western hemisphere
		if(IS_TOKEN("W")){
			state->Lon *= -1;
		}

		lonDone = 1;
	}
	else if(!latDone || !lonDone){
		bzero(lastToken, 32);
		memcpy(lastToken, token, strlen(token));
		continue;
	}
	else if(!qualityDone){
		sscanf(token, "%d", &state->Fix);
		qualityDone = 1;
	}
	else if(!satellitesDone){
		int satillites;
		sscanf(token, "%d", &satillites);
		state->Satellites = satillites;
		satellitesDone = 1;
	}
	else if(!HDOPDone){
		sscanf(token, "%f", &state->HDOP);
		HDOPDone = 1;
	}
	else if(!altitudeDone){
		sscanf(token, "%f", &state->Altitude);
		altitudeDone = 1;
	}

	CONTINUE_PARSE()
	return 0;
}
コード例 #5
0
ファイル: assembler.c プロジェクト: trol73/naken_asm
int assemble(struct _asm_context *asm_context)
{
  char token[TOKENLEN];
  int token_type;

  while(1)
  {
    token_type = tokens_get(asm_context, token, TOKENLEN);
#ifdef DEBUG
    printf("%d: <%d> %s\n", asm_context->line, token_type, token);
#endif
    if (token_type == TOKEN_EOF) break;

    if (token_type == TOKEN_EOL)
    {
      if (asm_context->macros.stack_ptr == 0) { asm_context->line++; }
    }
      else
    if (token_type == TOKEN_LABEL)
    {
      int param_count_temp;
      if (macros_lookup(&asm_context->macros, token, &param_count_temp) != NULL)
      {
        print_already_defined(asm_context, token);
        return -1;
      }

      if (symbols_append(&asm_context->symbols, token, asm_context->address / asm_context->bytes_per_address) == -1)
      {
        return -1;
      }
    }
      else
    if (token_type == TOKEN_POUND || IS_TOKEN(token,'.'))
    {
      token_type = tokens_get(asm_context, token, TOKENLEN);
#ifdef DEBUG
    printf("%d: <%d> %s\n", asm_context->line, token_type, token);
#endif
      if (token_type == TOKEN_EOF) break;

      if (strcasecmp(token, "define") == 0)
      {
        if (macros_parse(asm_context, IS_DEFINE) != 0) return -1;
      }
        else
      if (strcasecmp(token, "ifdef") == 0)
      {
        parse_ifdef(asm_context, 0);
      }
        else
      if (strcasecmp(token, "ifndef") == 0)
      {
        parse_ifdef(asm_context, 1);
      }
        else
      if (strcasecmp(token, "if") == 0)
      {
        parse_if(asm_context);
      }
        else
      if (strcasecmp(token, "endif") == 0)
      {
        if (asm_context->ifdef_count < 1)
        {
          printf("Error: unmatched .endif at %s:%d\n", asm_context->filename, asm_context->ifdef_count);
          return -1;
        }
        return 0;
      }
        else
      if (strcasecmp(token, "else") == 0)
      {
        if (asm_context->ifdef_count < 1)
        {
          printf("Error: unmatched .else at %s:%d\n", asm_context->filename, asm_context->ifdef_count);
          return -1;
        }
        return 2;
      }
        else
      if (strcasecmp(token, "include") == 0)
      {
        if (parse_include(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "binfile") == 0)
      {
        if (parse_binfile(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "code") == 0)
      {
        asm_context->segment = SEGMENT_CODE;
      }
        else
      if (strcasecmp(token, "bss") == 0)
      {
        asm_context->segment = SEGMENT_BSS;
      }
        else
      if (strcasecmp(token, "msp430_cpu4") == 0)
      {
        asm_context->msp430_cpu4 = 1;
      }
        else
      if (strcasecmp(token, "macro") == 0)
      {
        if (macros_parse(asm_context, IS_MACRO) != 0) return -1;
      }
        else
      if (strcasecmp(token, "pragma") == 0)
      {
        if (parse_pragma(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "device") == 0)
      {
        if (parse_device(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "set") == 0)
      {
        if (parse_set(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "export") == 0)
      {
        if (parse_export(asm_context) != 0) return -1;
      }
        else
      if (strcasecmp(token, "equ") == 0 || strcasecmp(token, "def")==0)
      {
        if (parse_equ(asm_context) != 0) return -1;
      }
        else
      {
        int ret = check_for_directive(asm_context, token);
        if (ret == 2) break;
        if (ret == -1) return -1;
        if (ret != 1)
        {
          printf("Error: Unknown directive '%s' at %s:%d.\n", token, asm_context->filename, asm_context->line);
          return -1;
        }
      }
    }
      else
    if (token_type == TOKEN_STRING)
    {
      int ret = check_for_directive(asm_context, token);
      if (ret == 2) break;
      if (ret == -1) return -1;
      if (ret != 1) 
      {
        int start_address = asm_context->address;
        char token2[TOKENLEN];
        int token_type2;

        token_type2 = tokens_get(asm_context, token2, TOKENLEN);

        if (strcasecmp(token2, "equ") == 0)
        {
          //token_type2 = tokens_get(asm_context, token2, TOKENLEN);
          int ptr = 0;
          int ch = '\n';

          while(1)
          {
            ch = tokens_get_char(asm_context);
            if (ch == EOF || ch == '\n') break;
            if (ch == '*' && ptr > 0 && token2[ptr-1] == '/')
            {
              macros_strip_comment(asm_context);
              ptr--;
              continue;
            }

            token2[ptr++] = ch;
            if (ptr == TOKENLEN-1)
            {
              printf("Internal Error: token overflow at %s:%d.\n", __FILE__, __LINE__);
              return -1;
            }
          }
          token2[ptr] = 0;
          tokens_unget_char(asm_context, ch);
          macros_strip(token2);
          macros_append(asm_context, token, token2, 0);
        }
          else
        {
          tokens_push(asm_context, token2, token_type2);

          ret = asm_context->parse_instruction(asm_context, token);

          if (asm_context->pass == 2 &&
              asm_context->list != NULL &&
              asm_context->include_count == 0)
          {
            asm_context->list_output(asm_context, start_address);
            fprintf(asm_context->list, "\n");
          }

          if (ret < 0) return -1;

          if (asm_context->macros.stack_ptr == 0) { asm_context->line++; }
          asm_context->instruction_count++;

          if (asm_context->address > start_address)
          {
            asm_context->code_count += (asm_context->address - start_address);
          }
        }
      }
    }
      else
    {
      print_error_unexp(token, asm_context);
      return -1;
    }
  }

  if (asm_context->error == 1) { return -1; }

  return 0;
}
コード例 #6
0
ファイル: ifdef_expression.c プロジェクト: zhevak/naken
static int parse_ifdef_expression(struct _asm_context *asm_context, int *num, int paren_count, int precedence, int state)
{
char token[TOKENLEN];
struct _operator operator;
int token_type;
//int state=0;  // 0 = get next num to process
int not=0;
int n1=0;
int n;

  operator.operation=OPER_NONE;
  operator.precedence=precedence;
  n=*num;

  while(1)
  {
    token_type=get_token(asm_context, token, TOKENLEN);

#ifdef DEBUG
printf("debug> #if: %d) %s   n=%d paren_count=%d precedence=%d state=%d\n", token_type, token, n, paren_count, precedence, state);
#endif

    if (token_type==TOKEN_EOL || token_type==TOKEN_EOF)
    {
      pushback(asm_context, token, token_type);

      if (paren_count!=0)
      {
        print_error("Unbalanced parentheses.", asm_context);
        return -1;
      }

      if (state!=1)
      {
        print_error("Unexpected end of expression.", asm_context);
        return -1;
      }

      if (operator.operation!=OPER_NONE)
      {
        n=eval_operation(operator.operation,n1,n);
#ifdef DEBUG
printf("debug> #if eval_operation() @EOL  n=%d precedence=%d state=%d\n", n, precedence, state);
#endif
        if (n==-1) { return -1; }
      }

      *num=n;
      return 0;
    }

    if (state!=1)
    {
      if (state==2)
      {
        n1=n;
      }

      if (token_type==TOKEN_SYMBOL)
      {
        if (IS_TOKEN(token,'!'))
        {
          not^=1;
          continue;
        }
          else
        if (IS_TOKEN(token,'('))
        {
          if (parse_ifdef_expression(asm_context, &n, paren_count+1, PREC_OR, 0)==-1) return -1;
        }
          else
        if (IS_TOKEN(token,')'))
        {
          if (paren_count==0)
          {
            print_error_unexp(token, asm_context);
            return -1;
          }

          if (state!=1)
          {
            print_error("Unexpected end of expression.", asm_context);
            return -1;
          }

          if (operator.operation!=OPER_NONE)
          {
            n=eval_operation(operator.operation,n1,n);
#ifdef DEBUG
printf("debug> #if eval_operation() @paren  n=%d\n", n);
#endif
            if (n==-1) { return -1; }
          }

          *num=n;
          return 0;
        }
      }
        else
      if (token_type==TOKEN_STRING)
      {
        int param_count;
        char *value=defines_heap_lookup(&asm_context->defines_heap, token, &param_count);

        if (strcasecmp(token, "defined")==0)
        {
          n=parse_defined(asm_context);
#ifdef DEBUG
printf("debug> #if: parse_defined()=%d\n", n);
#endif
          if (n==-1) return -1;
        }
          else
        if (value!=NULL && param_count==0 && is_num(value))
        {
          n=atoi(value);
        }
          else
        {
          print_error_unexp(token, asm_context);
          return -1;
        }
      }
        else
      if (token_type==TOKEN_NUMBER)
      {
        n=atoi(token);
      }

      if (not==1)
      {
        if (n==0)
        { n=1; }
          else
        { n=0; }

        not=0;
      }

#if 0
      if (state==2)
      {
#ifdef DEBUG
printf("debug> #if eval_operation() n1=%d n=%d\n", n1, n);
#endif
        n=eval_operation(operator.operation,n1,n);
        state=0;
#ifdef DEBUG
printf("debug> #if eval_operation() n=%d operation=%d\n", n, operator.operation);
#endif
      }
#endif

      state=1;
      continue;
    }

    if (token_type==TOKEN_SYMBOL || token_type==TOKEN_EQUALITY)
    {
      struct _operator next_operator;

      if (get_operator(token, &next_operator)==-1)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

#ifdef DEBUG
printf("debug> #if get_operator() token=%s operation=%d precedence=%d\n", token, next_operator.operation, next_operator.precedence);
#endif

      if (next_operator.precedence>precedence)
      {
        pushback(asm_context, token, token_type);
        if (parse_ifdef_expression(asm_context, &n, paren_count, next_operator.precedence, 1)==-1) return -1;
      }
        else
      if (next_operator.precedence<precedence)
      {
        pushback(asm_context, token, token_type);
        return 0;
      }
        else
      {
        state=2;

        if (operator.operation!=OPER_NONE)
        {
          n=eval_operation(operator.operation,n1,n);
#ifdef DEBUG
printf("debug> #if eval_operation() @ state 2  n=%d\n", n);
#endif
          if (n==-1) { return -1; }
        }

        operator=next_operator;
      }

      continue;
    }

    print_error_unexp(token, asm_context);
    return -1;
  }

  return -1;
}
コード例 #7
0
static int eval_expression_go(struct _asm_context *asm_context, struct _var *var, struct _operator *last_operator)
{
  char token[TOKENLEN];
  int token_type;
  struct _var var_stack[3];
  int var_stack_ptr = 1;
  struct _operator operator;
  int last_token_was_op = -1;

#ifdef DEBUG
printf("Enter eval_expression_go,  var=%d/%f/%d\n", var_get_int32(var), var_get_float(var), var_get_type(var));
#endif

  memcpy(&operator, last_operator, sizeof(struct _operator));
  VAR_COPY(&var_stack[0], var);

  while(1)
  {
#ifdef DEBUG
printf("eval_expression> going to grab a token\n");
#endif
    token_type = tokens_get(asm_context, token, TOKENLEN);

#ifdef DEBUG
printf("eval_expression> token=%s   var_stack_ptr=%d\n", token, var_stack_ptr);
#endif

    // Issue 15: Return an error if a stack is full with noe operator.
    if (var_stack_ptr == 3 && operator.operation == OPER_UNSET)
    {
      return -1;
    }

    if (token_type == TOKEN_QUOTED)
    {
      if (token[0] == '\\')
      {
        int e = tokens_escape_char(asm_context, (unsigned char *)token);
        if (e == 0) return -1;
        if (token[e+1] != 0)
        {
          print_error("Quoted literal too long.", asm_context);
          return -1;
        }
        sprintf(token, "%d", token[e]);
      }
        else
      {
        if (token[1]!=0)
        {
          print_error("Quoted literal too long.", asm_context);
          return -1;
        }
        sprintf(token, "%d", token[0]);
      }

      token_type = TOKEN_NUMBER;
    }

    // Open and close parenthesis
    if (IS_TOKEN(token,'('))
    {
      if (last_token_was_op == 0 && operator.operation != OPER_UNSET)
      {
        operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
        var_stack_ptr--;
        operator.operation = OPER_UNSET;

        VAR_COPY(var, &var_stack[var_stack_ptr-1]);
        tokens_push(asm_context, token, token_type);
        return 0;
      }

      if (operator.operation == OPER_UNSET && var_stack_ptr == 2)
      {
        // This is probably the x(r12) case.. so this is actually okay
        VAR_COPY(var, &var_stack[var_stack_ptr-1]);
        tokens_push(asm_context, token, token_type);
        return 0;
      }

      struct _var paren_var;
      struct _operator paren_operator;

      paren_operator.precedence = PREC_UNSET;
      paren_operator.operation = OPER_UNSET;
      memset(&paren_var, 0, sizeof(struct _var));

      if (eval_expression_go(asm_context, &paren_var, &paren_operator) != 0)
      {
        return -1;
      }

      last_token_was_op = 0;

#ifdef DEBUG
printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&paren_var), var_get_type(&paren_var));
#endif

      VAR_COPY(&var_stack[var_stack_ptr++], &paren_var);

      token_type = tokens_get(asm_context, token, TOKENLEN);
      if (!(token[1] == 0 && token[0] == ')'))
      {
        print_error("No matching ')'", asm_context);
        return -1;
      }
      continue;
    }

    if (IS_TOKEN(token,')'))
    {
      tokens_push(asm_context, token, token_type);
      break;
    }

    // End of expression
    if (IS_TOKEN(token,',') || IS_TOKEN(token,']') || token_type == TOKEN_EOF ||
        IS_TOKEN(token,'.'))
    {
      tokens_push(asm_context, token, token_type);
      break;
    }

    if (token_type == TOKEN_EOL)
    {
      //asm_context->tokens.line++;
      tokens_push(asm_context, token, token_type);
      break;
    }

    // Read number
    if (token_type == TOKEN_NUMBER)
    {
      last_token_was_op = 0;

      if (var_stack_ptr == 3)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      var_set_int(&var_stack[var_stack_ptr++], atoll(token));
    }
      else
    if (token_type == TOKEN_FLOAT)
    {
      if (var_stack_ptr == 3)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      var_set_float(&var_stack[var_stack_ptr++], atof(token));
    }
      else
    if (token_type == TOKEN_SYMBOL)
    {
      last_token_was_op = 1;

      struct _operator operator_prev;
      memcpy(&operator_prev, &operator, sizeof(struct _operator));

      if (get_operator(token, &operator) == -1)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      // Issue 15: 2015-July-21 mkohn - If operator is ~ then reverse
      // the next number.
      if (operator.operation == OPER_NOT)
      {
        int64_t num;

        if (parse_unary(asm_context, &num, OPER_NOT) != 0) { return -1; }

        if (var_stack_ptr == 3)
        {
          print_error_unexp(token, asm_context);
          return -1;
        }

        var_set_int(&var_stack[var_stack_ptr++], num);
        memcpy(&operator, &operator_prev, sizeof(struct _operator));

        last_token_was_op = 0;

        continue;
      }

      // Stack pointer probably shouldn't be less than 2
      if (var_stack_ptr == 0)
      {
        printf("Error: Unexpected operator '%s' at %s:%d\n", token, asm_context->tokens.filename, asm_context->tokens.line);
        return -1;
      }

#ifdef DEBUG
printf("TOKEN %s: precedence %d %d\n", token, last_operator->precedence, operator.precedence);
#endif

      if (last_operator->precedence == PREC_UNSET)
      {
        memcpy(last_operator, &operator, sizeof(struct _operator));
      }
        else
      if (last_operator->precedence > operator.precedence)
      {
        if (eval_expression_go(asm_context, &var_stack[var_stack_ptr-1], &operator) == -1)
        {
          return -1;
        }
      }
        else
      {
        operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
        var_stack_ptr--;
        memcpy(last_operator, &operator, sizeof(struct _operator));
      }
    }
      else
    {
      if (asm_context->pass != 1)
      {
        print_error_unexp(token, asm_context);
      }
      return -1;
    }
  }

#ifdef DEBUG
printf("going to leave  operation=%d\n", last_operator->operation);
PRINT_STACK()
#endif

  if (last_operator->operation != OPER_UNSET)
  {
    operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator);
    var_stack_ptr--;
  }

  VAR_COPY(var, &var_stack[var_stack_ptr-1]);

  return 0;
}
コード例 #8
0
ファイル: mips.c プロジェクト: asteadman/naken_asm
int parse_instruction_mips(struct _asm_context *asm_context, char *instr)
{
struct _operand operands[3];
int operand_count = 0;
char token[TOKENLEN];
int token_type;
char instr_case[TOKENLEN];
int paren_flag;
int num,n,r;
int opcode;
#if 0
int n,cond,s=0;
int opcode=0;
#endif

  lower_copy(instr_case, instr);
  memset(operands, 0, sizeof(operands));

//printf("%s %s\n", instr_case, instr);

  while(1)
  {
    token_type = tokens_get(asm_context, token, TOKENLEN);
    if (token_type == TOKEN_EOL) { break; }
    //printf("token=%s token_type=%d\n", token, token_type);

    if (operand_count == 0 && IS_TOKEN(token,'.'))
    {
      strcat(instr_case, ".");
      strcat(instr, ".");
      token_type = tokens_get(asm_context, token, TOKENLEN);
      strcat(instr, token);
      n = 0;
      while(token[n] != 0) { token[n]=tolower(token[n]); n++; }
      strcat(instr_case, token);
      continue;
    }

    do
    {
      paren_flag = 0;

      if (IS_TOKEN(token,'('))
      {
        token_type = tokens_get(asm_context, token, TOKENLEN);
        paren_flag = 1;
      }

      num = get_register_mips(token, 't');
      if (num != -1)
      {
        operands[operand_count].value = num;
        operands[operand_count].type = OPERAND_TREG;
        if (paren_flag == 0) { break; }
      }
        else
      if (paren_flag == 0)
      {
        num = get_register_mips(token, 'f');
        if (num != -1)
        {
          operands[operand_count].value = num;
          operands[operand_count].type = OPERAND_FREG;
          break;
        }
      }

      if (paren_flag == 1)
      {
        token_type = tokens_get(asm_context, token, TOKENLEN);
        if (IS_NOT_TOKEN(token,')'))
        {
          print_error_unexp(token, asm_context);
          return -1;
        }

        operands[operand_count].reg2 = operands[operand_count].value;
        operands[operand_count].value = 0;
        operands[operand_count].type = OPERAND_IMMEDIATE_RS;;

        break;
      }

      operands[operand_count].type = OPERAND_IMMEDIATE;

      if (asm_context->pass == 1)
      {
        eat_operand(asm_context);
        break;
      }

      tokens_push(asm_context, token, token_type);
      if (eval_expression(asm_context, &num) != 0)
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      operands[operand_count].value = num;

      token_type = tokens_get(asm_context, token, TOKENLEN);
      if (IS_TOKEN(token,'('))
      {
        token_type = tokens_get(asm_context, token, TOKENLEN);
        num = get_register_mips(token, 't');
        if (num == -1)
        {
          print_error_unexp(token, asm_context);
          return -1;
        }

        operands[operand_count].reg2 = num;
        operands[operand_count].type = OPERAND_IMMEDIATE_RS;;

        token_type = tokens_get(asm_context, token, TOKENLEN);

        if (IS_NOT_TOKEN(token,')'))
        {
          print_error_unexp(token, asm_context);
          return -1;
        }
      }
        else
      {
        tokens_push(asm_context, token, token_type);
      }

    } while(0);

    operand_count++;

    token_type = tokens_get(asm_context, token, TOKENLEN);
    if (token_type == TOKEN_EOL) { break; }
    if (IS_NOT_TOKEN(token,','))
    {
      print_error_unexp(token, asm_context);
      return -1;
    }

    if (operand_count == 3)
    {
      print_error_unexp(token, asm_context);
      return -1;
    }
  }

  if (asm_context->pass == 1)
  {
    add_bin32(asm_context, 0, IS_OPCODE);
    return 4;
  }

  // Check pseudo-instructions
  if (strcmp(instr_case, "move") == 0 && operand_count == 2)
  {
    strcpy(instr_case, "add");
    operands[operand_count].value = 0;
    operands[operand_count].type = OPERAND_TREG;;
    operand_count++;
  }
    else
#if 0
  if (strcmp(instr_case, "li") == 0 && operand_count == 2)
  {
    strcpy(instr_case, "addi");
    memcpy(&operands[operand_count], &operands[operand_count-1], sizeof(struct _operand));
    operands[operand_count-1].value = 0;
    operands[operand_count-1].reg2 = 0;
    operands[operand_count-1].type = OPERAND_TREG;;
    operand_count++;
  }
    else
#endif
  if (strcmp(instr_case, "nop") == 0 && operand_count == 0)
  {
    strcpy(instr_case, "add");
    operand_count = 3;
  }
    else
  if (strcmp(instr_case, "neg") == 0 && operand_count == 1)
  {
    strcpy(instr_case, "subu");
    memcpy(&operands[1], &operands[0], sizeof(struct _operand));
    operand_count = 3;
  }

  // R-Type Instruction [ op 6, rs 5, rt 5, rd 5, sa 5, function 6 ]
  n = 0;
  while(mips_r_table[n].instr != NULL)
  {
    if (strcmp(instr_case, mips_r_table[n].instr) == 0)
    {
      char shift_table[] = { 0, 11, 21, 16, 6 };
      if (mips_r_table[n].operand_count != operand_count)
      {
        print_error_illegal_operands(instr, asm_context);
        return -1;
      }

      opcode = mips_r_table[n].function;

      for (r = 0; r < operand_count; r++)
      {
        if (operands[r].type != OPERAND_TREG)
        {
//printf("%s %s %s\n", instr_case, mips_r_table[n].instr, instr);
          printf("Error: '%s' expects registers at %s:%d\n", instr, asm_context->filename, asm_context->line);
          return -1;
        }
//printf("%s  %d<<%d\n", instr, operands[r].value, shift_table[(int)mips_r_table[n].operand[r]]);
        opcode |= operands[r].value << shift_table[(int)mips_r_table[n].operand[r]];
      }

      add_bin32(asm_context, opcode, IS_OPCODE);
      return 4;
    }
    n++;
  }

  // J-Type Instruction [ op 6, target 26 ]
  if (strcmp(instr_case, "ja") == 0 || strcmp(instr_case, "jal") == 0)
  {
    // FIXME - what to do with this
    //unsigned int upper = (address + 4) & 0xf0000000;
    if (operand_count != 1)
    {
      print_error_illegal_operands(instr, asm_context);
      return -1;
    }

    if (operands[0].type != OPERAND_IMMEDIATE)
    {
      printf("Error: Expecting address for '%s' at %s:%d\n", instr, asm_context->filename, asm_context->line);
      return -1;
    }

    if (instr_case[2] == 'l')  { opcode = 2 << 26; }
    else { opcode = 3 << 26; }

    add_bin32(asm_context, opcode | operands[0].value >> 2, IS_OPCODE);

    return 4;
  }

  // Coprocessor Instruction [ op 6, format 5, ft 5, fs 5, fd 5, funct 6 ]
  n = 0;
  while(mips_cop_table[n].instr != NULL)
  {
    if (strcmp(instr_case, mips_cop_table[n].instr) == 0)
    {
      char shift_table[] = { 0, 5, 11, 16 };
      if (mips_cop_table[n].operand_count != operand_count)
      {
        print_error_illegal_operands(instr, asm_context);
        return -1;
      }

      opcode = (0x11 << 26) | (mips_cop_table[n].format << 21) | mips_cop_table[n].function;

      for (r = 0; r < operand_count; r++)
      {
        if (operands[r].type != OPERAND_FREG)
        {
          printf("Error: '%s' expects registers at %s:%d\n", instr, asm_context->filename, asm_context->line);
          return -1;
        }
        opcode |= operands[r].value << shift_table[(int)mips_cop_table[n].operand[r]];
      }

      add_bin32(asm_context, opcode, IS_OPCODE);
      return 4;
    }
    n++;
  }

  // I-Type?  [ op 6, rs 5, rt 5, imm 16 ]
  n = 0;
  while(mips_i_table[n].instr != NULL)
  {
    if (strcmp(instr_case, mips_i_table[n].instr) == 0)
    {
      char shift_table[] = { 0, 0, 21, 16 };
      if (mips_i_table[n].operand_count != operand_count)
      {
        print_error_opcount(instr, asm_context);
        return -1;
      }

      opcode = mips_i_table[n].function << 26;

      for (r = 0; r < mips_i_table[n].operand_count; r++)
      {
        if ((mips_i_table[n].operand[r] == MIPS_OP_RT ||
            mips_i_table[n].operand[r] == MIPS_OP_RS) &&
            operands[r].type == OPERAND_TREG)
        {
          opcode |= operands[r].value << shift_table[(int)mips_i_table[n].operand[r]];
        }
          else
        if (mips_i_table[n].operand[r] == MIPS_OP_LABEL)
        {
          // FIXME - Calculate address
          //if (operands[r].value > 65535 || operands[r].value < -32768)
          //{
          //  print_error("Constant larger than 16 bit.", asm_context);
          //  return -1;
          //}
          opcode |= operands[r].value;
        }
          else
        if (mips_i_table[n].operand[r] == MIPS_OP_IMMEDIATE)
        {
          if (operands[r].value > 65535 || operands[r].value < -32768)
          {
            print_error("Constant larger than 16 bit.", asm_context);
            return -1;
          }
          opcode |= operands[r].value;
        }
          else
        if (mips_i_table[n].operand[r] == MIPS_OP_IMMEDIATE_RS)
        {
          if (operands[r].value > 65535 || operands[r].value < -32768)
          {
            print_error("Constant larger than 16 bit.", asm_context);
            return -1;
          }
          opcode |= operands[r].value;
          opcode |= operands[r].reg2 << 21;
        }
          else
        if (mips_i_table[n].operand[r] == MIPS_OP_RT_IS_0)
        {
          // Derr
        }
          else
        if (mips_i_table[n].operand[r] == MIPS_OP_RT_IS_1)
        {
          opcode |= 1 << 16;
        }
          else
        {
          print_error_illegal_operands(instr, asm_context);
          return -1;
        }
        opcode |= operands[r].value << shift_table[(int)mips_i_table[n].operand[r]];
      }

      add_bin32(asm_context, opcode, IS_OPCODE);
      return 4;
    }
    n++;
  }

  print_error_unknown_instr(instr, asm_context);

  return -1;
}
コード例 #9
0
ファイル: asm_65xx.c プロジェクト: atamariya/naken_asm
int parse_instruction_65xx(struct _asm_context *asm_context, char *instr)
{
  char token[TOKENLEN];
  char instr_case[TOKENLEN];
  char temp[80];
  int token_type;
  int opcode;
  int mode;
  int num;
  int index;
  int i;

  // make lower case
  lower_copy(instr_case, instr);

  // get instruction index
  index = -1;

  for(i = 0; i < 56; i++)
  {
    if(strcmp(instr_case, opcodes_65xx[i].name) == 0)
    {
      index = i;
      break;
    }
  }

  // no instruction found
  if(index == -1)
  {
    print_error_unexp(token, asm_context);
    return -1;
  }

  // default
  mode = MODE_IMPLIED;

  // begin parsing
  token_type=get_token(asm_context, token, TOKENLEN);
  if (token_type==TOKEN_EOL) { goto skip; }

  if(IS_TOKEN(token, '#'))
  {
    mode = MODE_IMMEDIATE;
    if(eval_expression(asm_context, &num) != 0)
    {
      if(asm_context->pass == 1)
      {
        eat_operand(asm_context);
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
    }

    num = (unsigned char)num;

    if(num < 0 || num > 0xFF)
      print_error_unexp(token, asm_context);
  }
    else
  if(IS_TOKEN(token, '('))
  {
    mode = MODE_INDIRECT;
    if(eval_expression(asm_context, &num) != 0)
    {
      if(asm_context->pass == 1)
      {
        eat_operand(asm_context);
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
    }

    token_type = get_token(asm_context, token, TOKENLEN);
    if (token_type==TOKEN_EOL) { goto skip; }
    if(IS_TOKEN(token, ','))
    {
      if(num < 0 || num > 0xFF)
      {
        print_error("X-Indexed Indirect value out of range", asm_context);
        return -1;
      }
      mode = MODE_X_INDEXED_INDIRECT;
      token_type = get_token(asm_context, token, TOKENLEN);
      if (token_type==TOKEN_EOL) { goto skip; }
      if(IS_NOT_TOKEN(token, 'x') && IS_NOT_TOKEN(token, 'X'))
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
      token_type = get_token(asm_context, token, TOKENLEN);
      if (token_type==TOKEN_EOL) { goto skip; }
      if(IS_NOT_TOKEN(token, ')'))
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
    }
      else
    if(IS_TOKEN(token, ')'))
    {
      mode = MODE_INDIRECT;
      token_type = get_token(asm_context, token, TOKENLEN);
      if (token_type==TOKEN_EOL) { goto skip; }
      if(IS_TOKEN(token, ','))
      {
        if(num < 0 || num > 0xFF)
        {
          print_error("Indirect Y-Indexed value out of range", asm_context);
          return -1;
        }
        mode = MODE_INDIRECT_Y_INDEXED;
        token_type = get_token(asm_context, token, TOKENLEN);
        if (token_type==TOKEN_EOL) { goto skip; }
        if(IS_NOT_TOKEN(token, 'y') && IS_NOT_TOKEN(token, 'Y'))
        {
          print_error_unexp(token, asm_context);
          return -1;
        }
        token_type = get_token(asm_context, token, TOKENLEN);
      }
    }
  }  
    else
  {
    pushback(asm_context, token, token_type);

    if(eval_expression(asm_context, &num) != 0)
    {
      if(asm_context->pass == 1)
      {
        eat_operand(asm_context);
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
    }

    // try zero page
    if((num >= 0x01 && num <= 0xFF)
        && opcodes_65xx[index].opcode[MODE_ZEROPAGE] != 0xFF)
    {
      mode = MODE_ZEROPAGE;
    }
      else
    {
      mode = MODE_ABSOLUTE;
    }

    token_type = get_token(asm_context, token, TOKENLEN);
    if (token_type==TOKEN_EOL) { goto skip; }

    if(IS_TOKEN(token, ','))
    {
      token_type = get_token(asm_context, token, TOKENLEN);
      if (token_type==TOKEN_EOL) { goto skip; }

      if(IS_TOKEN(token, 'x') || IS_TOKEN(token, 'X'))
      {
        if((num >= 0x00 && num <= 0xFF)
            && opcodes_65xx[index].opcode[MODE_ZEROPAGE_X_INDEXED] != 0xFF)
        {
          mode = MODE_ZEROPAGE_X_INDEXED;
        }
          else
        {
          mode = MODE_ABSOLUTE_X_INDEXED;
        }
      }
        else
      if(IS_TOKEN(token, 'y') || IS_TOKEN(token, 'Y'))
      {
        if((num >= 0x00 && num <= 0xFF)
            && opcodes_65xx[index].opcode[MODE_ZEROPAGE_Y_INDEXED] != 0xFF)
        {
          mode = MODE_ZEROPAGE_Y_INDEXED;
        }
          else
        {
          mode = MODE_ABSOLUTE_Y_INDEXED;
        }
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }
    }

    if(num < 0 || num > 0xFFFF)
    {
      print_error("Address out of range", asm_context);
      return -1;
    }
  }

skip:
  // branches are in table positions 3 - 10
  if(index >= 3 && index <= 10)
  {
    if(mode == MODE_IMMEDIATE)
    {
      mode = MODE_RELATIVE;
      num = (unsigned char)num;
    }
    else
    {
      mode = MODE_RELATIVE;
      if(asm_context->pass == 2)
      {
        // calculate branch offset, need to add 2 to current
        // address, since thats where the program counter would be
        num -= (asm_context->address + 2);
        if(num < -128 || num > 127)
        {
          print_error("Branch out of range", asm_context);
          return -1;
        }
        num = (unsigned char)num;
      }
    }
  }

  // see if theres an opcode for this instruction and mode
  opcode = opcodes_65xx[index].opcode[mode];

  if(asm_context->pass == 2 && opcode == 0xFF)
  {
    sprintf(temp, "No instruction found for addressing mode %d", mode);
    print_error(temp, asm_context);
    return -1;
  }

  // warn if indirect JMP bug will happen
  if((opcode == 0x6C) && ((num & 0xFF) == 0xFF))
  {
    print_error("Warning: Indirect JMP to upper page boundary (6502 bug)", asm_context);
  }

//printf("address=%04x, num=%04x\n", asm_context->address, num);

  // write opcode
//printf("%04x, %02x\n", asm_context->address, opcode & 0xFF);
  add_bin8(asm_context, opcode & 0xFF, IS_OPCODE);

  // write low byte first, if any
  if(mode_bytes[mode] > 1)
  {
//printf("%04x, %02x\n", asm_context->address, num & 0xFF);
    add_bin8(asm_context, num & 0xFF, IS_OPCODE);
  }

  // then high byte, if any
  if(mode_bytes[mode] > 2)
  {
//printf("%04x, %02x\n", asm_context->address, (num >> 8) & 0xFF);
    add_bin8(asm_context, (num >> 8) & 0xFF, IS_OPCODE);
  }
コード例 #10
0
ファイル: thumb.c プロジェクト: asteadman/naken_asm
int parse_instruction_thumb(struct _asm_context *asm_context, char *instr)
{
char token[TOKENLEN];
int token_type;
char instr_case[TOKENLEN];
struct _operand operands[3];
int operand_count=0;
int matched=0;
int num;
int n;

  lower_copy(instr_case, instr);

  memset(&operands, 0, sizeof(operands));
  while(1)
  {
    token_type=tokens_get(asm_context, token, TOKENLEN);
    if (token_type==TOKEN_EOL || token_type==TOKEN_EOF)
    {
      break;
    }

    if (operand_count>=3)
    {
      print_error_opcount(instr, asm_context);
      return -1;
    }

    if ((num=get_register_thumb(token))!=-1)
    {
      operands[operand_count].type=OPERAND_REGISTER;
      operands[operand_count].value=num;
      token_type=tokens_get(asm_context, token, TOKENLEN);
      if (IS_TOKEN(token,'!'))
      {
        operands[operand_count].type=OPERAND_REGISTER_INC;
      }
        else
      {
        tokens_push(asm_context, token, token_type);
      }
    }
      else
    if ((num=get_h_register_thumb(token))!=-1)
    {
      operands[operand_count].type=OPERAND_H_REGISTER;
      operands[operand_count].value=num;
    }
      else
    if (token_type==TOKEN_POUND)
    {
      if (eval_expression(asm_context, &num)!=0)
      {
        if (asm_context->pass==1)
        {
          eat_operand(asm_context);
        }
          else
        {
          print_error_illegal_expression(instr, asm_context);
          return -1;
        }
      }

      operands[operand_count].type=OPERAND_NUMBER;
      operands[operand_count].value=num;
    }
      else
    if (IS_TOKEN(token,'['))
    {
      token_type=tokens_get(asm_context, token, TOKENLEN);

      if (strcasecmp(token,"pc")==0 || strcasecmp(token,"r15")==0)
      {
        operands[operand_count].type=OPERAND_PC_AND_REG_IN_BRACKETS;
      }
        else
      if (strcasecmp(token,"sp")==0 || strcasecmp(token,"r13")==0)
      {
        operands[operand_count].type=OPERAND_SP_AND_REG_IN_BRACKETS;
      }
        else
      if ((num=get_register_thumb(token))!=-1)
      {
        operands[operand_count].type=OPERAND_TWO_REG_IN_BRACKETS;
        operands[operand_count].value=num;
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      if (expect_token_s(asm_context,",")!=0) { return -1; }

      token_type=tokens_get(asm_context, token, TOKENLEN);

      if ((num=get_register_thumb(token))!=-1)
      {
        operands[operand_count].second_value=num;
        if (operands[operand_count].type==OPERAND_PC_AND_NUM_IN_BRACKETS)
        {
          operands[operand_count].type=OPERAND_PC_AND_REG_IN_BRACKETS;
        }
      }
        else
      if (token_type==TOKEN_POUND)
      {
        if (eval_expression(asm_context, &num)!=0)
        {
          if (asm_context->pass==1)
          {
            eat_operand(asm_context);
          }
            else
          {
            print_error_illegal_expression(instr, asm_context);
            return -1;
          }
        }

        operands[operand_count].second_value=num;
        operands[operand_count].type++;
      }
        else
      {
        print_error_unexp(token, asm_context);
        return -1;
      }

      if (expect_token_s(asm_context,"]")!=0) { return -1; }
    }
      else
    if (IS_TOKEN(token,'{'))
    {
      operands[operand_count].type=OPERAND_REGISTER_LIST;
      if (read_register_list(asm_context, &operands[operand_count])==-1)
      {
        return -1;
      }
    }
      else
    {
      tokens_push(asm_context, token, token_type);

      if (eval_expression(asm_context, &num)!=0)
      {
        if (asm_context->pass==1)
        {
          eat_operand(asm_context);
        }
          else
        {
          print_error_illegal_expression(instr, asm_context);
          return -1;
        }
      }

      operands[operand_count].value=num;
      operands[operand_count].type=OPERAND_ADDRESS;
    }

    operand_count++;
    token_type=tokens_get(asm_context, token, TOKENLEN);
    if (token_type==TOKEN_EOL) break;
    if (IS_NOT_TOKEN(token,',') || operand_count==3)
    {
      print_error_unexp(token, asm_context);
      return -1;
    }
  }

  n=0;
  while(table_thumb[n].instr!=NULL)
  {
    if (strcmp(table_thumb[n].instr,instr_case)==0)
    {
      matched=1;

      switch(table_thumb[n].type)
      {
        case OP_SHIFT:
          if (operand_count==3 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REGISTER &&
              operands[2].type==OPERAND_NUMBER)
          {
            if (check_reg_lower(asm_context, operands[0].value)==-1) { return -1; }
            if (check_reg_lower(asm_context, operands[1].value)==-1) { return -1; }
            if (check_range(asm_context, "Offset", operands[2].value, 0, 31)==-1) { return -1; }
#if 0
            if (operands[2].value<0 || operands[2].value>31)
            {
              print_error_range("Offset", 0, 31, asm_context);
              return -1;
            }
#endif
            add_bin16(asm_context, table_thumb[n].opcode|(operands[2].value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_ADD_SUB:
          if (operand_count==3 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REGISTER &&
              operands[2].type==OPERAND_REGISTER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[2].value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
            else
          if (operand_count==3 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REGISTER &&
              operands[2].type==OPERAND_NUMBER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(1<<10)|(operands[2].value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_IMM:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_NUMBER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<8)|(operands[1].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_ALU:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REGISTER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_HI:
          if (operand_count==2)
          {
            if (operands[0].type==OPERAND_H_REGISTER &&
                operands[1].type==OPERAND_REGISTER)
            {
              add_bin16(asm_context, table_thumb[n].opcode|(1<<7)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
              return 2;
            }
              else
            if (operands[0].type==OPERAND_REGISTER &&
                operands[1].type==OPERAND_H_REGISTER)
            {
              add_bin16(asm_context, table_thumb[n].opcode|(1<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
              return 2;
            }
              else
            if (operands[0].type==OPERAND_H_REGISTER &&
                operands[1].type==OPERAND_H_REGISTER)
            {
              add_bin16(asm_context, table_thumb[n].opcode|(1<<7)|(1<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
              return 2;
            }
          }
          break;
        case OP_HI_BX:
          if (operand_count==1 &&
              operands[0].type==OPERAND_REGISTER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<3), IS_OPCODE);
            return 2;
          }
            else
          if (operand_count==1 &&
              operands[0].type==OPERAND_H_REGISTER)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(1<<6)|(operands[0].value<<3), IS_OPCODE);
            return 2;
          }
          break;
        case OP_PC_RELATIVE_LOAD:
          // REVIEW - Docs say this is a 10 bit, 4 byte aligned number
          // and it seems unsigned.  Why isn't this signed?
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_PC_AND_NUM_IN_BRACKETS)
          {
            if (check_range(asm_context, "Offset", operands[1].second_value, 0, 1020)==-1) { return -1; }
            if (is_4_byte_aligned(asm_context, operands[1].second_value)==-1) { return -1; }
#if 0
            if ((operands[1].second_value&0x3)!=0)
            {
              print_error("Offset not 4 byte aligned", asm_context);
              return -1;
            }
#endif
            add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<8)|(operands[1].second_value>>2), IS_OPCODE);
            return 2;
          }
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_ADDRESS)
          {
            // REVIEW: This looks so odd.  Docs say: The value of the PC will
            // be 4 bytes greater than the address of this instruction, but bit
            // 1 of the PC is forced to 0 to ensure it is word aligned.
            if (is_4_byte_aligned(asm_context, operands[1].value)==-1) { return -1; }
#if 0
            if ((operands[1].value&0x3)!=0)
            {
              print_error("Offset not 4 byte aligned", asm_context);
              return -1;
            }
#endif
            int offset=operands[1].value-((asm_context->address+4)&0xfffffffc);
            if (asm_context->pass==1) { offset=0; }
            if (check_range(asm_context, "Offset", offset, 0, 1020)==-1) { return -1; }
#if 0
            if (offset<0 || offset>1020)
            {
              print_error_range("Offset", 0, 1020, asm_context);
              return -1;
            }
#endif
            add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<8)|(offset>>2), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_TWO_REG_IN_BRACKETS)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[1].second_value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE_SIGN_EXT_HALF_WORD:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_TWO_REG_IN_BRACKETS)
          {
            add_bin16(asm_context, table_thumb[n].opcode|(operands[1].second_value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE_IMM_OFFSET_WORD:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REG_AND_NUM_IN_BRACKETS)
          {
            int offset=operands[1].second_value;
            if (check_range(asm_context, "Offset", offset, 0, 124)==-1) { return -1; }
            if (is_4_byte_aligned(asm_context, offset)==-1) { return -1; }
#if 0
            if ((offset&0x3)!=0)
            {
              print_error("Offset not 4 byte aligned", asm_context);
              return -1;
            }
#endif
            offset=offset>>2;
            add_bin16(asm_context, table_thumb[n].opcode|(offset<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE_IMM_OFFSET:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REG_AND_NUM_IN_BRACKETS)
          {
            if (check_range(asm_context, "Offset", operands[1].second_value, 0, 31)==-1) { return -1; }
            add_bin16(asm_context, table_thumb[n].opcode|(operands[1].second_value<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE_IMM_OFFSET_HALF_WORD:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_REG_AND_NUM_IN_BRACKETS)
          {
            int offset=operands[1].second_value;
            if (check_range(asm_context, "Offset", offset, 0, 60)==-1) { return -1; }
            if (is_2_byte_aligned(asm_context, offset)==-1) { return -1; }
#if 0
            if ((offset&0x1)!=0)
            {
              print_error("Offset not 2 byte aligned", asm_context);
              return -1;
            }
#endif
            offset=offset>>1;
            add_bin16(asm_context, table_thumb[n].opcode|(offset<<6)|(operands[1].value<<3)|(operands[0].value), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_STORE_SP_RELATIVE:
          if (operand_count==2 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_SP_AND_NUM_IN_BRACKETS)
          {
            if (check_range(asm_context, "Offset", operands[1].value, 0, 1020)==-1) { return -1; }
            if (is_4_byte_aligned(asm_context, operands[1].value)==-1) { return -1; }
            add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<8)|(operands[1].second_value>>2), IS_OPCODE);
            return 2;
          }
          break;
        case OP_LOAD_ADDRESS:
          if (operand_count==3 &&
              operands[0].type==OPERAND_REGISTER &&
              operands[1].type==OPERAND_H_REGISTER &&
              operands[2].type==OPERAND_NUMBER)
          {
            if (check_range(asm_context, "Offset", operands[2].value, 0, 1020)==-1) { return -1; }
            if (is_4_byte_aligned(asm_context, operands[2].value)==-1) { return -1; }
            if (operands[1].value==7)
            {
              add_bin16(asm_context, table_thumb[n].opcode|(operands[0].value<<8)|(operands[2].value>>2), IS_OPCODE);
              return 2;
            }
              else
            if (operands[1].value==5)
コード例 #11
0
ファイル: thumb.c プロジェクト: asteadman/naken_asm
static int read_register_list(struct _asm_context *asm_context, struct _operand *operand)
{
int token_type;
char token[TOKENLEN];
int reg_start,reg_end;

  while(1)
  {
    tokens_get(asm_context, token, TOKENLEN);

    if ((strcasecmp(token,"lr")==0 || strcasecmp(token,"r14")==0) &&
        operand->second_value==0)
    {
      operand->second_value=1;
    }
      else
    if ((strcasecmp(token,"pc")==0 || strcasecmp(token,"r15")==0) &&
        operand->second_value==0)
    {
      operand->second_value=2;
    }
      else
    if ((reg_start=get_register_thumb(token))!=-1)
    {
      token_type=tokens_get(asm_context, token, TOKENLEN);

      if (IS_TOKEN(token,'-'))
      {
        tokens_get(asm_context, token, TOKENLEN);
        if ((reg_end=get_register_thumb(token))==-1 || reg_end<reg_start)
        {
          print_error_unexp(token, asm_context);
          return -1;
        }

        while(reg_start<=reg_end)
        {
          operand->value|=1<<reg_start;
          reg_start++;
        }
      }
        else
      {
        operand->value|=1<<reg_start;
        tokens_push(asm_context, token, token_type);
      }
    }
      else
    {
      print_error_unexp(token, asm_context);
      return -1;
    }

    tokens_get(asm_context, token, TOKENLEN);
    if (IS_TOKEN(token,'}'))
    {
      break;
    }
      else
    if (IS_NOT_TOKEN(token,','))
    {
      print_error_unexp(token, asm_context);
      return -1;
    }
  }

  return 0;
}