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

📄 tc-d30v.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
/* tc-d30v.c -- Assembler code for the Mitsubishi D30V   Copyright 1997, 1998, 1999, 2000 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/d30v.h"const char comment_chars[] = ";";const char line_comment_chars[] = "#";const char line_separator_chars[] = "";const char *md_shortopts = "OnNcC";const char EXP_CHARS[] = "eE";const char FLT_CHARS[] = "dD";#if HAVE_LIMITS_H#include <limits.h>#endif#ifndef CHAR_BIT#define CHAR_BIT 8#endif#define NOP_MULTIPLY 1#define NOP_ALL 2static int warn_nops = 0;static int Optimizing = 0;static int warn_register_name_conflicts = 1;#define FORCE_SHORT	1#define FORCE_LONG	2/* EXEC types.  */typedef enum _exec_type{  EXEC_UNKNOWN,			/* no order specified */  EXEC_PARALLEL,		/* done in parallel (FM=00) */  EXEC_SEQ,			/* sequential (FM=01) */  EXEC_REVSEQ			/* reverse sequential (FM=10) */} exec_type_enum;/* Fixups.  */#define MAX_INSN_FIXUPS (5)struct d30v_fixup{  expressionS exp;  int operand;  int pcrel;  int size;  bfd_reloc_code_real_type reloc;};typedef struct _fixups{  int fc;  struct d30v_fixup fix[MAX_INSN_FIXUPS];  struct _fixups *next;} Fixups;static Fixups FixUps[2];static Fixups *fixups;/* Whether current and previous instruction are word multiply insns.  */static int cur_mul32_p = 0;static int prev_mul32_p = 0;/*  The flag_explicitly_parallel is true iff the instruction being assembled    has been explicitly written as a parallel short-instruction pair by the    human programmer.  It is used in parallel_ok () to distinguish between    those dangerous parallelizations attempted by the human, which are to be    allowed, and those attempted by the assembler, which are not.  It is set    from md_assemble ().  */static int flag_explicitly_parallel = 0;static int flag_xp_state = 0;/* Whether current and previous left sub-instruction disables   execution of right sub-instruction.  */static int cur_left_kills_right_p = 0;static int prev_left_kills_right_p = 0;/* The known current alignment of the current section.  */static int d30v_current_align;static segT d30v_current_align_seg;/* The last seen label in the current section.  This is used to auto-align   labels preceeding instructions.  */static symbolS *d30v_last_label;/* Two nops.  */#define NOP_LEFT   ((long long) NOP << 32)#define NOP_RIGHT  ((long long) NOP)#define NOP2 (FM00 | NOP_LEFT | NOP_RIGHT)/* 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 d30v_operand *op, int rel_flag));static int get_operands PARAMS ((expressionS exp[], int cmp_hack));static struct d30v_format *find_format PARAMS ((struct d30v_opcode *opcode,			expressionS ops[],int fsize, int cmp_hack));static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers));static void write_long PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn,				   Fixups *fx, int use_sequential));static int write_2_short PARAMS ((struct d30v_insn *opcode1, long long insn1,		   struct d30v_insn *opcode2, long long insn2, exec_type_enum exec_type, Fixups *fx));static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode,				      int shortp, int is_parallel));static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1,				struct d30v_insn *opcode2, unsigned long insn2,				exec_type_enum exec_type));static void d30v_number_to_chars PARAMS ((char *buf, long long value, int nbytes));static void check_size PARAMS ((long value, int bits, char *file, int line));static void d30v_align PARAMS ((int, char *, symbolS *));static void s_d30v_align PARAMS ((int));static void s_d30v_text PARAMS ((int));static void s_d30v_data PARAMS ((int));static void s_d30v_section PARAMS ((int));struct option md_longopts[] ={  {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);/* The target specific pseudo-ops which we support.  */const pseudo_typeS md_pseudo_table[] ={  { "word", cons, 4 },  { "hword", cons, 2 },  { "align", s_d30v_align, 0 },  { "text", s_d30v_text, 0 },  { "data", s_d30v_data, 0 },  { "section", s_d30v_section, 0 },  { "section.s", s_d30v_section, 0 },  { "sect", s_d30v_section, 0 },  { "sect.s", s_d30v_section, 0 },  { NULL, NULL, 0 }};/* Opcode hash table.  */static struct hash_control *d30v_hash;/* Do a binary search of the pre_defined_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 = reg_name_cnt () - 1;  do    {      middle = (low + high) / 2;      cmp = strcasecmp (name, pre_defined_registers[middle].name);      if (cmp < 0)	high = middle - 1;      else if (cmp > 0)	low = middle + 1;      else	{	  if (symbol_find (name) != NULL)	    {	      if (warn_register_name_conflicts)		as_warn (_("Register name %s conflicts with symbol of the same name"),			 name);	    }	  return pre_defined_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;  /* Don't bother checking 32-bit values.  */  if (bits == 32)    {      if (sizeof (unsigned long) * CHAR_BIT == 32)        return 0;      /* We don't record signed or unsigned for 32-bit quantities.	 Allow either.  */      min = -((unsigned long) 1 << (bits - 1));      max = ((unsigned long) 1 << bits) - 1;      return (long)num < min || (long)num > max;    }  if (flags & OPERAND_SHIFT)    {      /* We know that all shifts are right by three bits.  */      if (flags & OPERAND_SIGNED)	num = (unsigned long) ((long) num >= 0)		? (((long) num) >> 3)		: ((num >> 3) | ~(~(unsigned long) 0 >> 3));      else	num >>= 3;    }  if (flags & OPERAND_SIGNED)    {      max = ((unsigned long) 1 << (bits - 1)) - 1;      min = - ((unsigned long) 1 << (bits - 1));      return (long)num > max || (long)num < min;    }  else    {      max = ((unsigned long) 1 << bits) - 1;      min = 0;      return num > max || num < min;    }}voidmd_show_usage (stream)     FILE *stream;{  fprintf (stream, _("\nD30V options:\n\-O                      Make adjacent short instructions parallel if possible.\n\-n                      Warn about all NOPs inserted by the assembler.\n\-N			Warn about NOPs inserted after word multiplies.\n\-c                      Warn about symbols whoes names match register names.\n\-C                      Opposite of -C.  -c is the default.\n"));}intmd_parse_option (c, arg)     int c;     char *arg;{  switch (c)    {      /* Optimize.  Will attempt to parallelize operations.  */    case 'O':      Optimizing = 1;      break;      /* Warn about all NOPS that the assembler inserts.  */    case 'n':      warn_nops = NOP_ALL;      break;      /* Warn about the NOPS that the assembler inserts because of the	 multiply hazard.  */    case 'N':      warn_nops = NOP_MULTIPLY;      break;    case 'c':      warn_register_name_conflicts = 1;      break;    case 'C':      warn_register_name_conflicts = 0;      break;    default:      return 0;    }  return 1;}symbolS *md_undefined_symbol (name)     char *name;{  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;     asection *sec;     fragS *fragP;{  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 (){  struct d30v_opcode *opcode;  d30v_hash = hash_new ();  /* Insert opcode names into a hash table.  */  for (opcode = (struct d30v_opcode *) d30v_opcode_table; opcode->name; opcode++)      hash_insert (d30v_hash, opcode->name, (char *) opcode);  fixups = &FixUps[0];  FixUps[0].next = &FixUps[1];  FixUps[1].next = &FixUps[0];  d30v_current_align_seg = now_seg;}/* 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' || *p == ' ' || *p == ',')	break;      p++;    }  if (*p == '-')    {      *p = ' ';      return -1;    }  if (*p == '+')    {      *p = ' ';      return 1;    }  return 0;}static bfd_reloc_code_real_typeget_reloc (op, rel_flag)     struct d30v_operand *op;     int rel_flag;{  switch (op->bits)    {    case 6:      if (op->flags & OPERAND_SHIFT)	return BFD_RELOC_D30V_9_PCREL;      else	return BFD_RELOC_D30V_6;      break;    case 12:      if (!(op->flags & OPERAND_SHIFT))	as_warn (_("unexpected 12-bit reloc type"));      if (rel_flag == RELOC_PCREL)	return BFD_RELOC_D30V_15_PCREL;      else	return BFD_RELOC_D30V_15;    case 18:      if (!(op->flags & OPERAND_SHIFT))	as_warn (_("unexpected 18-bit reloc type"));      if (rel_flag == RELOC_PCREL)	return BFD_RELOC_D30V_21_PCREL;      else	return BFD_RELOC_D30V_21;    case 32:      if (rel_flag == RELOC_PCREL)	return BFD_RELOC_D30V_32_PCREL;      else	return BFD_RELOC_D30V_32;    default:      return 0;    }}/* Parse a string of operands and return an array of expressions.  */static intget_operands (exp, cmp_hack)     expressionS exp[];     int cmp_hack;{  char *p = input_line_pointer;  int numops = 0;  int post = 0;  if (cmp_hack)    {      exp[numops].X_op = O_absent;      exp[numops++].X_add_number = cmp_hack - 1;    }  while (*p)    {      while (*p == ' ' || *p == '\t' || *p == ',')	p++;      if (*p == 0 || *p == '\n' || *p == '\r')	break;      if (*p == '@')	{	  p++;	  exp[numops].X_op = O_absent;	  if (*p == '(')	    {	      p++;	      exp[numops].X_add_number = OPERAND_ATPAR;	      post = postfix (p);	    }	  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.  */	  expression (&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;	}

⌨️ 快捷键说明

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