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

📄 tc-mcore.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
/* tc-mcore.c -- Assemble code for M*Core   Copyright 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 "as.h"#include "bfd.h"#include "subsegs.h"#define DEFINE_TABLE#include "../opcodes/mcore-opc.h"#include <ctype.h>#include <string.h>#ifdef OBJ_ELF#include "elf/mcore.h"#endif#ifndef streq#define streq(a,b) (strcmp (a, b) == 0)#endif/* Forward declarations for dumb compilers.  */static void   mcore_s_literals PARAMS ((int));static void   mcore_cons PARAMS ((int));static void   mcore_float_cons PARAMS ((int));static void   mcore_stringer PARAMS ((int));static void   mcore_fill   PARAMS ((int));static int    log2 PARAMS ((unsigned int));static char * parse_reg    PARAMS ((char *, unsigned *));static char * parse_creg   PARAMS ((char *, unsigned *));static char * parse_exp    PARAMS ((char *, expressionS *));static char * parse_rt     PARAMS ((char *, char **, int, expressionS *));static char * parse_imm    PARAMS ((char *, unsigned *, unsigned, unsigned));static char * parse_mem    PARAMS ((char *, unsigned *, unsigned *, unsigned));static char * parse_psrmod PARAMS ((char *, unsigned *));static void   make_name PARAMS ((char *, char *, int));static int    enter_literal PARAMS ((expressionS *, int));static void   dump_literals PARAMS ((int));static void   check_literals PARAMS ((int, int));static void   mcore_s_text    PARAMS ((int));static void   mcore_s_data    PARAMS ((int));static void   mcore_s_section PARAMS ((int));static void   mcore_s_bss     PARAMS ((int));#ifdef OBJ_ELFstatic void   mcore_s_comm    PARAMS ((int));#endif/* Several places in this file insert raw instructions into the   object. They should use MCORE_INST_XXX macros to get the opcodes   and then use these two macros to crack the MCORE_INST value into   the appropriate byte values.  */#define	INST_BYTE0(x)  (target_big_endian ? (((x) >> 8) & 0xFF) : ((x) & 0xFF))#define	INST_BYTE1(x)  (target_big_endian ? ((x) & 0xFF) : (((x) >> 8) & 0xFF))const char comment_chars[] = "#/";const char line_separator_chars[] = ";";const char line_comment_chars[] = "#/";const int md_reloc_size = 8;static int do_jsri2bsr = 0;	/* Change here from 1 by Cruess 19 August 97.  */static int sifilter_mode = 0;const char EXP_CHARS[] = "eE";/* Chars that mean this number is a floating point constant    As in 0f12.456    or    0d1.2345e12  */const char FLT_CHARS[] = "rRsSfFdDxXpP";#define C(what,length) (((what) << 2) + (length))#define GET_WHAT(x)    ((x >> 2))/* These are the two types of relaxable instruction */#define COND_JUMP  1#define UNCD_JUMP  2#define UNDEF_DISP      0#define DISP12          1#define DISP32          2#define UNDEF_WORD_DISP 3#define C12_LEN	        2#define C32_LEN	       10	/* allow for align */#define U12_LEN	        2#define U32_LEN	        8	/* allow for align */typedef enum{  M210,  M340}cpu_type;cpu_type cpu = M340;/* Initialize the relax table.  */const relax_typeS md_relax_table[] = {  {    0,     0, 0,	  0 },  {    0,     0, 0,	  0 },  {    0,     0, 0,	  0 },  {    0,     0, 0,	  0 },  /* COND_JUMP */  {    0,     0, 0,	  0 },			  /* UNDEF_DISP */  { 2048, -2046, C12_LEN, C(COND_JUMP, DISP32) }, /* DISP12 */  {    0,     0, C32_LEN, 0 },			  /* DISP32 */  {    0,     0, C32_LEN, 0 },			  /* UNDEF_WORD_DISP */  /* UNCD_JUMP */  {    0,     0, 0,	  0 },			  /* UNDEF_DISP */       { 2048, -2046, U12_LEN, C(UNCD_JUMP, DISP32) }, /* DISP12 */           {    0,     0, U32_LEN, 0 },			  /* DISP32 */           {    0,     0, U32_LEN, 0 }			  /* UNDEF_WORD_DISP */};/* Literal pool data structures.  */struct literal{  unsigned short  refcnt;  unsigned char	  ispcrel;  unsigned char	  unused;  expressionS	  e;};#define MAX_POOL_SIZE	(1024/4)static struct literal litpool [MAX_POOL_SIZE];static unsigned poolsize;static unsigned poolnumber;static unsigned long poolspan;/* SPANPANIC: the point at which we get too scared and force a dump   of the literal pool, and perhaps put a branch in place.   Calculated as:  		 1024	span of lrw/jmpi/jsri insn (actually span+1)  		-2	possible alignment at the insn.  		-2	possible alignment to get the table aligned.  		-2	an inserted branch around the table.  	     == 1018   at 1018, we might be in trouble.   -- so we have to be smaller than 1018 and since we deal with 2-byte   instructions, the next good choice is 1016.   -- Note we have a test case that fails when we've got 1018 here.  */#define SPANPANIC	(1016)		/* 1024 - 1 entry - 2 byte rounding.  */#define SPANCLOSE	(900)#define SPANEXIT	(600)static symbolS * poolsym;		/* label for current pool.  */static char poolname[8];static struct hash_control * opcode_hash_control;	/* Opcode mnemonics.  *//* This table describes all the machine specific pseudo-ops the assembler   has to support.  The fields are:     Pseudo-op name without dot     Function to call to execute this pseudo-op     Integer arg to pass to the function.   */const pseudo_typeS md_pseudo_table[] ={  { "export",   s_globl,          0 },  { "import",   s_ignore,         0 },  { "literals", mcore_s_literals, 0 },  { "page",     listing_eject,    0 },  /* The following are to intercept the placement of data into the text     section (eg addresses for a switch table), so that the space they     occupy can be taken into account when deciding whether or not to     dump the current literal pool.     XXX - currently we do not cope with the .space and .dcb.d directives.  */  { "ascii",    mcore_stringer,       0 },  { "asciz",    mcore_stringer,       1 },  { "byte",     mcore_cons,           1 },  { "dc",       mcore_cons,           2 },  { "dc.b",     mcore_cons,           1 },  { "dc.d",     mcore_float_cons,    'd'},  { "dc.l",     mcore_cons,           4 },  { "dc.s",     mcore_float_cons,    'f'},  { "dc.w",     mcore_cons,           2 },  { "dc.x",     mcore_float_cons,    'x'},  { "double",   mcore_float_cons,    'd'},  { "float",    mcore_float_cons,    'f'},  { "hword",    mcore_cons,           2 },  { "int",      mcore_cons,           4 },  { "long",     mcore_cons,           4 },  { "octa",     mcore_cons,          16 },  { "quad",     mcore_cons,           8 },  { "short",    mcore_cons,           2 },  { "single",   mcore_float_cons,    'f'},  { "string",   mcore_stringer,       1 },  { "word",     mcore_cons,           2 },  { "fill",     mcore_fill,           0 },  /* Allow for the effect of section changes.  */  { "text",      mcore_s_text,    0 },  { "data",      mcore_s_data,    0 },  { "bss",       mcore_s_bss,     1 },#ifdef OBJ_EF  { "comm",      mcore_s_comm,    0 },#endif  { "section",   mcore_s_section, 0 },  { "section.s", mcore_s_section, 0 },  { "sect",      mcore_s_section, 0 },  { "sect.s",    mcore_s_section, 0 },  { 0,          0,                0 }};static voidmcore_s_literals (ignore)     int ignore;{  dump_literals (0);  demand_empty_rest_of_line ();}static voidmcore_cons (nbytes)     int nbytes;{  if (now_seg == text_section)    {      char * ptr = input_line_pointer;      int    commas = 1;      /* Count the number of commas on the line.  */      while (! is_end_of_line [(unsigned char) * ptr])	commas += * ptr ++ == ',';      poolspan += nbytes * commas;    }  cons (nbytes);  /* In theory we ought to call check_literals (2,0) here in case     we need to dump the literal table.  We cannot do this however,     as the directives that we are intercepting may be being used     to build a switch table, and we must not interfere with its     contents.  Instead we cross our fingers and pray...  */}static voidmcore_float_cons (float_type)     int float_type;{  if (now_seg == text_section)    {      char * ptr = input_line_pointer;      int    commas = 1;#ifdef REPEAT_CONS_EXPRESSIONS#error REPEAT_CONS_EXPRESSIONS not handled#endif      /* Count the number of commas on the line.  */      while (! is_end_of_line [(unsigned char) * ptr])	commas += * ptr ++ == ',';      /* We would like to compute "hex_float (float_type) * commas"	 but hex_float is not exported from read.c  */      float_type == 'f' ? 4 : (float_type == 'd' ? 8 : 12);      poolspan += float_type * commas;    }  float_cons (float_type);  /* See the comment in mcore_cons () about calling check_literals.     It is unlikely that a switch table will be constructed using     floating point values, but it is still likely that an indexed     table of floating point constants is being created by these     directives, so again we must not interfere with their placement.  */}static voidmcore_stringer (append_zero)     int append_zero;{  if (now_seg == text_section)    {      char * ptr = input_line_pointer;      /* In theory we should compute how many bytes are going to	 be occupied by the string(s) and add this to the poolspan.	 To keep things simple however, we just add the number of	 bytes left on the current line.  This will be an over-	 estimate, which is OK, and automatically allows for the	 appending a zero byte, since the real string(s) is/are	 required to be enclosed in double quotes.  */      while (! is_end_of_line [(unsigned char) * ptr])	ptr ++;      poolspan += ptr - input_line_pointer;    }  stringer (append_zero);  /* We call check_literals here in case a large number of strings are     being placed into the text section with a sequence of stringer     directives.  In theory we could be upsetting something if these     strings are actually in an indexed table instead of referenced by     individual labels.  Let us hope that that never happens.  */  check_literals (2, 0);}static voidmcore_fill (unused)     int unused;{  if (now_seg == text_section)    {      char * str = input_line_pointer;      int    size = 1;      int    repeat;      repeat = atoi (str);      /* Look to see if a size has been specified.  */      while (*str != '\n' && *str != 0 && *str != ',')	++ str;      if (* str == ',')	{	  size = atoi (str + 1);	  if (size > 8)	    size = 8;	  else if (size < 0)	    size = 0;	}      poolspan += size * repeat;    }  s_fill (unused);  check_literals (2, 0);}/* Handle the section changing pseudo-ops.  These call through to the   normal implementations, but they dump the literal pool first.  */static voidmcore_s_text (ignore)     int ignore;{  dump_literals (0);#ifdef OBJ_ELF  obj_elf_text (ignore);#else  s_text (ignore);#endif}static voidmcore_s_data (ignore)     int ignore;{  dump_literals (0);#ifdef OBJ_ELF  obj_elf_data (ignore);#else  s_data (ignore);#endif}static voidmcore_s_section (ignore)     int ignore;{  /* Scan forwards to find the name of the section.  If the section     being switched to is ".line" then this is a DWARF1 debug section     which is arbitarily placed inside generated code.  In this case     do not dump the literal pool because it is a) inefficient and     b) would require the generation of extra code to jump around the     pool.  */  char * ilp = input_line_pointer;  while (*ilp != 0 && isspace(*ilp))    ++ ilp;  if (strncmp (ilp, ".line", 5) == 0      && (isspace (ilp[5]) || *ilp == '\n' || *ilp == '\r'))    ;  else    dump_literals (0);#ifdef OBJ_ELF  obj_elf_section (ignore);#endif#ifdef OBJ_COFF  obj_coff_section (ignore);#endif}static voidmcore_s_bss (needs_align)     int needs_align;{  dump_literals (0);  s_lcomm_bytes (needs_align);}#ifdef OBJ_ELFstatic voidmcore_s_comm (needs_align)     int needs_align;{  dump_literals (0);  obj_elf_common (needs_align);}#endif/* This function is called once, at assembler startup time.  This should   set up all the tables, etc that the MD part of the assembler needs.  */voidmd_begin (){  mcore_opcode_info * opcode;  char * prev_name = "";  opcode_hash_control = hash_new ();  /* Insert unique names into hash table */  for (opcode = mcore_table; opcode->name; opcode ++)    {      if (streq (prev_name, opcode->name))	{	  /* Make all the opcodes with the same name point to the same	     string.  */	  opcode->name = prev_name;	}      else	{	  prev_name = opcode->name;	  hash_insert (opcode_hash_control, opcode->name, (char *) opcode);	}    }}static int reg_m;static int reg_n;static expressionS immediate;	/* absolute expression *//* Get a log2(val).  */static intlog2 (val)    unsigned int val;{    int log = -1;    while (val != 0)      {        log ++;        val >>= 1;      }    return log;}/* Try to parse a reg name.  */static char *parse_reg (s, reg)     char * s;     unsigned * reg;{  /* Strip leading whitespace.  */  while (isspace (* s))    ++ s;  if (tolower (s[0]) == 'r')    {      if (s[1] == '1' && s[2] >= '0' && s[2] <= '5')	{	  *reg = 10 + s[2] - '0';	  return s + 3;	}      if (s[1] >= '0' && s[1] <= '9')	{	  *reg = s[1] - '0';	  return s + 2;	}    }  else if (   tolower (s[0]) == 's'	   && tolower (s[1]) == 'p'	   && ! isalnum (s[2]))    {      * reg = 0;      return s + 2;    }  as_bad (_("register expected, but saw '%.6s'"), s);  return s;}static struct Cregs{  char * name;  unsigned int crnum;}cregs[] ={  { "psr",	 0},  { "vbr",	 1},  { "epsr",	 2},  { "fpsr",	 3},  { "epc",	 4},  { "fpc",	 5},  { "ss0",	 6},  { "ss1",	 7},  { "ss2",	 8},  { "ss3",	 9},  { "ss4",	10},  { "gcr",	11},  { "gsr",	12},  { "",		 0}};static char *parse_creg (s, reg)     char * s;     unsigned * reg;{  int i;  /* Strip leading whitespace.  */  while (isspace (* s))    ++s;  if ((tolower (s[0]) == 'c' && tolower (s[1]) == 'r'))    {      if (s[2] == '3' && s[3] >= '0' && s[3] <= '1')	{	  *reg = 30 + s[3] - '0';	  return s + 4;	}      if (s[2] == '2' && s[3] >= '0' && s[3] <= '9')	{	  *reg = 20 + s[3] - '0';	  return s + 4;	}      if (s[2] == '1' && s[3] >= '0' && s[3] <= '9')	{	  *reg = 10 + s[3] - '0';	  return s + 4;	}      if (s[2] >= '0' && s[2] <= '9')	{	  *reg = s[2] - '0';	  return s + 3;	}    }  /* Look at alternate creg names before giving error.  */  for (i = 0; cregs[i].name[0] != '\0'; i++)    {      char buf [10];      int  length;      int  j;      length = strlen (cregs[i].name);      for (j = 0; j < length; j++)	buf[j] = tolower (s[j]);      if (strncmp (cregs[i].name, buf, length) == 0)	{	  *reg = cregs[i].crnum;	  return s + length;	}    }  as_bad (_("control register expected, but saw '%.6s'"), s);  return s;}static char *parse_psrmod (s, reg)  char *     s;  unsigned * reg;{  int  i;  char buf[10];  static struct psrmods  {    char *       name;    unsigned int value;  }  psrmods[] =  {    { "ie", 1 },    { "fe", 2 },    { "ee", 4 },    { "af", 8 }	/* Really 0 and non-combinable.  */  };

⌨️ 快捷键说明

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