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

📄 tc-tic54x.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X   Copyright 1999, 2000 Free Software Foundation, Inc.   Contributed by Timothy Wall (twall@cygnus.com)   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.  *//* Texas Instruments TMS320C54X machine specific gas.   Written by Timothy Wall (twall@alum.mit.edu).   Valuable things to do:   Pipeline conflict warnings   We encode/decode "ld #_label, dp" differently in relocatable files     This means we're not compatible with TI output containing those     expressions.  We store the upper nine bits; TI stores the lower nine     bits.  How they recover the original upper nine bits is beyond me.   Tests to add to expect testsuite:     '=' and '==' with .if, .elseif, and .break   Incompatibilities (mostly trivial):   We don't allow '''   We fill text section with zeroes instead of "nop"s   We don't convert '' or "" to a single instance   We don't convert '' to '\0'   We don't allow strings with .byte/.half/.short/.long   Probably details of the subsym stuff are different   TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.  */#include <stdlib.h>#include <limits.h>#include <errno.h>#include "as.h"#include "sb.h"#include "macro.h"#include "subsegs.h"#include "struc-symbol.h"#include "opcode/tic54x.h"#include "obj-coff.h"#include <math.h>#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm.  */const char comment_chars[] = ";";const char line_comment_chars[] = ";*#"; /* At column zero only.  */const char line_separator_chars[] = ""; /* Not permitted.  *//* Characters which indicate that this is a floating point constant.  */const char FLT_CHARS[] = "fF";/* Characters that can be used to separate mantissa from exp in FP   nums.  */const char EXP_CHARS[] = "eE";/* Only word (et al.), align, or conditionals are allowed within   .struct/.union.  */#define ILLEGAL_WITHIN_STRUCT()					\  do								\    if (current_stag != NULL)					\      { 							\	as_bad (_("pseudo-op illegal within .struct/.union"));	\	return;							\      }								\  while (0)voidmd_show_usage (stream)     FILE *stream;{  fprintf (stream, _("C54x-specific command line  options:\n"));  fprintf (stream, _("-mfar-mode | -mf          Use extended addressing\n"));  fprintf (stream, _("-mcpu=<CPU version>       Specify the CPU version\n"));#if 0  fprintf (stream, _("-mcoff-version={0|1|2}    Select COFF version\n"));#endif  fprintf (stream, _("-merrors-to-file <filename>\n"));  fprintf (stream, _("-me <filename>            Redirect errors to a file\n"));}const char *md_shortopts = "";enum cpu_version{  VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,  V545LP = 15, V546LP = 16};enum address_mode{  c_mode,   /* 16-bit addresses.  */  far_mode  /* >16-bit addresses.  */};#define OPTION_ADDRESS_MODE     (OPTION_MD_BASE)#define OPTION_CPU_VERSION      (OPTION_ADDRESS_MODE + 1)#define OPTION_COFF_VERSION     (OPTION_CPU_VERSION + 1)#define OPTION_STDERR_TO_FILE   (OPTION_COFF_VERSION + 1)struct option md_longopts[] ={  { "mfar-mode",       no_argument,	 NULL, OPTION_ADDRESS_MODE },  { "mf",	      no_argument,	 NULL, OPTION_ADDRESS_MODE },  { "mcpu",	    required_argument,   NULL, OPTION_CPU_VERSION },#if 0  { "mcoff-version",   required_argument,   NULL, OPTION_COFF_VERSION },#endif  { "merrors-to-file", required_argument,   NULL, OPTION_STDERR_TO_FILE },  { "me",	      required_argument,   NULL, OPTION_STDERR_TO_FILE },  { NULL, no_argument, NULL, 0},};size_t md_longopts_size = sizeof (md_longopts);static int assembly_begun = 0;/* Addressing mode is not entirely implemented; the latest rev of the Other   assembler doesn't seem to make any distinction whatsoever; all relocations   are stored as extended relocatiosn.  Older versions used REL16 vs RELEXT16,   but now it seems all relocations are RELEXT16.  We use all RELEXT16.   The cpu version is kind of a waste of time as well.  There is one   instruction (RND) for LP devices only, and several for devices with   extended addressing only.  We include it for compatibility.  */static enum address_mode amode = c_mode;static enum cpu_version cpu = VNONE;/* Include string substitutions in listing?  */static int listing_sslist = 0;/* Did we do subsym substitutions on the line?  */static int substitution_line = 0;/* Last label seen.  */static symbolS *last_label_seen = NULL;/* This ensures that all new labels are unique.  */static int local_label_id;static struct hash_control *subsym_recurse_hash; /* Prevent infinite recurse.  */static struct hash_control *math_hash; /* Built-in math functions.  *//* Allow maximum levels of macro nesting; level 0 is the main substitution   symbol table.  The other assembler only does 32 levels, so there!  */static struct hash_control *subsym_hash[100];/* Keep track of local labels so we can substitute them before GAS sees them   since macros use their own 'namespace' for local labels, use a separate hash   We do our own local label handling 'cuz it's subtly different from the   stock GAS handling.   We use our own macro nesting counter, since GAS overloads it when expanding   other things (like conditionals and repeat loops).  */static int macro_level = 0;static struct hash_control *local_label_hash[100];/* Keep track of struct/union tags.  */static struct hash_control *stag_hash;static struct hash_control *op_hash;static struct hash_control *parop_hash;static struct hash_control *reg_hash;static struct hash_control *mmreg_hash;static struct hash_control *cc_hash;static struct hash_control *cc2_hash;static struct hash_control *cc3_hash;static struct hash_control *sbit_hash;static struct hash_control *misc_symbol_hash;static char *subsym_substitute PARAMS ((char *line, int forced));static char *subsym_lookup PARAMS ((char *name, int nest_level));static void subsym_create_or_replace PARAMS ((char *name, char *value));static float math_ceil PARAMS ((float, float));static float math_cvi PARAMS ((float, float));static float math_floor PARAMS ((float, float));static float math_fmod PARAMS ((float, float));static float math_int PARAMS ((float, float));static float math_round PARAMS ((float, float));static float math_sgn PARAMS ((float, float));static float math_trunc PARAMS ((float, float));static float math_acos PARAMS ((float, float));static float math_asin PARAMS ((float, float));static float math_atan PARAMS ((float, float));static float math_atan2 PARAMS ((float, float));static float math_cosh PARAMS ((float, float));static float math_cos PARAMS ((float, float));static float math_cvf PARAMS ((float, float));static float math_exp PARAMS ((float, float));static float math_fabs PARAMS ((float, float));static float math_ldexp PARAMS ((float, float));static float math_log10 PARAMS ((float, float));static float math_log PARAMS ((float, float));static float math_max PARAMS ((float, float));static float math_pow PARAMS ((float, float));static float math_sin PARAMS ((float, float));static float math_sinh PARAMS ((float, float));static float math_sqrt PARAMS ((float, float));static float math_tan PARAMS ((float, float));static float math_tanh PARAMS ((float, float));static struct stag{  symbolS *sym;		     /* Symbol for this stag; value is offset.  */  const char *name;		 /* Shortcut to symbol name.  */  bfd_vma size;		     /* Size of struct/union.  */  int current_bitfield_offset;      /* Temporary for tracking fields.  */  int is_union;  struct stag_field		 /* List of fields.  */  {    const char *name;    bfd_vma offset;		 /* Of start of this field.  */    int bitfield_offset;	    /* Of start of this field.  */    struct stag *stag;	      /* If field is struct/union.  */    struct stag_field *next;  } *field;  /* For nesting; used only in stag construction.  */  struct stag *inner;	       /* Enclosed .struct.  */  struct stag *outer;	       /* Enclosing .struct.  */} *current_stag = NULL;static segT stag_saved_seg;static subsegT stag_saved_subseg;/* Output a single character (upper octect is zero).  */static voidtic54x_emit_char (c)     char c;{  expressionS exp;  exp.X_op = O_constant;  exp.X_add_number = c;  emit_expr (&exp, 2);}/* Walk backwards in the frag chain.  */static fragS *frag_prev (frag, seg)     fragS *frag;     segT seg;{  segment_info_type *seginfo = seg_info (seg);  fragS *fragp;  for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)    if (fragp->fr_next == frag)      return fragp;  return NULL;}static fragS *bit_offset_frag (frag, seg)     fragS *frag;     segT seg;{  while (frag != NULL)    {      if (frag->fr_fix == 0	  && frag->fr_opcode == NULL	  && frag->tc_frag_data == 0)	frag = frag_prev (frag, seg);      else	return frag;    }  return NULL;}/* Return the number of bits allocated in the most recent word, or zero if   none. .field/.space/.bes may leave words partially allocated.  */static intfrag_bit_offset (frag, seg)     fragS *frag;     segT seg;{  frag = bit_offset_frag (frag, seg);  if (frag)    return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;  return 0;}/* Read an expression from a C string; returns a pointer past the end of the   expression.  */static char *parse_expression (char *str, expressionS * exp){  char *s;  char *tmp;  tmp = input_line_pointer;	/* Save line pointer.  */  input_line_pointer = str;  expression (exp);  s = input_line_pointer;  input_line_pointer = tmp;	/* Restore line pointer.  */  return s;			/* Return pointer to where parsing stopped.  */}/* .asg "character-string"|character-string, symbol   .eval is the only pseudo-op allowed to perform arithmetic on substitution   symbols.  all other use of symbols defined with .asg are currently   unsupported.  */static voidtic54x_asg (x)     int x ATTRIBUTE_UNUSED;{  int c;  char *name;  char *str;  char *tmp;  int quoted = *input_line_pointer == '"';  ILLEGAL_WITHIN_STRUCT ();  if (quoted)    {      int len;      str = demand_copy_C_string (&len);      c = *input_line_pointer;    }  else    {      str = input_line_pointer;      while ((c = *input_line_pointer) != ',')	{	  if (is_end_of_line[(int) *input_line_pointer])	    break;	  ++input_line_pointer;	}      *input_line_pointer = 0;    }  if (c != ',')    {      as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));      ignore_rest_of_line ();      return;    }  name = ++input_line_pointer;  c = get_symbol_end ();	/* Get terminator.  */  if (!isalpha (*name))    {      as_bad ("symbols assigned with .asg must begin with a letter");      ignore_rest_of_line ();      return;    }  tmp = xmalloc (strlen (str) + 1);  strcpy (tmp, str);  str = tmp;  tmp = xmalloc (strlen (name) + 1);  strcpy (tmp, name);  name = tmp;  subsym_create_or_replace (name, str);  *input_line_pointer = c;  demand_empty_rest_of_line ();}/* .eval expression, symbol   There's something screwy about this.  The other assembler sometimes does and   sometimes doesn't substitute symbols defined with .eval.   We'll put the symbols into the subsym table as well as the normal symbol   table, since that's what works best.  */static voidtic54x_eval (x)     int x ATTRIBUTE_UNUSED;{  char c;  int value;  char *name;  symbolS *symbolP;  char valuestr[32], *tmp;  int quoted;  ILLEGAL_WITHIN_STRUCT ();  SKIP_WHITESPACE ();  quoted = *input_line_pointer == '"';  if (quoted)    ++input_line_pointer;  value = get_absolute_expression ();  if (quoted)    {      if (*input_line_pointer != '"')	{	  as_bad (_("Unterminated string after absolute expression"));	  ignore_rest_of_line ();	  return;	}      ++input_line_pointer;    }  if (*input_line_pointer++ != ',')    {      as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));      ignore_rest_of_line ();      return;    }  name = input_line_pointer;  c = get_symbol_end ();	/* Get terminator.  */  tmp = xmalloc (strlen (name) + 1);  name = strcpy (tmp, name);  *input_line_pointer = c;  if (!isalpha (*name))    {      as_bad (_("symbols assigned with .eval must begin with a letter"));      ignore_rest_of_line ();      return;    }  symbolP = symbol_new (name, absolute_section,			(valueT) value, &zero_address_frag);  SF_SET_LOCAL (symbolP);  symbol_table_insert (symbolP);  /* The "other" assembler sometimes doesn't put .eval's in the subsym table     But since there's not written rule as to when, don't even bother trying     to match their behavior.  */  sprintf (valuestr, "%d", value);  tmp = xmalloc (strlen (valuestr) + 1);  strcpy (tmp, valuestr);  subsym_create_or_replace (name, tmp);  demand_empty_rest_of_line ();}/* .bss symbol, size [, [blocking flag] [, alignment flag]   alignment is to a longword boundary; blocking is to 128-word boundary.   1) if there is a hole in memory, this directive should attempt to fill it      (not yet implemented).   2) if the blocking flag is not set, allocate at the current SPC      otherwise, check to see if the current SPC plus the space to be      allocated crosses the page boundary (128 words).      if there's not enough space, create a hole and align with the next page      boundary.      (not yet implemented).  */static voidtic54x_bss (x)     int x ATTRIBUTE_UNUSED;{  char c;  char *name;  char *p;  int words;  segT current_seg;  subsegT current_subseg;  symbolS *symbolP;  int block = 0;  int align = 0;  ILLEGAL_WITHIN_STRUCT ();  current_seg = now_seg;	/* Save current seg.  */  current_subseg = now_subseg;	/* Save current subseg.  */  name = input_line_pointer;  c = get_symbol_end ();	/* Get terminator.  */  if (c != ',')    {      as_bad (".bss size argument missing\n");      ignore_rest_of_line ();      return;    }  ++input_line_pointer;  words = get_absolute_expression ();  if (words < 0)    {      as_bad (".bss size %d < 0!", words);      ignore_rest_of_line ();      return;    }  if (*input_line_pointer == ',')

⌨️ 快捷键说明

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