⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tc-tic30.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
	  {			/* yes, we've read in another operand */	    p_insn.operands[found_separator]++;	    if (p_insn.operands[found_separator] > MAX_OPERANDS)	      {		as_bad ("Spurious operands; (%d operands/instruction max)",			MAX_OPERANDS);		return 1;	      }	    /* now parse operand adding info to 'insn' as we go along */	    save_char = *current_posn;	    *current_posn = '\0';	    p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] =	      tic30_operand (token_start);	    *current_posn = save_char;	    if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1])	      return 1;	  }	else	  {	    if (expecting_operand)	      {		as_bad ("Expecting operand after ','; got nothing");		return 1;	      }	    if (*current_posn == ',')	      {		as_bad ("Expecting operand before ','; got nothing");		return 1;	      }	  }	/* now *current_posn must be either ',' or END_OF_INSN */	if (*current_posn == ',')	  {	    if (*++current_posn == END_OF_INSN)	      {			/* just skip it, if it's \n complain */		as_bad ("Expecting operand after ','; got nothing");		return 1;	      }	    expecting_operand = 1;	  }      }    while (*current_posn != END_OF_INSN);	/* until we get end of insn */  }  if (p_insn.swap_operands)    {      int temp_num, i;      operand *temp_op;      temp_num = p_insn.operands[0];      p_insn.operands[0] = p_insn.operands[1];      p_insn.operands[1] = temp_num;      for (i = 0; i < MAX_OPERANDS; i++)	{	  temp_op = p_insn.operand_type[0][i];	  p_insn.operand_type[0][i] = p_insn.operand_type[1][i];	  p_insn.operand_type[1][i] = temp_op;	}    }  if (p_insn.operands[0] != p_insn.tm->operands_1)    {      as_bad ("incorrect number of operands given in the first instruction");      return 1;    }  if (p_insn.operands[1] != p_insn.tm->operands_2)    {      as_bad ("incorrect number of operands given in the second instruction");      return 1;    }  debug ("Number of operands in first insn: %d\n", p_insn.operands[0]);  debug ("Number of operands in second insn: %d\n", p_insn.operands[1]);  {				/* Now check if operands are correct */    int count;    int num_rn = 0;    int num_ind = 0;    for (count = 0; count < 2; count++)      {	int i;	for (i = 0; i < p_insn.operands[count]; i++)	  {	    if ((p_insn.operand_type[count][i]->op_type &		 p_insn.tm->operand_types[count][i]) == 0)	      {		as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1);		return 1;	      }	    /* Get number of R register and indirect reference contained within the first	       two operands of each instruction.  This is required for the multiply	       parallel instructions which require two R registers and two indirect	       references, but not in any particular place.  */	    if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2)	      num_rn++;	    else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2)	      num_ind++;	  }      }    if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn))      {	/* Check for the multiply instructions */	if (num_rn != 2)	  {	    as_bad ("incorrect format for multiply parallel instruction");	    return 1;	  }	if (num_ind != 2)	  {			/* Shouldn't get here */	    as_bad ("incorrect format for multiply parallel instruction");	    return 1;	  }	if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) &&	    (p_insn.operand_type[0][2]->reg.opcode != 0x01))	  {	    as_bad ("destination for multiply can only be R0 or R1");	    return 1;	  }	if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) &&	    (p_insn.operand_type[1][2]->reg.opcode != 0x03))	  {	    as_bad ("destination for add/subtract can only be R2 or R3");	    return 1;	  }	/* Now determine the P field for the instruction */	if (p_insn.operand_type[0][0]->op_type & Indirect)	  {	    if (p_insn.operand_type[0][1]->op_type & Indirect)	      p_insn.p_field = 0x00000000;	/* Ind * Ind, Rn  +/- Rn  */	    else if (p_insn.operand_type[1][0]->op_type & Indirect)	      p_insn.p_field = 0x01000000;	/* Ind * Rn,  Ind +/- Rn  */	    else	      p_insn.p_field = 0x03000000;	/* Ind * Rn,  Rn  +/- Ind */	  }	else	  {	    if (p_insn.operand_type[0][1]->op_type & Rn)	      p_insn.p_field = 0x02000000;	/* Rn  * Rn,  Ind +/- Ind */	    else if (p_insn.operand_type[1][0]->op_type & Indirect)	      {		operand *temp;		p_insn.p_field = 0x01000000;	/* Rn  * Ind, Ind +/- Rn  */		/* Need to swap the two multiply operands around so that everything is in		   its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */		temp = p_insn.operand_type[0][0];		p_insn.operand_type[0][0] = p_insn.operand_type[0][1];		p_insn.operand_type[0][1] = temp;	      }	    else	      {		operand *temp;		p_insn.p_field = 0x03000000;	/* Rn  * Ind, Rn  +/- Ind */		temp = p_insn.operand_type[0][0];		p_insn.operand_type[0][0] = p_insn.operand_type[0][1];		p_insn.operand_type[0][1] = temp;	      }	  }      }  }  debug ("P field: %08X\n", p_insn.p_field);  /* Finalise opcode.  This is easier for parallel instructions as they have to be     fully resolved, there are no memory addresses allowed, except through indirect     addressing, so there are no labels to resolve.  */  {    p_insn.opcode = p_insn.tm->base_opcode;    switch (p_insn.tm->oporder)      {      case OO_4op1:	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);	p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);	p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);	break;      case OO_4op2:	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);	p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);	p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);	p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19);	p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);	if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode)	  as_warn ("loading the same register in parallel operation");	break;      case OO_4op3:	p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);	p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);	p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);	p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22);	break;      case OO_5op1:	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);	p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);	p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);	p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);	p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);	break;      case OO_5op2:	p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);	p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);	p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);	p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);	p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);	p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);	break;      case OO_PField:	p_insn.opcode |= p_insn.p_field;	if (p_insn.operand_type[0][2]->reg.opcode == 0x01)	  p_insn.opcode |= 0x00800000;	if (p_insn.operand_type[1][2]->reg.opcode == 0x03)	  p_insn.opcode |= 0x00400000;	switch (p_insn.p_field)	  {	  case 0x00000000:	    p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);	    p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);	    p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);	    p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19);	    break;	  case 0x01000000:	    p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum);	    p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);	    p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);	    p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);	    break;	  case 0x02000000:	    p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);	    p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);	    p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);	    p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);	    p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16);	    p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);	    break;	  case 0x03000000:	    p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);	    p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);	    p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);	    p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);	    p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);	    break;	  }	break;      }  }				/* Opcode is finalised at this point for all parallel instructions.  */  {				/* Output opcode */    char *p;    p = frag_more (INSN_SIZE);    md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE);  }  {    int i, j;    for (i = 0; i < 2; i++)      for (j = 0; j < p_insn.operands[i]; j++)	free (p_insn.operand_type[i][j]);  }  debug ("Final opcode: %08X\n", p_insn.opcode);  debug ("\n");  return 1;}operand *tic30_operand (token)     char *token;{  int count;  char ind_buffer[strlen (token)];  operand *current_op;  debug ("In tic30_operand with %s\n", token);  current_op = (operand *) malloc (sizeof (operand));  memset (current_op, '\0', sizeof (operand));  if (*token == DIRECT_REFERENCE)    {      char *token_posn = token + 1;      int direct_label = 0;      debug ("Found direct reference\n");      while (*token_posn)	{	  if (!is_digit_char (*token_posn))	    direct_label = 1;	  token_posn++;	}      if (direct_label)	{	  char *save_input_line_pointer;	  segT retval;	  debug ("Direct reference is a label\n");	  current_op->direct.label = token + 1;	  save_input_line_pointer = input_line_pointer;	  input_line_pointer = token + 1;	  debug ("Current input_line_pointer: %s\n", input_line_pointer);	  retval = expression (&current_op->direct.direct_expr);	  debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op);	  debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number);	  debug ("Segment: %d\n", retval);	  input_line_pointer = save_input_line_pointer;	  if (current_op->direct.direct_expr.X_op == O_constant)	    {	      current_op->direct.address = current_op->direct.direct_expr.X_add_number;	      current_op->direct.resolved = 1;	    }	}      else	{	  debug ("Direct reference is a number\n");	  current_op->direct.address = atoi (token + 1);	  current_op->direct.resolved = 1;	}      current_op->op_type = Direct;    }  else if (*token == INDIRECT_REFERENCE)    {				/* Indirect reference operand */      int found_ar = 0;      int found_disp = 0;      int ar_number = -1;      int disp_number = 0;      int buffer_posn = 1;      ind_addr_type *ind_addr_op;      debug ("Found indirect reference\n");      ind_buffer[0] = *token;      for (count = 1; count < strlen (token); count++)	{			/* Strip operand */	  ind_buffer[buffer_posn] = tolower (*(token + count));	  if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') &&	      (*(token + count) == 'r' || *(token + count) == 'R'))	    {	      /* AR reference is found, so get its number and remove it from the buffer	         so it can pass through hash_find() */	      if (found_ar)		{		  as_bad ("More than one AR register found in indirect reference");		  return NULL;		}	      if (*(token + count + 1) < '0' || *(token + count + 1) > '7')		{		  as_bad ("Illegal AR register in indirect reference");		  return NULL;		}	      ar_number = *(token + count + 1) - '0';	      found_ar = 1;	      count++;	    }	  if (*(token + count) == '(')	    {	      /* Parenthesis found, so check if a displacement value is inside.  If so, get	         the value and remove it from the buffer.  */	      if (is_digit_char (*(token + count + 1)))		{		  char disp[10];		  int disp_posn = 0;		  if (found_disp)		    {		      as_bad ("More than one displacement found in indirect reference");		      return NULL;		    }		  count++;		  while (*(token + count) != ')')		    {		      if (!is_digit_char (*(token + count)))			{			  as_bad ("Invalid displacement in indirect reference");			  return NULL;			}		      disp[disp_posn++] = *(token + (count++));		    }		  disp[disp_posn] = '\0';		  disp_number = atoi (disp);		  count--;		  found_disp = 1;		}	    }	  buffer_posn++;	}      ind_buffer[buffer_posn] = '\0';      if (!found_ar)	{	  as_bad ("AR register not found in indirect reference");	  return NULL;	}      ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer);      if (ind_addr_op)	{	  debug ("Found indirect reference: %s\n", ind_addr_op->syntax);	  if (ind_addr_op->displacement == IMPLIED_DISP)	    {	      found_disp = 1;	      disp_number = 1;	    }	  else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp)	    {	      /* Maybe an implied displacement of 1 again */	      as_bad ("required displacement wasn't given in indirect reference");	      return 0;	    }	}      else	{	  as_bad ("illegal indirect reference");	  return NULL;	}      if (found_disp && (disp_number < 0 || disp_number > 255))	{	  as_bad ("displacement must be an unsigned 8-bit number");	  return NULL;	}      current_op->indirect.mod = ind_addr_op->modfield;      current_op->indirect.disp = disp_number;      current_op->indirect.ARnum = ar_number;      current_op->op_type = Indirect;    }  else    {      reg *regop = (reg *) hash_find (reg_hash, token);      if (regop)	{	  debug ("Found register operand: %s\n", regop->name);	  if (regop->regtype == REG_ARn)	    current_op->op_type = ARn;	  else if (regop->regtype == REG_Rn)	    current_op->op_type = Rn;	  else if (regop->regtype == REG_DP)	    current_op->op_type = DPReg;	  else	    current_op->op_type = OtherReg;	  current_op->reg.opcode = regop->opcode;	}      else	{	  if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h'))	    {	      char *save_input_line_pointer;	      segT retval;	      debug ("Probably a label: %s\n", token);	      current_op->immediate.label = (char *) malloc (strlen (token) + 1);	      strcpy (current_op->immediate.label, token);	      current_op->immediate.label[strlen (token)] = '\0';	      save_input_line_pointer = input_line_pointer;	      input_line_pointer = token;	      debug ("Current input_line_pointer: %s\n", input_line_pointer);	      retval = expression (&current_op->immediate.imm_expr);	      debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op);	      debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number);	      debug ("Segment: %d\n", retval);	      input_line_pointer = save_input_line_pointer;	      if (current_op->immediate.imm_expr.X_op == O_constant)		{		  current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number;		  current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number;		  current_op->immediate.resolved = 1;		}	    }	  else	    {	      unsigned count;	      debug ("Found a number or displacement\n");	      for (count = 0; count < strlen (token); count++)		if (*(token + count) == '.')		  current_op->immediate.decimal_found = 1;	      current_op->immediate.label = (char *) malloc (strlen (token) + 1);	      strcpy (current_op->immediate.label, token);	      current_op->immediate.label[strlen (token)] = '\0';	      current_op->immediate.f_number = (float) atof (token);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -