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

📄 tc-cris.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tc-cris.c -- Assembler code for the CRIS CPU core.   Copyright 2000, 2001 Free Software Foundation, Inc.   Contributed by Axis Communications AB, Lund, Sweden.   Originally written for GAS 1.38.1 by Mikael Asker.   Updated, BFDized and GNUified by Hans-Peter Nilsson.   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/cris.h"#include "dwarf2dbg.h"/* Conventions used here:   Generally speaking, pointers to binutils types such as "fragS" and   "expressionS" get parameter and variable names ending in "P", such as   "fragP", to harmonize with the rest of the binutils code.  Other   pointers get a "p" suffix, such as "bufp".  Any function or type-name   that could clash with a current or future binutils or GAS function get   a "cris_" prefix.  */#define SYNTAX_RELAX_REG_PREFIX "no_register_prefix"#define SYNTAX_ENFORCE_REG_PREFIX "register_prefix"#define SYNTAX_USER_SYM_LEADING_UNDERSCORE "leading_underscore"#define SYNTAX_USER_SYM_NO_LEADING_UNDERSCORE "no_leading_underscore"#define REGISTER_PREFIX_CHAR '$'/* This might be CRIS_INSN_NONE if we're assembling a prefix-insn only.   Note that some prefix-insns might be assembled as CRIS_INSN_NORMAL.  */enum cris_insn_kind{  CRIS_INSN_NORMAL, CRIS_INSN_NONE, CRIS_INSN_BRANCH};/* An instruction will have one of these prefixes.   Although the same bit-pattern, we handle BDAP with an immediate   expression (eventually quick or [pc+]) different from when we only have   register expressions.  */enum prefix_kind{  PREFIX_NONE, PREFIX_BDAP_IMM, PREFIX_BDAP, PREFIX_BIAP, PREFIX_DIP,  PREFIX_PUSH};/* The prefix for an instruction.  */struct cris_prefix{  enum prefix_kind kind;  int base_reg_number;  unsigned int opcode;  /* There might be an expression to be evaluated, like I in [rN+I].  */  expressionS expr;  /* If there's an expression, we might need a relocation.  Here's the     type of what relocation to start relaxaton with.     The relocation is assumed to start immediately after the prefix insn,     so we don't provide an offset.  */  enum bfd_reloc_code_real reloc;};/* The description of the instruction being assembled.  */struct cris_instruction{  /* If CRIS_INSN_NONE, then this insn is of zero length.  */  enum cris_insn_kind insn_type;  /* If a special register was mentioned, this is its description, else     it is NULL.  */  const struct cris_spec_reg *spec_reg;  unsigned int opcode;  /* An insn may have at most one expression; theoretically there could be     another in its prefix (but I don't see how that could happen).  */  expressionS expr;  /* The expression might need a relocation.  Here's one to start     relaxation with.  */  enum bfd_reloc_code_real reloc;  /* The size in bytes of an immediate expression, or zero in     nonapplicable.  */  int imm_oprnd_size;};static void cris_process_instruction PARAMS ((char *,					      struct cris_instruction *,					      struct cris_prefix *));static int get_bwd_size_modifier PARAMS ((char **, int *));static int get_bw_size_modifier PARAMS ((char **, int *));static int get_gen_reg PARAMS ((char **, int *));static int get_spec_reg PARAMS ((char **,				 const struct cris_spec_reg **));static int get_autoinc_prefix_or_indir_op PARAMS ((char **,						   struct cris_prefix *,						   int *, int *, int *,						   expressionS *));static int get_3op_or_dip_prefix_op PARAMS ((char **,					     struct cris_prefix *));static int cris_get_expression PARAMS ((char **, expressionS *));static int get_flags PARAMS ((char **, int *));static void gen_bdap PARAMS ((int, expressionS *));static int branch_disp PARAMS ((int));static void gen_cond_branch_32 PARAMS ((char *, char *, fragS *,					symbolS *, symbolS *, long int));static void cris_number_to_imm PARAMS ((char *, long, int, fixS *));static void cris_create_short_jump PARAMS ((char *, addressT, addressT,					    fragS *, symbolS *));static void s_syntax PARAMS ((int));static void s_cris_file PARAMS ((int));static void s_cris_loc PARAMS ((int));/* All the .syntax functions.  */static void cris_force_reg_prefix PARAMS ((void));static void cris_relax_reg_prefix PARAMS ((void));static void cris_sym_leading_underscore PARAMS ((void));static void cris_sym_no_leading_underscore PARAMS ((void));static char *cris_insn_first_word_frag PARAMS ((void));/* Handle to the opcode hash table.  */static struct hash_control *op_hash = NULL;/* Whether we demand that registers have a `$' prefix.  Default here.  */static boolean demand_register_prefix = false;/* Whether global user symbols have a leading underscore.  Default here.  */static boolean symbols_have_leading_underscore = true;const pseudo_typeS md_pseudo_table[] ={  {"dword", cons, 4},  {"syntax", s_syntax, 0},  {"file", s_cris_file, 0},  {"loc", s_cris_loc, 0},  {NULL, 0, 0}};static int warn_for_branch_expansion = 0;const char cris_comment_chars[] = ";";/* This array holds the chars that only start a comment at the beginning of   a line.  If the line seems to have the form '# 123 filename'   .line and .file directives will appear in the pre-processed output.  *//* Note that input_file.c hand-checks for '#' at the beginning of the   first line of the input file.  This is because the compiler outputs   #NO_APP at the beginning of its output.  *//* Also note that slash-star will always start a comment.  */const char line_comment_chars[] = "#";const char line_separator_chars[] = "@";/* Now all floating point support is shut off.  See md_atof.  */const char EXP_CHARS[] = "";const char FLT_CHARS[] = "";/* For CRIS, we encode the relax_substateTs (in e.g. fr_substate) as:		       2		 1		   0      ---/ /--+-----------------+-----------------+-----------------+	      |	 what state ?	|	     how long ?		    |      ---/ /--+-----------------+-----------------+-----------------+   The "how long" bits are 00 = byte, 01 = word, 10 = dword (long).   This is a Un*x convention.   Not all lengths are legit for a given value of (what state).   Groups for CRIS address relaxing:   1. Bcc      length: byte, word, 10-byte expansion   2. BDAP      length: byte, word, dword  */#define STATE_CONDITIONAL_BRANCH    (1)#define STATE_BASE_PLUS_DISP_PREFIX (2)#define STATE_LENGTH_MASK	    (3)#define STATE_BYTE		    (0)#define STATE_WORD		    (1)#define STATE_DWORD		    (2)/* Symbol undefined.  */#define STATE_UNDF		    (3)#define STATE_MAX_LENGTH	    (3)/* These displacements are relative to the adress following the opcode   word of the instruction.  The first letter is Byte, Word.  The 2nd   letter is Forward, Backward.  */#define BRANCH_BF ( 254)#define BRANCH_BB (-256)#define BRANCH_WF (2 +  32767)#define BRANCH_WB (2 + -32768)#define BDAP_BF	  ( 127)#define BDAP_BB	  (-128)#define BDAP_WF	  ( 32767)#define BDAP_WB	  (-32768)#define ENCODE_RELAX(what, length) (((what) << 2) + (length))const relax_typeS md_cris_relax_table[] ={  /* Error sentinel (0, 0).  */  {1,	      1,	 0,  0},  /* Unused (0, 1).  */  {1,	      1,	 0,  0},  /* Unused (0, 2).  */  {1,	      1,	 0,  0},  /* Unused (0, 3).  */  {1,	      1,	 0,  0},  /* Bcc o (1, 0).  */  {BRANCH_BF, BRANCH_BB, 0,  ENCODE_RELAX (1, 1)},  /* Bcc [PC+] (1, 1).  */  {BRANCH_WF, BRANCH_WB, 2,  ENCODE_RELAX (1, 2)},  /* BEXT/BWF, BA, JUMP (external), JUMP (always), Bnot_cc, JUMP (default)     (1, 2).  */  {0,	      0,	 10, 0},  /* Unused (1, 3).  */  {1,	      1,	 0,  0},  /* BDAP o (2, 0).  */  {BDAP_BF,   BDAP_BB,	 0,  ENCODE_RELAX (2, 1)},  /* BDAP.[bw] [PC+] (2, 1).  */  {BDAP_WF,   BDAP_WB,	 2,  ENCODE_RELAX (2, 2)},  /* BDAP.d [PC+] (2, 2).  */  {0,	      0,	 4,  0}};#undef BRANCH_BF#undef BRANCH_BB#undef BRANCH_WF#undef BRANCH_WB#undef BDAP_BF#undef BDAP_BB#undef BDAP_WF#undef BDAP_WB/* Target-specific multicharacter options, not const-declared at usage   in 2.9.1 and CVS of 2000-02-16.  */struct option md_longopts[] ={#define OPTION_NO_US (OPTION_MD_BASE + 0)  {"no-underscore", no_argument, NULL, OPTION_NO_US},#define OPTION_US (OPTION_MD_BASE + 1)  {"underscore", no_argument, NULL, OPTION_US},  {NULL, no_argument, NULL, 0}};/* Not const-declared at usage in 2.9.1.  */size_t md_longopts_size = sizeof (md_longopts);const char *md_shortopts = "hHN";/* At first glance, this may seems wrong and should be 4 (ba + nop); but   since a short_jump must skip a *number* of long jumps, it must also be   a long jump.  Here, we hope to make it a "ba [16bit_offs]" and a "nop"   for the delay slot and hope that the jump table at most needs   32767/4=8191 long-jumps.  A branch is better than a jump, since it is   relative; we will not have a reloc to fix up somewhere.   Note that we can't add relocs, because relaxation uses these fixed   numbers, and md_create_short_jump is called after relaxation.  */const int md_short_jump_size = 6;const int md_long_jump_size = 6;/* Report output format.  Small changes in output format (like elf   variants below) can happen until all options are parsed.  */const char *cris_target_format (){  switch (OUTPUT_FLAVOR)    {    case bfd_target_aout_flavour:      return "a.out-cris";    case bfd_target_elf_flavour:      if (symbols_have_leading_underscore)	return "elf32-us-cris";      return "elf32-cris";    default:      abort ();      return NULL;    }}/* Prepare machine-dependent frags for relaxation.   Called just before relaxation starts. Any symbol that is now undefined   will not become defined.   Return the correct fr_subtype in the frag.   Return the initial "guess for fr_var" to caller.  The guess for fr_var   is *actually* the growth beyond fr_fix. Whatever we do to grow fr_fix   or fr_var contributes to our returned value.   Although it may not be explicit in the frag, pretend   fr_var starts with a value.  */intmd_estimate_size_before_relax (fragP, segment_type)     fragS *fragP;     /* The segment is either N_DATA or N_TEXT.  */     segT segment_type;{  int old_fr_fix;  old_fr_fix = fragP->fr_fix;  switch (fragP->fr_subtype)    {    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):      if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)	{	  /* The symbol lies in the same segment - a relaxable case.  */	  fragP->fr_subtype	    = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);	}      else	{	  /* Unknown or not the same segment, so not relaxable.  */	  char *writep;	  /* A small branch-always (2 bytes) to the "real" branch	     instruction, plus a delay-slot nop (2 bytes), plus a	     jump (2 plus 4 bytes).  See gen_cond_branch_32.  */	  fragP->fr_fix += 2 + 2 + 2 + 4;	  writep = fragP->fr_literal + old_fr_fix;	  gen_cond_branch_32 (fragP->fr_opcode, writep, fragP,			      fragP->fr_symbol, (symbolS *) NULL,			      fragP->fr_offset);	  frag_wane (fragP);	}      break;    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):      /* We *might* give a better initial guess if we peek at offsets	 now, but the caller will relax correctly and without this, so	 don't bother.  */      break;    case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_UNDF):      /* Note that we can not do anything sane with relaxing	 [rX + a_known_symbol_in_text], it will have to be a 32-bit	 value.	 We could play tricks with managing a constant pool and make	 a_known_symbol_in_text a "bdap [pc + offset]" pointing there, but	 that's pointless, it can only be longer and slower.	 Off-topic: If PIC becomes *really* important, and has to be done	 in the assembler and linker only (which would be weird or	 clueless), we can so something.  Imagine:	   move.x [r + 32_bit_symbol],r	   move.x [32_bit_symbol],r	   move.x 32_bit_symbol,r	 can be shortened by a word (8-bit offset) if we are close to the	 symbol or keep its length (16-bit offset) or be a word longer	 (32-bit offset).  Then change the 32_bit_symbol into a "bdap [pc	 + offset]", and put the offset to the 32_bit_symbol in "offset".	 Weird, to say the least, and we still have to add support for a	 PC-relative relocation in the loader (shared libraries).  But	 it's an interesting thought.  */      if (S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)	{	  /* Go for dword if not absolute or same segment.  */	  fragP->fr_subtype	    = ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD);	  fragP->fr_var += 4;	}      else	{	  /* Absolute expression.  */	  long int value;	  value = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;	  if (value >= -128 && value <= 127)	    {	      /* Byte displacement.  */	      (fragP->fr_opcode)[0] = value;	    }	  else	    {	      /* Word or dword displacement.  */	      int pow2_of_size = 1;	      char *writep;	      if (value < -32768 || value > 32767)		{		  /* Outside word range, make it a dword.  */		  pow2_of_size = 2;		}	      /* Modify the byte-offset BDAP into a word or dword offset		 BDAP.	Or really, a BDAP rX,8bit into a		 BDAP.[wd] rX,[PC+] followed by a word or dword.  */	      (fragP->fr_opcode)[0] = BDAP_PC_LOW + pow2_of_size * 16;	      /* Keep the register number in the highest four bits.  */	      (fragP->fr_opcode)[1] &= 0xF0;	      (fragP->fr_opcode)[1] |= BDAP_INCR_HIGH;	      /* It grew by two or four bytes.  */	      fragP->fr_fix += 1 << pow2_of_size;	      writep = fragP->fr_literal + old_fr_fix;	      md_number_to_chars (writep, value, 1 << pow2_of_size);	    }	  frag_wane (fragP);	}      break;    default:      BAD_CASE (fragP->fr_subtype);    }  return fragP->fr_var + (fragP->fr_fix - old_fr_fix);}/* Perform post-processing of machine-dependent frags after relaxation.   Called after relaxation is finished.   In:	Address of frag.	fr_type == rs_machine_dependent.	fr_subtype is what the address relaxed to.   Out: Any fixS:s and constants are set up.   The caller will turn the frag into a ".space 0".  */voidmd_convert_frag (abfd, sec, fragP)     bfd *abfd ATTRIBUTE_UNUSED;     segT sec ATTRIBUTE_UNUSED;     fragS *fragP;{  /* Pointer to first byte in variable-sized part of the frag.  */  char *var_partp;  /* Pointer to first opcode byte in frag.  */  char *opcodep;  /* Used to check integrity of the relaxation.     One of 2 = long, 1 = word, or 0 = byte.  */  int length_code;  /* Size in bytes of variable-sized part of frag.  */  int var_part_size = 0;  /* This is part of *fragP.  It contains all information about addresses

⌨️ 快捷键说明

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