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

📄 tc-mips.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
	  {	    sec = subseg_new (".mdebug", (subsegT) 0);	    (void) bfd_set_section_flags (stdoutput, sec,					  SEC_HAS_CONTENTS | SEC_READONLY);	    (void) bfd_set_section_alignment (stdoutput, sec, 2);	  }#ifdef MIPS_STABS_ELF	pdr_seg = subseg_new (".pdr", (subsegT) 0);	(void) bfd_set_section_flags (stdoutput, pdr_seg,			     SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);	(void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);#endif	subseg_set (seg, subseg);      }    }  if (! ECOFF_DEBUGGING)    md_obj_begin ();}voidmd_mips_end (){  if (! ECOFF_DEBUGGING)    md_obj_end ();}voidmd_assemble (str)     char *str;{  struct mips_cl_insn insn;  imm_expr.X_op = O_absent;  imm_reloc = BFD_RELOC_UNUSED;  imm_unmatched_hi = false;  offset_expr.X_op = O_absent;  offset_reloc = BFD_RELOC_UNUSED;  if (mips_opts.mips16)    mips16_ip (str, &insn);  else    {      mips_ip (str, &insn);      DBG ((_("returned from mips_ip(%s) insn_opcode = 0x%x\n"),	    str, insn.insn_opcode));    }  if (insn_error)    {      as_bad ("%s `%s'", insn_error, str);      return;    }  if (insn.insn_mo->pinfo == INSN_MACRO)    {      if (mips_opts.mips16)	mips16_macro (&insn);      else	macro (&insn);    }  else    {      if (imm_expr.X_op != O_absent)	append_insn ((char *) NULL, &insn, &imm_expr, imm_reloc,		     imm_unmatched_hi);      else if (offset_expr.X_op != O_absent)	append_insn ((char *) NULL, &insn, &offset_expr, offset_reloc, false);      else	append_insn ((char *) NULL, &insn, NULL, BFD_RELOC_UNUSED, false);    }}/* See whether instruction IP reads register REG.  CLASS is the type   of register.  */static intinsn_uses_reg (ip, reg, class)     struct mips_cl_insn *ip;     unsigned int reg;     enum mips_regclass class;{  if (class == MIPS16_REG)    {      assert (mips_opts.mips16);      reg = mips16_to_32_reg_map[reg];      class = MIPS_GR_REG;    }  /* Don't report on general register 0, since it never changes.  */  if (class == MIPS_GR_REG && reg == 0)    return 0;  if (class == MIPS_FP_REG)    {      assert (! mips_opts.mips16);      /* If we are called with either $f0 or $f1, we must check $f0.	 This is not optimal, because it will introduce an unnecessary	 NOP between "lwc1 $f0" and "swc1 $f1".  To fix this we would	 need to distinguish reading both $f0 and $f1 or just one of	 them.  Note that we don't have to check the other way,	 because there is no instruction that sets both $f0 and $f1	 and requires a delay.  */      if ((ip->insn_mo->pinfo & INSN_READ_FPR_S)	  && ((((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS) &~(unsigned)1)	      == (reg &~ (unsigned) 1)))	return 1;      if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)	  && ((((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT) &~(unsigned)1)	      == (reg &~ (unsigned) 1)))	return 1;    }  else if (! mips_opts.mips16)    {      if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)	  && ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS) == reg)	return 1;      if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)	  && ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT) == reg)	return 1;    }  else    {      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_X)	  && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RX)				    & MIPS16OP_MASK_RX)]	      == reg))	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Y)	  && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RY)				    & MIPS16OP_MASK_RY)]	      == reg))	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Z)	  && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_MOVE32Z)				    & MIPS16OP_MASK_MOVE32Z)]	      == reg))	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_T) && reg == TREG)	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_SP) && reg == SP)	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_31) && reg == RA)	return 1;      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_GPR_X)	  && ((ip->insn_opcode >> MIPS16OP_SH_REGR32)	      & MIPS16OP_MASK_REGR32) == reg)	return 1;    }  return 0;}/* This function returns true if modifying a register requires a   delay.  */static intreg_needs_delay (reg)     unsigned int reg;{  unsigned long prev_pinfo;  prev_pinfo = prev_insn.insn_mo->pinfo;  if (! mips_opts.noreorder      && ISA_HAS_COPROC_DELAYS (mips_opts.isa)      && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)	  || (! gpr_interlocks	      && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))    {      /* A load from a coprocessor or from memory.  All load	 delays delay the use of general register rt for one	 instruction on the r3000.  The r6000 and r4000 use	 interlocks.  */      /* Itbl support may require additional care here.  */      know (prev_pinfo & INSN_WRITE_GPR_T);      if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT))	return 1;    }  return 0;}/* Mark instruction labels in mips16 mode.  This permits the linker to   handle them specially, such as generating jalx instructions when   needed.  We also make them odd for the duration of the assembly, in   order to generate the right sort of code.  We will make them even   in the adjust_symtab routine, while leaving them marked.  This is   convenient for the debugger and the disassembler.  The linker knows   to make them odd again.  */static voidmips16_mark_labels (){  if (mips_opts.mips16)    {      struct insn_label_list *l;      valueT val;      for (l = insn_labels; l != NULL; l = l->next)	{#ifdef OBJ_ELF	  if (OUTPUT_FLAVOR == bfd_target_elf_flavour)	    S_SET_OTHER (l->label, STO_MIPS16);#endif	  val = S_GET_VALUE (l->label);	  if ((val & 1) == 0)	    S_SET_VALUE (l->label, val + 1);	}    }}/* Output an instruction.  PLACE is where to put the instruction; if   it is NULL, this uses frag_more to get room.  IP is the instruction   information.  ADDRESS_EXPR is an operand of the instruction to be   used with RELOC_TYPE.  */static voidappend_insn (place, ip, address_expr, reloc_type, unmatched_hi)     char *place;     struct mips_cl_insn *ip;     expressionS *address_expr;     bfd_reloc_code_real_type reloc_type;     boolean unmatched_hi;{  register unsigned long prev_pinfo, pinfo;  char *f;  fixS *fixp;  int nops = 0;  /* Mark instruction labels in mips16 mode.  */  if (mips_opts.mips16)    mips16_mark_labels ();  prev_pinfo = prev_insn.insn_mo->pinfo;  pinfo = ip->insn_mo->pinfo;  if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))    {      int prev_prev_nop;      /* If the previous insn required any delay slots, see if we need	 to insert a NOP or two.  There are eight kinds of possible	 hazards, of which an instruction can have at most one type.	 (1) a load from memory delay	 (2) a load from a coprocessor delay	 (3) an unconditional branch delay	 (4) a conditional branch delay	 (5) a move to coprocessor register delay	 (6) a load coprocessor register from memory delay	 (7) a coprocessor condition code delay	 (8) a HI/LO special register delay	 There are a lot of optimizations we could do that we don't.	 In particular, we do not, in general, reorder instructions.	 If you use gcc with optimization, it will reorder	 instructions and generally do much more optimization then we	 do here; repeating all that work in the assembler would only	 benefit hand written assembly code, and does not seem worth	 it.  */      /* This is how a NOP is emitted.  */#define emit_nop()					\  (mips_opts.mips16					\   ? md_number_to_chars (frag_more (2), 0x6500, 2)	\   : md_number_to_chars (frag_more (4), 0, 4))      /* The previous insn might require a delay slot, depending upon	 the contents of the current insn.  */      if (! mips_opts.mips16	  && ISA_HAS_COPROC_DELAYS (mips_opts.isa)	  && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)               && ! cop_interlocks)	      || (! gpr_interlocks		  && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))	{	  /* A load from a coprocessor or from memory.  All load	     delays delay the use of general register rt for one	     instruction on the r3000.  The r6000 and r4000 use	     interlocks.  */	  /* Itbl support may require additional care here.  */	  know (prev_pinfo & INSN_WRITE_GPR_T);	  if (mips_optimize == 0	      || insn_uses_reg (ip,				((prev_insn.insn_opcode >> OP_SH_RT)				 & OP_MASK_RT),				MIPS_GR_REG))	    ++nops;	}      else if (! mips_opts.mips16	       && ISA_HAS_COPROC_DELAYS (mips_opts.isa)	       && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)		    && ! cop_interlocks)		   || (mips_opts.isa == ISA_MIPS1		       && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))	{	  /* A generic coprocessor delay.  The previous instruction	     modified a coprocessor general or control register.  If	     it modified a control register, we need to avoid any	     coprocessor instruction (this is probably not always	     required, but it sometimes is).  If it modified a general	     register, we avoid using that register.	     On the r6000 and r4000 loading a coprocessor register	     from memory is interlocked, and does not require a delay.	     This case is not handled very well.  There is no special	     knowledge of CP0 handling, and the coprocessors other	     than the floating point unit are not distinguished at	     all.  */          /* Itbl support may require additional care here. FIXME!             Need to modify this to include knowledge about             user specified delays!  */	  if (prev_pinfo & INSN_WRITE_FPR_T)	    {	      if (mips_optimize == 0		  || insn_uses_reg (ip,				    ((prev_insn.insn_opcode >> OP_SH_FT)				     & OP_MASK_FT),				    MIPS_FP_REG))		++nops;	    }	  else if (prev_pinfo & INSN_WRITE_FPR_S)	    {	      if (mips_optimize == 0		  || insn_uses_reg (ip,				    ((prev_insn.insn_opcode >> OP_SH_FS)				     & OP_MASK_FS),				    MIPS_FP_REG))		++nops;	    }	  else	    {	      /* We don't know exactly what the previous instruction		 does.  If the current instruction uses a coprocessor		 register, we must insert a NOP.  If previous		 instruction may set the condition codes, and the		 current instruction uses them, we must insert two		 NOPS.  */              /* Itbl support may require additional care here.  */	      if (mips_optimize == 0		  || ((prev_pinfo & INSN_WRITE_COND_CODE)		      && (pinfo & INSN_READ_COND_CODE)))		nops += 2;	      else if (pinfo & INSN_COP)		++nops;	    }	}      else if (! mips_opts.mips16	       && ISA_HAS_COPROC_DELAYS (mips_opts.isa)	       && (prev_pinfo & INSN_WRITE_COND_CODE)               && ! cop_interlocks)	{	  /* The previous instruction sets the coprocessor condition	     codes, but does not require a general coprocessor delay	     (this means it is a floating point comparison	     instruction).  If this instruction uses the condition	     codes, we need to insert a single NOP.  */	  /* Itbl support may require additional care here.  */	  if (mips_optimize == 0	      || (pinfo & INSN_READ_COND_CODE))	    ++nops;	}      /* If we're fixing up mfhi/mflo for the r7000 and the	 previous insn was an mfhi/mflo and the current insn	 reads the register that the mfhi/mflo wrote to, then	 insert two nops.  */      else if (mips_7000_hilo_fix	       && MF_HILO_INSN (prev_pinfo)	       && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD)				      & OP_MASK_RD),				 MIPS_GR_REG))	{	  nops += 2;	}      /* If we're fixing up mfhi/mflo for the r7000 and the	 2nd previous insn was an mfhi/mflo and the current insn	 reads the register that the mfhi/mflo wrote to, then	 insert one nop.  */      else if (mips_7000_hilo_fix	       && MF_HILO_INSN (prev_prev_insn.insn_opcode)	       && insn_uses_reg (ip, ((prev_prev_insn.insn_opcode >> OP_SH_RD)                                       & OP_MASK_RD),                                    MIPS_GR_REG))	{	  nops += 1;	}      else if (prev_pinfo & INSN_READ_LO)	{

⌨️ 快捷键说明

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