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

📄 tc-tic30.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
	  as_bad ("The %s operand doesn't match", ordinal_names[count]);	  return;	}    }  /* Now set the addressing mode for 3 operand instructions.  */  if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2))    {      /* Set the addressing mode to the values used for 2 operand instructions in the         G addressing field of the opcode.  */      char *p;      switch (insn.operand_type[0]->op_type)	{	case Rn:	case ARn:	case DPReg:	case OtherReg:	  if (insn.operand_type[1]->op_type & (AllReg))	    insn.addressing_mode = AM_Register;	  else if (insn.operand_type[1]->op_type & Indirect)	    insn.addressing_mode = AM_Direct;	  else	    {	      /* Shouldn't make it to this stage */	      as_bad ("Incompatible first and second operands in instruction");	      return;	    }	  break;	case Indirect:	  if (insn.operand_type[1]->op_type & (AllReg))	    insn.addressing_mode = AM_Indirect;	  else if (insn.operand_type[1]->op_type & Indirect)	    insn.addressing_mode = AM_Immediate;	  else	    {	      /* Shouldn't make it to this stage */	      as_bad ("Incompatible first and second operands in instruction");	      return;	    }	  break;	}      /* Now make up the opcode for the 3 operand instructions.  As in parallel         instructions, there will be no unresolved values, so they can be fully formed         and added to the frag table.  */      insn.opcode = insn.tm->base_opcode;      if (insn.operand_type[0]->op_type & Indirect)	{	  insn.opcode |= (insn.operand_type[0]->indirect.ARnum);	  insn.opcode |= (insn.operand_type[0]->indirect.mod << 3);	}      else	insn.opcode |= (insn.operand_type[0]->reg.opcode);      if (insn.operand_type[1]->op_type & Indirect)	{	  insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8);	  insn.opcode |= (insn.operand_type[1]->indirect.mod << 11);	}      else	insn.opcode |= (insn.operand_type[1]->reg.opcode << 8);      if (insn.operands == 3)	insn.opcode |= (insn.operand_type[2]->reg.opcode << 16);      insn.opcode |= insn.addressing_mode;      p = frag_more (INSN_SIZE);      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);    }  else    {				/* Not a three operand instruction */      char *p;      int am_insn = -1;      insn.opcode = insn.tm->base_opcode;      /* Create frag for instruction - all instructions are 4 bytes long.  */      p = frag_more (INSN_SIZE);      if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode))	{	  insn.opcode |= insn.addressing_mode;	  if (insn.addressing_mode == AM_Indirect)	    {	      /* Determine which operand gives the addressing mode */	      if (insn.operand_type[0]->op_type & Indirect)		am_insn = 0;	      if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect))		am_insn = 1;	      insn.opcode |= (insn.operand_type[am_insn]->indirect.disp);	      insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8);	      insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11);	      if (insn.operands > 1)		insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);	      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	    }	  else if (insn.addressing_mode == AM_Register)	    {	      insn.opcode |= (insn.operand_type[0]->reg.opcode);	      if (insn.operands > 1)		insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);	      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	    }	  else if (insn.addressing_mode == AM_Direct)	    {	      if (insn.operand_type[0]->op_type & Direct)		am_insn = 0;	      if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct))		am_insn = 1;	      if (insn.operands > 1)		insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);	      if (insn.operand_type[am_insn]->direct.resolved == 1)		{		  /* Resolved values can be placed straight into instruction word, and output */		  insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF);		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else		{		/* Unresolved direct addressing mode instruction */		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		  fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0);		}	    }	  else if (insn.addressing_mode == AM_Immediate)	    {	      if (insn.operand_type[0]->immediate.resolved == 1)		{		  char *keeploc;		  int size;		  if (insn.operands > 1)		    insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);		  switch (insn.tm->imm_arg_type)		    {		    case Imm_Float:		      debug ("Floating point first operand\n");		      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		      keeploc = input_line_pointer;		      input_line_pointer = insn.operand_type[0]->immediate.label;		      if (md_atof ('f', p + 2, &size) != 0)			{			  as_bad ("invalid short form floating point immediate operand");			  return;			}		      input_line_pointer = keeploc;		      break;		    case Imm_UInt:		      debug ("Unsigned int first operand\n");		      if (insn.operand_type[0]->immediate.decimal_found)			as_warn ("rounding down first operand float to unsigned int");		      if (insn.operand_type[0]->immediate.u_number > 0xFFFF)			as_warn ("only lower 16-bits of first operand are used");		      insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL);		      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		      break;		    case Imm_SInt:		      debug ("Int first operand\n");		      if (insn.operand_type[0]->immediate.decimal_found)			as_warn ("rounding down first operand float to signed int");		      if (insn.operand_type[0]->immediate.s_number < -32768 ||			  insn.operand_type[0]->immediate.s_number > 32767)			{			  as_bad ("first operand is too large for 16-bit signed int");			  return;			}		      insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL);		      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		      break;		    }		}	      else		{		/* Unresolved immediate label */		  if (insn.operands > 1)		    insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		  fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0);		}	    }	}      else if (insn.tm->opcode_modifier == PCRel)	{	  /* Conditional Branch and Call instructions */	  if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp))	    {	      if (insn.operand_type[0]->op_type & (AllReg))		{		  insn.opcode |= (insn.operand_type[0]->reg.opcode);		  insn.opcode |= PC_Register;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else		{		  insn.opcode |= PC_Relative;		  if (insn.operand_type[0]->immediate.resolved == 1)		    {		      insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF);		      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		    }		  else		    {		      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		      fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0);		    }		}	    }	  else if ((insn.tm->operand_types[0] & ARn) == ARn)	    {	      /* Decrement and Branch instructions */	      insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22);	      if (insn.operand_type[1]->op_type & (AllReg))		{		  insn.opcode |= (insn.operand_type[1]->reg.opcode);		  insn.opcode |= PC_Register;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else if (insn.operand_type[1]->immediate.resolved == 1)		{		  if (insn.operand_type[0]->immediate.decimal_found)		    {		      as_bad ("first operand is floating point");		      return;		    }		  if (insn.operand_type[0]->immediate.s_number < -32768 ||		      insn.operand_type[0]->immediate.s_number > 32767)		    {		      as_bad ("first operand is too large for 16-bit signed int");		      return;		    }		  insn.opcode |= (insn.operand_type[1]->immediate.s_number);		  insn.opcode |= PC_Relative;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else		{		  insn.opcode |= PC_Relative;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		  fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0);		}	    }	}      else if (insn.tm->operand_types[0] == IVector)	{	  /* Trap instructions */	  if (insn.operand_type[0]->op_type & IVector)	    insn.opcode |= (insn.operand_type[0]->immediate.u_number);	  else	    {			/* Shouldn't get here */	      as_bad ("interrupt vector for trap instruction out of range");	      return;	    }	  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	}      else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate)	{	  /* Push, Pop and Rotate instructions */	  insn.opcode |= (insn.operand_type[0]->reg.opcode << 16);	  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	}      else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct))	{	  /* LDP Instruction needs to be tested for before the next section */	  if (insn.operand_type[0]->op_type & Direct)	    {	      if (insn.operand_type[0]->direct.resolved == 1)		{		  /* Direct addressing uses lower 8 bits of direct address */		  insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else		{		  fixS *fix;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		  fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0);		  /* Ensure that the assembler doesn't complain about fitting a 24-bit		     address into 8 bits.  */		  fix->fx_no_overflow = 1;		}	    }	  else	    {	      if (insn.operand_type[0]->immediate.resolved == 1)		{		  /* Immediate addressing uses upper 8 bits of address */		  if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)		    {		      as_bad ("LDP instruction needs a 24-bit operand");		      return;		    }		  insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16);		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		}	      else		{		  fixS *fix;		  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);		  fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0);		  fix->fx_no_overflow = 1;		}	    }	}      else if (insn.tm->operand_types[0] & (Imm24))	{	  /* Unconditional Branch and Call instructions */	  if (insn.operand_type[0]->immediate.resolved == 1)	    {	      if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)		as_warn ("first operand is too large for a 24-bit displacement");	      insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF);	      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	    }	  else	    {	      md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	      fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0);	    }	}      else if (insn.tm->operand_types[0] & NotReq)	{	  /* Check for NOP instruction without arguments.  */	  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	}      else if (insn.tm->operands == 0)	{	  /* Check for instructions without operands.  */	  md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);	}    }  debug ("Addressing mode: %08X\n", insn.addressing_mode);  {    int i;    for (i = 0; i < insn.operands; i++)      {	if (insn.operand_type[i]->immediate.label)	  free (insn.operand_type[i]->immediate.label);	free (insn.operand_type[i]);      }  }  debug ("Final opcode: %08X\n", insn.opcode);  debug ("\n");}struct tic30_par_insn {  partemplate *tm;		/* Template of current parallel instruction */  int operands[2];		/* Number of given operands for each insn */  /* Type of operand given in instruction */  operand *operand_type[2][MAX_OPERANDS];  int swap_operands;		/* Whether to swap operands around.  */  unsigned p_field;		/* Value of p field in multiply add/sub instructions */  unsigned opcode;		/* Final opcode */};struct tic30_par_insn p_insn;inttic30_parallel_insn (char *token){  static partemplate *p_opcode;  char *current_posn = token;  char *token_start;  char save_char;  debug ("In tic30_parallel_insn with %s\n", token);  memset (&p_insn, '\0', sizeof (p_insn));  while (is_opcode_char (*current_posn))    current_posn++;  {				/* Find instruction */    save_char = *current_posn;    *current_posn = '\0';    p_opcode = (partemplate *) hash_find (parop_hash, token);    if (p_opcode)      {	debug ("Found instruction %s\n", p_opcode->name);	p_insn.tm = p_opcode;      }    else      {	char first_opcode[6] =	{0};	char second_opcode[6] =	{0};	int i;	int current_opcode = -1;	int char_ptr = 0;	for (i = 0; i < strlen (token); i++)	  {	    char ch = *(token + i);	    if (ch == '_' && current_opcode == -1)	      {		current_opcode = 0;		continue;	      }	    if (ch == '_' && current_opcode == 0)	      {		current_opcode = 1;		char_ptr = 0;		continue;	      }	    switch (current_opcode)	      {	      case 0:		first_opcode[char_ptr++] = ch;		break;	      case 1:		second_opcode[char_ptr++] = ch;		break;	      }	  }	debug ("first_opcode = %s\n", first_opcode);	debug ("second_opcode = %s\n", second_opcode);	sprintf (token, "q_%s_%s", second_opcode, first_opcode);	p_opcode = (partemplate *) hash_find (parop_hash, token);	if (p_opcode)	  {	    debug ("Found instruction %s\n", p_opcode->name);	    p_insn.tm = p_opcode;	    p_insn.swap_operands = 1;	  }	else	  return 0;      }    *current_posn = save_char;  }  {				/* Find operands */    int paren_not_balanced;    int expecting_operand = 0;    int found_separator = 0;    do      {	/* skip optional white space before operand */	while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)	  {	    if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR)	      {		as_bad ("Invalid character %s before %s operand",			output_invalid (*current_posn),			ordinal_names[insn.operands]);		return 1;	      }	    if (*current_posn == PARALLEL_SEPARATOR)	      found_separator = 1;	    current_posn++;	  }	token_start = current_posn;	/* after white space */	paren_not_balanced = 0;	while (paren_not_balanced || *current_posn != ',')	  {	    if (*current_posn == END_OF_INSN)	      {		if (paren_not_balanced)		  {		    as_bad ("Unbalanced parenthesis in %s operand.",			    ordinal_names[insn.operands]);		    return 1;		  }		else		  break;	/* we are done */	      }	    else if (*current_posn == PARALLEL_SEPARATOR)	      {		while (is_space_char (*(current_posn - 1)))		  current_posn--;		break;	      }	    else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))	      {		as_bad ("Invalid character %s in %s operand",			output_invalid (*current_posn),			ordinal_names[insn.operands]);		return 1;	      }	    if (*current_posn == '(')	      ++paren_not_balanced;	    if (*current_posn == ')')	      --paren_not_balanced;	    current_posn++;	  }	if (current_posn != token_start)

⌨️ 快捷键说明

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