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

📄 mips.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (type == DELAY_LOAD || type == DELAY_FCMP)    num_nops = 1;  else if (type == DELAY_HILO)    num_nops = 2;  else    num_nops = 0;  /* Make sure that we don't put nop's after labels.  */  next_insn = NEXT_INSN (cur_insn);  while (next_insn != 0 && GET_CODE (next_insn) == NOTE)    next_insn = NEXT_INSN (next_insn);  dslots_load_total += num_nops;  if (TARGET_DEBUG_F_MODE      || !optimize      || type == DELAY_NONE      || operands == 0      || cur_insn == 0      || next_insn == 0      || GET_CODE (next_insn) == CODE_LABEL      || (set_reg = operands[0]) == 0)    {      dslots_number_nops = 0;      mips_load_reg  = 0;      mips_load_reg2 = 0;      mips_load_reg3 = 0;      mips_load_reg4 = 0;      return ret;    }  set_reg = operands[0];  if (set_reg == 0)    return ret;  while (GET_CODE (set_reg) == SUBREG)    set_reg = SUBREG_REG (set_reg);  mode = GET_MODE (set_reg);  dslots_number_nops = num_nops;  mips_load_reg = set_reg;  if (GET_MODE_SIZE (mode)      > (unsigned) (FP_REG_P (REGNO (set_reg)) ? UNITS_PER_FPREG : UNITS_PER_WORD))    mips_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);  else    mips_load_reg2 = 0;  if (type == DELAY_HILO)    {      mips_load_reg3 = gen_rtx_REG (SImode, MD_REG_FIRST);      mips_load_reg4 = gen_rtx_REG (SImode, MD_REG_FIRST+1);    }  else    {      mips_load_reg3 = 0;      mips_load_reg4 = 0;    }  return ret;}/* Determine whether a memory reference takes one (based off of the GP   pointer), two (normal), or three (label + reg) instructions, and bump the   appropriate counter for -mstats.  */voidmips_count_memory_refs (op, num)     rtx op;     int num;{  int additional = 0;  int n_words = 0;  rtx addr, plus0, plus1;  enum rtx_code code0, code1;  int looping;  if (TARGET_DEBUG_B_MODE)    {      fprintf (stderr, "\n========== mips_count_memory_refs:\n");      debug_rtx (op);    }  /* Skip MEM if passed, otherwise handle movsi of address.  */  addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);  /* Loop, going through the address RTL.  */  do    {      looping = FALSE;      switch (GET_CODE (addr))	{	case REG:	case CONST_INT:	case LO_SUM:	  break;	case PLUS:	  plus0 = XEXP (addr, 0);	  plus1 = XEXP (addr, 1);	  code0 = GET_CODE (plus0);	  code1 = GET_CODE (plus1);	  if (code0 == REG)	    {	      additional++;	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code0 == CONST_INT)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code1 == REG)	    {	      additional++;	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == CONST_INT)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  break;	case LABEL_REF:	  n_words = 2;		/* always 2 words */	  break;	case CONST:	  addr = XEXP (addr, 0);	  looping = 1;	  continue;	case SYMBOL_REF:	  n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;	  break;	default:	  break;	}    }  while (looping);  if (n_words == 0)    return;  n_words += additional;  if (n_words > 3)    n_words = 3;  num_refs[n_words-1] += num;}/* Return a pseudo that points to the address of the current function.   The first time it is called for a function, an initializer for the   pseudo is emitted in the beginning of the function.  */rtxembedded_pic_fnaddr_reg (){  if (cfun->machine->embedded_pic_fnaddr_rtx == NULL)    {      rtx seq;      cfun->machine->embedded_pic_fnaddr_rtx = gen_reg_rtx (Pmode);      /* Output code at function start to initialize the pseudo-reg.  */      /* ??? We used to do this in FINALIZE_PIC, but that does not work for	 inline functions, because it is called after RTL for the function	 has been copied.  The pseudo-reg in embedded_pic_fnaddr_rtx however	 does not get copied, and ends up not matching the rest of the RTL.	 This solution works, but means that we get unnecessary code to	 initialize this value every time a function is inlined into another	 function.  */      start_sequence ();      emit_insn (gen_get_fnaddr (cfun->machine->embedded_pic_fnaddr_rtx,				 XEXP (DECL_RTL (current_function_decl), 0)));      seq = get_insns ();      end_sequence ();      push_topmost_sequence ();      emit_insn_after (seq, get_insns ());      pop_topmost_sequence ();    }  return cfun->machine->embedded_pic_fnaddr_rtx;}/* Return RTL for the offset from the current function to the argument.   X is the symbol whose offset from the current function we want.  */rtxembedded_pic_offset (x)     rtx x;{  /* Make sure it is emitted.  */  embedded_pic_fnaddr_reg ();  return    gen_rtx_CONST (Pmode,		   gen_rtx_MINUS (Pmode, x,				  XEXP (DECL_RTL (current_function_decl), 0)));}/* Return the appropriate instructions to move one operand to another.  */const char *mips_move_1word (operands, insn, unsignedp)     rtx operands[];     rtx insn;     int unsignedp;{  const char *ret = 0;  rtx op0 = operands[0];  rtx op1 = operands[1];  enum rtx_code code0 = GET_CODE (op0);  enum rtx_code code1 = GET_CODE (op1);  enum machine_mode mode = GET_MODE (op0);  int subreg_offset0 = 0;  int subreg_offset1 = 0;  enum delay_type delay = DELAY_NONE;  while (code0 == SUBREG)    {      subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),					     GET_MODE (SUBREG_REG (op0)),					     SUBREG_BYTE (op0),					     GET_MODE (op0));      op0 = SUBREG_REG (op0);      code0 = GET_CODE (op0);    }  while (code1 == SUBREG)    {      subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),					     GET_MODE (SUBREG_REG (op1)),					     SUBREG_BYTE (op1),					     GET_MODE (op1));      op1 = SUBREG_REG (op1);      code1 = GET_CODE (op1);    }  /* For our purposes, a condition code mode is the same as SImode.  */  if (mode == CCmode)    mode = SImode;  if (code0 == REG)    {      int regno0 = REGNO (op0) + subreg_offset0;      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_offset1;	  /* Just in case, don't do anything for assigning a register	     to itself, unless we are filling a delay slot.  */	  if (regno0 == regno1 && set_nomacro == 0)	    ret = "";	  else if (GP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		ret = "move\t%0,%1";	      else if (MD_REG_P (regno1))		{		  delay = DELAY_HILO;		  if (regno1 != HILO_REGNUM)		    ret = "mf%1\t%0";		  else		    ret = "mflo\t%0";		}	      else if (ST_REG_P (regno1) && ISA_HAS_8CC)		ret = "li\t%0,1\n\tmovf\t%0,%.,%1";	      else		{		  delay = DELAY_LOAD;		  if (FP_REG_P (regno1))		    ret = "mfc1\t%0,%1";		  else if (ALL_COP_REG_P (regno1))		    {		      static char retval[] = "mfc_\t%0,%1";		      retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (regno1);		      ret = retval;		    }		  else if (regno1 == FPSW_REGNUM && ! ISA_HAS_8CC)		    ret = "cfc1\t%0,$31";		}	    }	  else if (FP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_LOAD;		  ret = "mtc1\t%1,%0";		}	      if (FP_REG_P (regno1))		ret = "mov.s\t%0,%1";	    }	  else if (MD_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_HILO;		  if (regno0 != HILO_REGNUM && ! TARGET_MIPS16)		    ret = "mt%0\t%1";		}	    }	  else if (regno0 == FPSW_REGNUM && ! ISA_HAS_8CC)	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_LOAD;		  ret = "ctc1\t%0,$31";		}	    }	  else if (ALL_COP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		{		  static char retval[] = "mtc_\t%1,%0";		  char cop = COPNUM_AS_CHAR_FROM_REGNUM (regno0);		  if (cop == '0')		    abort_with_insn (insn,				     "mtc0 not supported; it disturbs virtual address translation");		  delay = DELAY_LOAD;		  retval[3] = cop;		  ret = retval;		}	    }	}      else if (code1 == MEM)	{	  delay = DELAY_LOAD;	  if (TARGET_STATS)	    mips_count_memory_refs (op1, 1);	  if (GP_REG_P (regno0))	    {	      /* For loads, use the mode of the memory item, instead of the		 target, so zero/sign extend can use this code as well.  */	      switch (GET_MODE (op1))		{		default:		  break;		case SFmode:		  ret = "lw\t%0,%1";		  break;		case SImode:		case CCmode:		  ret = ((unsignedp && TARGET_64BIT)			 ? "lwu\t%0,%1"			 : "lw\t%0,%1");		  break;		case HImode:		  ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";		  break;		case QImode:		  ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";		  break;		}	    }	  else if (FP_REG_P (regno0) && (mode == SImode || mode == SFmode))	    ret = "l.s\t%0,%1";	  else if (ALL_COP_REG_P (regno0))	    {	      static char retval[] = "lwc_\t%0,%1";	      char cop = COPNUM_AS_CHAR_FROM_REGNUM (regno0);	      if (cop == '0')		abort_with_insn (insn,				 "loads from memory to COP0 are illegal");	      delay = DELAY_LOAD;	      retval[3] = cop;	      ret = retval;	    }	  if (ret != (char *)0 && MEM_VOLATILE_P (op1))	    {	      size_t i = strlen (ret);	      if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))		abort ();	      sprintf (volatile_buffer, "%%{%s%%}", ret);	      ret = volatile_buffer;	    }	}      else if (code1 == CONST_INT	       || (code1 == CONST_DOUBLE		   && GET_MODE (op1) == VOIDmode))	{	  if (code1 == CONST_DOUBLE)	    {	      /* This can happen when storing constants into long long                 bitfields.  Just store the least significant word of                 the value.  */	      operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));	    }	  if (INTVAL (op1) == 0 && ! TARGET_MIPS16)	    {	      if (GP_REG_P (regno0))		ret = "move\t%0,%z1";	      else if (FP_REG_P (regno0))		{		  delay = DELAY_LOAD;		  ret = "mtc1\t%z1,%0";		}	      else if (MD_REG_P (regno0))		{		

⌨️ 快捷键说明

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