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

📄 tc-mips.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
static char *insn_error;static int auto_align = 1;/* When outputting SVR4 PIC code, the assembler needs to know the   offset in the stack frame from which to restore the $gp register.   This is set by the .cprestore pseudo-op, and saved in this   variable.  */static offsetT mips_cprestore_offset = -1;/* This is the register which holds the stack frame, as set by the   .frame pseudo-op.  This is needed to implement .cprestore.  */static int mips_frame_reg = SP;/* To output NOP instructions correctly, we need to keep information   about the previous two instructions.  *//* Whether we are optimizing.  The default value of 2 means to remove   unneeded NOPs and swap branch instructions when possible.  A value   of 1 means to not swap branches.  A value of 0 means to always   insert NOPs.  */static int mips_optimize = 2;/* Debugging level.  -g sets this to 2.  -gN sets this to N.  -g0 is   equivalent to seeing no -g option at all.  */static int mips_debug = 0;/* The previous instruction.  */static struct mips_cl_insn prev_insn;/* The instruction before prev_insn.  */static struct mips_cl_insn prev_prev_insn;/* If we don't want information for prev_insn or prev_prev_insn, we   point the insn_mo field at this dummy integer.  */static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0 };/* Non-zero if prev_insn is valid.  */static int prev_insn_valid;/* The frag for the previous instruction.  */static struct frag *prev_insn_frag;/* The offset into prev_insn_frag for the previous instruction.  */static long prev_insn_where;/* The reloc type for the previous instruction, if any.  */static bfd_reloc_code_real_type prev_insn_reloc_type;/* The reloc for the previous instruction, if any.  */static fixS *prev_insn_fixp;/* Non-zero if the previous instruction was in a delay slot.  */static int prev_insn_is_delay_slot;/* Non-zero if the previous instruction was in a .set noreorder.  */static int prev_insn_unreordered;/* Non-zero if the previous instruction uses an extend opcode (if   mips16).  */static int prev_insn_extended;/* Non-zero if the previous previous instruction was in a .set   noreorder.  */static int prev_prev_insn_unreordered;/* If this is set, it points to a frag holding nop instructions which   were inserted before the start of a noreorder section.  If those   nops turn out to be unnecessary, the size of the frag can be   decreased.  */static fragS *prev_nop_frag;/* The number of nop instructions we created in prev_nop_frag.  */static int prev_nop_frag_holds;/* The number of nop instructions that we know we need in   prev_nop_frag.  */static int prev_nop_frag_required;/* The number of instructions we've seen since prev_nop_frag.  */static int prev_nop_frag_since;/* For ECOFF and ELF, relocations against symbols are done in two   parts, with a HI relocation and a LO relocation.  Each relocation   has only 16 bits of space to store an addend.  This means that in   order for the linker to handle carries correctly, it must be able   to locate both the HI and the LO relocation.  This means that the   relocations must appear in order in the relocation table.   In order to implement this, we keep track of each unmatched HI   relocation.  We then sort them so that they immediately precede the   corresponding LO relocation.  */struct mips_hi_fixup{  /* Next HI fixup.  */  struct mips_hi_fixup *next;  /* This fixup.  */  fixS *fixp;  /* The section this fixup is in.  */  segT seg;};/* The list of unmatched HI relocs.  */static struct mips_hi_fixup *mips_hi_fixup_list;/* Map normal MIPS register numbers to mips16 register numbers.  */#define X ILLEGAL_REGstatic const int mips32_to_16_reg_map[] ={  X, X, 2, 3, 4, 5, 6, 7,  X, X, X, X, X, X, X, X,  0, 1, X, X, X, X, X, X,  X, X, X, X, X, X, X, X};#undef X/* Map mips16 register numbers to normal MIPS register numbers.  */static const unsigned int mips16_to_32_reg_map[] ={  16, 17, 2, 3, 4, 5, 6, 7};/* Since the MIPS does not have multiple forms of PC relative   instructions, we do not have to do relaxing as is done on other   platforms.  However, we do have to handle GP relative addressing   correctly, which turns out to be a similar problem.   Every macro that refers to a symbol can occur in (at least) two   forms, one with GP relative addressing and one without.  For   example, loading a global variable into a register generally uses   a macro instruction like this:     lw $4,i   If i can be addressed off the GP register (this is true if it is in   the .sbss or .sdata section, or if it is known to be smaller than   the -G argument) this will generate the following instruction:     lw $4,i($gp)   This instruction will use a GPREL reloc.  If i can not be addressed   off the GP register, the following instruction sequence will be used:     lui $at,i     lw $4,i($at)   In this case the first instruction will have a HI16 reloc, and the   second reloc will have a LO16 reloc.  Both relocs will be against   the symbol i.   The issue here is that we may not know whether i is GP addressable   until after we see the instruction that uses it.  Therefore, we   want to be able to choose the final instruction sequence only at   the end of the assembly.  This is similar to the way other   platforms choose the size of a PC relative instruction only at the   end of assembly.   When generating position independent code we do not use GP   addressing in quite the same way, but the issue still arises as   external symbols and local symbols must be handled differently.   We handle these issues by actually generating both possible   instruction sequences.  The longer one is put in a frag_var with   type rs_machine_dependent.  We encode what to do with the frag in   the subtype field.  We encode (1) the number of existing bytes to   replace, (2) the number of new bytes to use, (3) the offset from   the start of the existing bytes to the first reloc we must generate   (that is, the offset is applied from the start of the existing   bytes after they are replaced by the new bytes, if any), (4) the   offset from the start of the existing bytes to the second reloc,   (5) whether a third reloc is needed (the third reloc is always four   bytes after the second reloc), and (6) whether to warn if this   variant is used (this is sometimes needed if .set nomacro or .set   noat is in effect).  All these numbers are reasonably small.   Generating two instruction sequences must be handled carefully to   ensure that delay slots are handled correctly.  Fortunately, there   are a limited number of cases.  When the second instruction   sequence is generated, append_insn is directed to maintain the   existing delay slot information, so it continues to apply to any   code after the second instruction sequence.  This means that the   second instruction sequence must not impose any requirements not   required by the first instruction sequence.   These variant frags are then handled in functions called by the   machine independent code.  md_estimate_size_before_relax returns   the final size of the frag.  md_convert_frag sets up the final form   of the frag.  tc_gen_reloc adjust the first reloc and adds a second   one if needed.  */#define RELAX_ENCODE(old, new, reloc1, reloc2, reloc3, warn) \  ((relax_substateT) \   (((old) << 23) \    | ((new) << 16) \    | (((reloc1) + 64) << 9) \    | (((reloc2) + 64) << 2) \    | ((reloc3) ? (1 << 1) : 0) \    | ((warn) ? 1 : 0)))#define RELAX_OLD(i) (((i) >> 23) & 0x7f)#define RELAX_NEW(i) (((i) >> 16) & 0x7f)#define RELAX_RELOC1(i) ((bfd_vma) (((i) >> 9) & 0x7f) - 64)#define RELAX_RELOC2(i) ((bfd_vma) (((i) >> 2) & 0x7f) - 64)#define RELAX_RELOC3(i) (((i) >> 1) & 1)#define RELAX_WARN(i) ((i) & 1)/* For mips16 code, we use an entirely different form of relaxation.   mips16 supports two versions of most instructions which take   immediate values: a small one which takes some small value, and a   larger one which takes a 16 bit value.  Since branches also follow   this pattern, relaxing these values is required.   We can assemble both mips16 and normal MIPS code in a single   object.  Therefore, we need to support this type of relaxation at   the same time that we support the relaxation described above.  We   use the high bit of the subtype field to distinguish these cases.   The information we store for this type of relaxation is the   argument code found in the opcode file for this relocation, whether   the user explicitly requested a small or extended form, and whether   the relocation is in a jump or jal delay slot.  That tells us the   size of the value, and how it should be stored.  We also store   whether the fragment is considered to be extended or not.  We also   store whether this is known to be a branch to a different section,   whether we have tried to relax this frag yet, and whether we have   ever extended a PC relative fragment because of a shift count.  */#define RELAX_MIPS16_ENCODE(type, small, ext, dslot, jal_dslot)	\  (0x80000000							\   | ((type) & 0xff)						\   | ((small) ? 0x100 : 0)					\   | ((ext) ? 0x200 : 0)					\   | ((dslot) ? 0x400 : 0)					\   | ((jal_dslot) ? 0x800 : 0))#define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)#define RELAX_MIPS16_TYPE(i) ((i) & 0xff)#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)#define RELAX_MIPS16_DSLOT(i) (((i) & 0x400) != 0)#define RELAX_MIPS16_JAL_DSLOT(i) (((i) & 0x800) != 0)#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x1000) != 0)#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x1000)#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x1000)#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x2000) != 0)#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x2000)#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x2000)/* Prototypes for static functions.  */#ifdef __STDC__#define internalError() \    as_fatal (_("internal Error, line %d, %s"), __LINE__, __FILE__)#else#define internalError() as_fatal (_("MIPS internal Error"));#endifenum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };static int insn_uses_reg PARAMS ((struct mips_cl_insn *ip,				  unsigned int reg, enum mips_regclass class));static int reg_needs_delay PARAMS ((unsigned int));static void mips16_mark_labels PARAMS ((void));static void append_insn PARAMS ((char *place,				 struct mips_cl_insn * ip,				 expressionS * p,				 bfd_reloc_code_real_type r,				 boolean));static void mips_no_prev_insn PARAMS ((int));static void mips_emit_delays PARAMS ((boolean));#ifdef USE_STDARGstatic void macro_build PARAMS ((char *place, int *counter, expressionS * ep,				 const char *name, const char *fmt,				 ...));#elsestatic void macro_build ();#endifstatic void mips16_macro_build PARAMS ((char *, int *, expressionS *,					const char *, const char *,					va_list));static void macro_build_lui PARAMS ((char *place, int *counter,				     expressionS * ep, int regnum));static void set_at PARAMS ((int *counter, int reg, int unsignedp));static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip,					 expressionS *));static void load_register PARAMS ((int *, int, expressionS *, int));static void load_address PARAMS ((int *counter, int reg, expressionS *ep));static void macro PARAMS ((struct mips_cl_insn * ip));static void mips16_macro PARAMS ((struct mips_cl_insn * ip));#ifdef LOSING_COMPILERstatic void macro2 PARAMS ((struct mips_cl_insn * ip));#endifstatic void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip));static void mips16_ip PARAMS ((char *str, struct mips_cl_insn * ip));static void mips16_immed PARAMS ((char *, unsigned int, int, offsetT, boolean,				  boolean, boolean, unsigned long *,				  boolean *, unsigned short *));static int my_getSmallExpression PARAMS ((expressionS * ep, char *str));static void my_getExpression PARAMS ((expressionS * ep, char *str));static symbolS *get_symbol PARAMS ((void));static void mips_align PARAMS ((int to, int fill, symbolS *label));static void s_align PARAMS ((int));static void s_change_sec PARAMS ((int));static void s_cons PARAMS ((int));static void s_float_cons PARAMS ((int));static void s_mips_globl PARAMS ((int));static void s_option PARAMS ((int));static void s_mipsset PARAMS ((int));static void s_abicalls PARAMS ((int));static void s_cpload PARAMS ((int));static void s_cprestore PARAMS ((int));static void s_gpword PARAMS ((int));static void s_cpadd PARAMS ((int));static void s_insn PARAMS ((int));static void md_obj_begin PARAMS ((void));static void md_obj_end PARAMS ((void));static long get_number PARAMS ((void));static void s_mips_ent PARAMS ((int));static void s_mips_end PARAMS ((int));static void s_mips_frame PARAMS ((int));static void s_mips_mask PARAMS ((int));static void s_mips_stab PARAMS ((int));static void s_mips_weakext PARAMS ((int));static void s_file PARAMS ((int));static int mips16_extended_frag PARAMS ((fragS *, asection *, long));static const char *mips_isa_to_str PARAMS ((int));static const char *mips_cpu_to_str PARAMS ((int));static int validate_mips_insn PARAMS ((const struct mips_opcode *));/* Table and functions used to map between CPU/ISA names, and   ISA levels, and CPU numbers.  */struct mips_cpu_info{  const char *name;           /* CPU or ISA name.  */  int is_isa;                 /* Is this an ISA?  (If 0, a CPU.) */  int isa;                    /* ISA level.  */  int cpu;                    /* CPU number (default CPU if ISA).  */};static const struct mips_cpu_info *mips_cpu_info_from_name PARAMS ((const char *));static const struct mips_cpu_info *mips_cpu_info_from_isa PARAMS ((int));static const struct mips_cpu_info *mips_cpu_info_from_cpu PARAMS ((int));/* Pseudo-op table.   The following pseudo-ops from the Kane and Heinrich MIPS book   should be defined here, but are currently unsupported: .alias,   .galive, .gjaldef, .gjrlive, .livereg, .noalias.   The following pseudo-ops from the Kane and Heinrich MIPS book are   specific to the type of debugging information being generated, and   should be defined by the object format: .aent, .begin, .bend,   .bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,   .vreg.   The following pseudo-ops from the Kane and Heinrich MIPS book are   not MIPS CPU specific, but are also not specific to the object file   format.  This file is probably the best place to define them, but   they are not currently supported: .asm0, .endr, .lab, .repeat,   .struct.  */static const pseudo_typeS mips_pseudo_table[] ={  /* MIPS specific pseudo-ops.  */  {"option", s_option, 0},  {"set", s_mipsset, 0},  {"rdata", s_change_sec, 'r'},  {"sdata", s_change_sec, 's'},  {"livereg", s_ignore, 0},  {"abicalls", s_abicalls, 0},  {"cpload", s_cpload, 0},  {"cprestore", s_cprestore, 0},  {"gpword", s_gpword, 0},  {"cpadd", s_cpadd, 0},  {"insn", s_insn, 0},  /* Relatively generic pseudo-ops that happen to be used on MIPS     chips.  */  {"asciiz", stringer, 1},  {"bss", s_change_sec, 'b'},  {"err", s_err, 0},  {"half", s_cons, 1},  {"dword", s_cons, 3},  {"weakext", s_mips_weakext, 0},  /* These pseudo-ops are defined in read.c, but must be overridden     here for one reason or another.  */  {"align", s_align, 0},  {"byte", s_cons, 0},  {"data", s_change_sec, 'd'},  {"double", s_float_cons, 'd'},  {"float", s_float_cons, 'f'},  {"globl", s_mips_globl, 0},  {"global", s_mips_globl, 0},  {"hword", s_cons, 1},  {"int", s_cons, 2},  {"long", s_cons, 2},  {"octa", s_cons, 4},  {"quad", s_cons, 3},  {"short", s_cons, 1},  {"single", s_float_cons, 'f'},

⌨️ 快捷键说明

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