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

📄 tc-d10v.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 3 页
字号:
/* tc-d10v.c -- Assembler code for the Mitsubishi D10V   Copyright 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.   This file is part of GAS, the GNU Assembler.   GAS is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   GAS is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with GAS; see the file COPYING.  If not, write to   the Free Software Foundation, 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  */#include <stdio.h>#include <ctype.h>#include "as.h"#include "subsegs.h"#include "opcode/d10v.h"#include "elf/ppc.h"//#include "read.h"const char comment_chars[] = ";";const char line_comment_chars[] = "#";const char line_separator_chars[] = "";const char *md_shortopts = "O";const char EXP_CHARS[] = "eE";const char FLT_CHARS[] = "dD";int Optimizing = 0;#define AT_WORD_P(X) ((X)->X_op == O_right_shift \		      && (X)->X_op_symbol != NULL \		      && symbol_constant_p ((X)->X_op_symbol) \		      && S_GET_VALUE ((X)->X_op_symbol) == AT_WORD_RIGHT_SHIFT)#define AT_WORD_RIGHT_SHIFT 2/* Fixups.  */#define MAX_INSN_FIXUPS (5)struct d10v_fixup{  expressionS exp;  int operand;  int pcrel;  int size;  bfd_reloc_code_real_type reloc;};typedef struct _fixups{  int fc;  struct d10v_fixup fix[MAX_INSN_FIXUPS];  struct _fixups *next;} Fixups;static Fixups FixUps[2];static Fixups *fixups;static int do_not_ignore_hash = 0;typedef int packing_type;#define PACK_UNSPEC 	(0)	/* Packing order not specified.  */#define PACK_PARALLEL	(1)	/* "||"  */#define PACK_LEFT_RIGHT (2)	/* "->"  */#define PACK_RIGHT_LEFT (3)	/* "<-"  */static packing_type etype = PACK_UNSPEC; /* Used by d10v_cleanup.  *//* True if instruction swapping warnings should be inhibited.   --nowarnswap.  */static boolean flag_warn_suppress_instructionswap;/* True if instruction packing should be performed when --gstabs is specified.   --gstabs-packing, --no-gstabs-packing.  */static boolean flag_allow_gstabs_packing = 1;/* Local functions.  */static int reg_name_search PARAMS ((char *name));static int register_name PARAMS ((expressionS *expressionP));static int check_range PARAMS ((unsigned long num, int bits, int flags));static int postfix PARAMS ((char *p));static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));static int get_operands PARAMS ((expressionS exp[]));static struct d10v_opcode *find_opcode PARAMS ((struct d10v_opcode *opcode, expressionS ops[]));static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn));static void write_long PARAMS ((unsigned long insn, Fixups *fx));static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,				  struct d10v_opcode *opcode2, unsigned long insn2, packing_type exec_type, Fixups *fx));static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type,						   offsetT value, int left, fixS *fix));static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,				struct d10v_opcode *opcode2, unsigned long insn2,				packing_type exec_type));static symbolS * find_symbol_matching_register PARAMS ((expressionS *));struct option md_longopts[] ={#define OPTION_NOWARNSWAP (OPTION_MD_BASE)  {"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},#define OPTION_GSTABSPACKING (OPTION_MD_BASE + 1)  {"gstabspacking",  no_argument, NULL, OPTION_GSTABSPACKING},  {"gstabs-packing", no_argument, NULL, OPTION_GSTABSPACKING},#define OPTION_NOGSTABSPACKING (OPTION_MD_BASE + 2)  {"nogstabspacking",   no_argument, NULL, OPTION_NOGSTABSPACKING},  {"no-gstabs-packing", no_argument, NULL, OPTION_NOGSTABSPACKING},  {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);static void d10v_dot_word PARAMS ((int));/* The target specific pseudo-ops which we support.  */const pseudo_typeS md_pseudo_table[] ={  { "word",	d10v_dot_word,	2 },  { NULL,       NULL,           0 }};/* Opcode hash table.  */static struct hash_control *d10v_hash;/* Do a binary search of the d10v_predefined_registers array to see if   NAME is a valid regiter name.  Return the register number from the   array on success, or -1 on failure.  */static intreg_name_search (name)     char *name;{  int middle, low, high;  int cmp;  low = 0;  high = d10v_reg_name_cnt () - 1;  do    {      middle = (low + high) / 2;      cmp = strcasecmp (name, d10v_predefined_registers[middle].name);      if (cmp < 0)	high = middle - 1;      else if (cmp > 0)	low = middle + 1;      else	return d10v_predefined_registers[middle].value;    }  while (low <= high);  return -1;}/* Check the string at input_line_pointer   to see if it is a valid register name.  */static intregister_name (expressionP)     expressionS *expressionP;{  int reg_number;  char c, *p = input_line_pointer;  while (*p	 && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != ')')    p++;  c = *p;  if (c)    *p++ = 0;  /* Look to see if it's in the register table.  */  reg_number = reg_name_search (input_line_pointer);  if (reg_number >= 0)    {      expressionP->X_op = O_register;      /* Temporarily store a pointer to the string here.  */      expressionP->X_op_symbol = (symbolS *) input_line_pointer;      expressionP->X_add_number = reg_number;      input_line_pointer = p;      return 1;    }  if (c)    *(p - 1) = c;  return 0;}static intcheck_range (num, bits, flags)     unsigned long num;     int bits;     int flags;{  long min, max;  int retval = 0;  /* Don't bother checking 16-bit values.  */  if (bits == 16)    return 0;  if (flags & OPERAND_SHIFT)    {      /* All special shift operands are unsigned and <= 16.	 We allow 0 for now.  */      if (num > 16)	return 1;      else	return 0;    }  if (flags & OPERAND_SIGNED)    {      /* Signed 3-bit integers are restricted to the (-2, 3) range.  */      if (flags & RESTRICTED_NUM3)	{	  if ((long) num < -2 || (long) num > 3)	    retval = 1;	}      else	{	  max = (1 << (bits - 1)) - 1;	  min = - (1 << (bits - 1));	  if (((long) num > max) || ((long) num < min))	    retval = 1;	}    }  else    {      max = (1 << bits) - 1;      min = 0;      if (((long) num > max) || ((long) num < min))	retval = 1;    }  return retval;}voidmd_show_usage (stream)     FILE *stream;{  fprintf (stream, _("D10V options:\n\-O                      Optimize.  Will do some operations in parallel.\n\--gstabs-packing        Pack adjacent short instructions together even\n\                        when --gstabs is specified.  On by default.\n\--no-gstabs-packing     If --gstabs is specified, do not pack adjacent\n\                        instructions together.\n"));}intmd_parse_option (c, arg)     int c;     char *arg ATTRIBUTE_UNUSED;{  switch (c)    {    case 'O':      /* Optimize. Will attempt to parallelize operations.  */      Optimizing = 1;      break;    case OPTION_NOWARNSWAP:      flag_warn_suppress_instructionswap = 1;      break;    case OPTION_GSTABSPACKING:      flag_allow_gstabs_packing = 1;      break;    case OPTION_NOGSTABSPACKING:      flag_allow_gstabs_packing = 0;      break;    default:      return 0;    }  return 1;}symbolS *md_undefined_symbol (name)     char *name ATTRIBUTE_UNUSED;{  return 0;}/* Turn a string in input_line_pointer into a floating point constant   of type TYPE, and store the appropriate bytes in *LITP.  The number   of LITTLENUMS emitted is stored in *SIZEP.  An error message is   returned, or NULL on OK.  */char *md_atof (type, litP, sizeP)     int type;     char *litP;     int *sizeP;{  int prec;  LITTLENUM_TYPE words[4];  char *t;  int i;  switch (type)    {    case 'f':      prec = 2;      break;    case 'd':      prec = 4;      break;    default:      *sizeP = 0;      return _("bad call to md_atof");    }  t = atof_ieee (input_line_pointer, type, words);  if (t)    input_line_pointer = t;  *sizeP = prec * 2;  for (i = 0; i < prec; i++)    {      md_number_to_chars (litP, (valueT) words[i], 2);      litP += 2;    }  return NULL;}voidmd_convert_frag (abfd, sec, fragP)     bfd *abfd ATTRIBUTE_UNUSED;     asection *sec ATTRIBUTE_UNUSED;     fragS *fragP ATTRIBUTE_UNUSED;{  abort ();}valueTmd_section_align (seg, addr)     asection *seg;     valueT addr;{  int align = bfd_get_section_alignment (stdoutput, seg);  return ((addr + (1 << align) - 1) & (-1 << align));}voidmd_begin (){  char *prev_name = "";  struct d10v_opcode *opcode;  d10v_hash = hash_new ();  /* Insert unique names into hash table.  The D10v instruction set     has many identical opcode names that have different opcodes based     on the operands.  This hash table then provides a quick index to     the first opcode with a particular name in the opcode table.  */  for (opcode = (struct d10v_opcode *) d10v_opcodes; opcode->name; opcode++)    {      if (strcmp (prev_name, opcode->name))	{	  prev_name = (char *) opcode->name;	  hash_insert (d10v_hash, opcode->name, (char *) opcode);	}    }  fixups = &FixUps[0];  FixUps[0].next = &FixUps[1];  FixUps[1].next = &FixUps[0];}/* Remove the postincrement or postdecrement operator ( '+' or '-' )   from an expression.  */static intpostfix (p)     char *p;{  while (*p != '-' && *p != '+')    {      if (*p == 0 || *p == '\n' || *p == '\r')	break;      p++;    }  if (*p == '-')    {      *p = ' ';      return (-1);    }  if (*p == '+')    {      *p = ' ';      return (1);    }  return (0);}static bfd_reloc_code_real_typeget_reloc (op)     struct d10v_operand *op;{  int bits = op->bits;  if (bits <= 4)    return (0);  if (op->flags & OPERAND_ADDR)    {      if (bits == 8)	return (BFD_RELOC_D10V_10_PCREL_R);      else	return (BFD_RELOC_D10V_18_PCREL);    }  return (BFD_RELOC_16);}/* Parse a string of operands.  Return an array of expressions.  */static intget_operands (exp)     expressionS exp[];{  char *p = input_line_pointer;  int numops = 0;  int post = 0;  int uses_at = 0;  while (*p)    {      while (*p == ' ' || *p == '\t' || *p == ',')	p++;      if (*p == 0 || *p == '\n' || *p == '\r')	break;      if (*p == '@')	{	  uses_at = 1;	  p++;	  exp[numops].X_op = O_absent;	  if (*p == '(')	    {	      p++;	      exp[numops].X_add_number = OPERAND_ATPAR;	    }	  else if (*p == '-')	    {	      p++;	      exp[numops].X_add_number = OPERAND_ATMINUS;	    }	  else	    {	      exp[numops].X_add_number = OPERAND_ATSIGN;	      post = postfix (p);	    }	  numops++;	  continue;	}      if (*p == ')')	{	  /* Just skip the trailing paren.  */	  p++;	  continue;	}      input_line_pointer = p;      /* Check to see if it might be a register name.  */      if (!register_name (&exp[numops]))	{	  /* Parse as an expression.  */	  if (uses_at)	    {	      /* Any expression that involves the indirect addressing		 cannot also involve immediate addressing.  Therefore		 the use of the hash character is illegal.  */	      int save = do_not_ignore_hash;	      do_not_ignore_hash = 1;	      expression (&exp[numops]);	      do_not_ignore_hash = save;	    }	  else	    expression (&exp[numops]);	}      if (strncasecmp (input_line_pointer, "@word", 5) == 0)	{	  input_line_pointer += 5;	  if (exp[numops].X_op == O_register)	    {	      /* If it looked like a register name but was followed by                 "@word" then it was really a symbol, so change it to                 one.  */	      exp[numops].X_op = O_symbol;	      exp[numops].X_add_symbol =		symbol_find_or_make ((char *) exp[numops].X_op_symbol);	    }	  /* Check for identifier@word+constant.  */	  if (*input_line_pointer == '-' || *input_line_pointer == '+')	    {	      expressionS new_exp;	      expression (&new_exp);	      exp[numops].X_add_number = new_exp.X_add_number;	    }	  /* Convert expr into a right shift by AT_WORD_RIGHT_SHIFT.  */	  {	    expressionS new_exp;	    memset (&new_exp, 0, sizeof new_exp);	    new_exp.X_add_number = AT_WORD_RIGHT_SHIFT;	    new_exp.X_op = O_constant;	    new_exp.X_unsigned = 1;	    exp[numops].X_op_symbol = make_expr_symbol (&new_exp);	    exp[numops].X_op = O_right_shift;	  }	  know (AT_WORD_P (&exp[numops]));	}      if (exp[numops].X_op == O_illegal)	as_bad (_("illegal operand"));      else if (exp[numops].X_op == O_absent)	as_bad (_("missing operand"));      numops++;      p = input_line_pointer;    }  switch (post)    {    case -1:	/* Postdecrement mode.  */      exp[numops].X_op = O_absent;      exp[numops++].X_add_number = OPERAND_MINUS;      break;    case 1:	/* Postincrement mode.  */      exp[numops].X_op = O_absent;      exp[numops++].X_add_number = OPERAND_PLUS;      break;    }  exp[numops].X_op = 0;  return (numops);}static unsigned longd10v_insert_operand (insn, op_type, value, left, fix)     unsigned long insn;     int op_type;     offsetT value;     int left;     fixS *fix;{  int shift, bits;  shift = d10v_operands[op_type].shift;  if (left)    shift += 15;  bits = d10v_operands[op_type].bits;  /* Truncate to the proper number of bits.  */  if (check_range (value, bits, d10v_operands[op_type].flags))    as_bad_where (fix->fx_file, fix->fx_line,		  _("operand out of range: %d"), value);  value &= 0x7FFFFFFF >> (31 - bits);  insn |= (value << shift);  return insn;}/* Take a pointer to the opcode entry in the opcode table and the   array of operand expressions.  Return the instruction.  */static unsigned longbuild_insn (opcode, opers, insn)     struct d10v_opcode *opcode;     expressionS *opers;     unsigned long insn;

⌨️ 快捷键说明

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