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

📄 i960.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	}      else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)	{	  constant = XEXP (XEXP (XEXP (x, 0), 1), 1);	  other = XEXP (x, 1);	}      else	constant = 0;      if (constant)	x = gen_rtx (PLUS, Pmode,		     gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),			      XEXP (XEXP (XEXP (x, 0), 1), 0)),		     plus_constant (other, INTVAL (constant)));    }  return x;}#if 0/* Return the most stringent alignment that we are willing to consider   objects of size SIZE and known alignment ALIGN as having. */   inti960_alignment (size, align)     int size;     int align;{  int i;  if (! TARGET_STRICT_ALIGN)    if (TARGET_IC_COMPAT2_0 || align >= 4)      {	i = i960_object_bytes_bitalign (size) / BITS_PER_UNIT;	if (i > align)	  align = i;      }  return align;}#endif/* Modes for condition codes.  */#define C_MODES		\  ((1 << (int) CCmode) | (1 << (int) CC_UNSmode) | (1<< (int) CC_CHKmode))/* Modes for single-word (and smaller) quantities.  */#define S_MODES						\ (~C_MODES						\  & ~ ((1 << (int) DImode) | (1 << (int) TImode)	\       | (1 << (int) DFmode) | (1 << (int) TFmode)))/* Modes for double-word (and smaller) quantities.  */#define D_MODES					\  (~C_MODES					\   & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))/* Modes for quad-word quantities.  */#define T_MODES (~C_MODES)/* Modes for single-float quantities.  */#define SF_MODES ((1 << (int) SFmode))/* Modes for double-float quantities.  */#define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))/* Modes for quad-float quantities.  */#define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))unsigned int hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = {  T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  TF_MODES, TF_MODES, TF_MODES, TF_MODES, C_MODES};/* Return the minimum alignment of an expression rtx X in bytes.  This takes   advantage of machine specific facts, such as knowing that the frame pointer   is always 16 byte aligned.  */inti960_expr_alignment (x, size)     rtx x;     int size;{  int align = 1;  if (x == 0)    return 1;  switch (GET_CODE(x))    {    case CONST_INT:      align = INTVAL(x);      if ((align & 0xf) == 0)	align = 16;      else if ((align & 0x7) == 0)	align = 8;      else if ((align & 0x3) == 0)	align = 4;      else if ((align & 0x1) == 0)	align = 2;      else	align = 1;      break;    case PLUS:      align = MIN (i960_expr_alignment (XEXP (x, 0), size),		   i960_expr_alignment (XEXP (x, 1), size));      break;    case SYMBOL_REF:      /* If this is a valid program, objects are guaranteed to be	 correctly aligned for whatever size the reference actually is. */      align = i960_object_bytes_bitalign (size) / BITS_PER_UNIT;      break;    case REG:      if (REGNO (x) == FRAME_POINTER_REGNUM)	align = 16;      break;    case ASHIFT:    case LSHIFT:      align = i960_expr_alignment (XEXP (x, 0));      if (GET_CODE (XEXP (x, 1)) == CONST_INT)	{	  align = align << INTVAL (XEXP (x, 1));	  align = MIN (align, 16);	}      break;    case MULT:      align = (i960_expr_alignment (XEXP (x, 0), size) *	       i960_expr_alignment (XEXP (x, 1), size));      align = MIN (align, 16);      break;    }  return align;}/* Return true if it is possible to reference both BASE and OFFSET, which   have alignment at least as great as 4 byte, as if they had alignment valid   for an object of size SIZE.  */inti960_improve_align (base, offset, size)     rtx base;     rtx offset;     int size;{  int i, j;  /* We have at least a word reference to the object, so we know it has to     be aligned at least to 4 bytes.  */  i = MIN (i960_expr_alignment (base, 4),	   i960_expr_alignment (offset, 4));  i = MAX (i, 4);  /* We know the size of the request.  If strict align is not enabled, we     can guess that the alignment is OK for the requested size.  */  if (! TARGET_STRICT_ALIGN)    if ((j = (i960_object_bytes_bitalign (size) / BITS_PER_UNIT)) > i)      i = j;  return (i >= size);}/* Return true if it is possible to access BASE and OFFSET, which have 4 byte   (SImode) alignment as if they had 16 byte (TImode) alignment.  */inti960_si_ti (base, offset)     rtx base;     rtx offset;{  return i960_improve_align (base, offset, 16);}/* Return true if it is possible to access BASE and OFFSET, which have 4 byte   (SImode) alignment as if they had 8 byte (DImode) alignment.  */inti960_si_di (base, offset)     rtx base;     rtx offset;{  return i960_improve_align (base, offset, 8);}/* Return raw values of size and alignment (in words) for the data   type being accessed.  These values will be rounded by the caller.  */static void i960_arg_size_and_align (mode, type, size_out, align_out)     enum machine_mode mode;     tree type;     int *size_out;     int *align_out;{  int size, align;  /* Use formal alignment requirements of type being passed, except make     it at least a word.  If we don't have a type, this is a library call,     and the parm has to be of scalar type.  In this case, consider its     formal alignment requirement to be its size in words.  */  if (mode == BLKmode)    size = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  else if (mode == VOIDmode)    {      /* End of parm list.  */      assert (type != 0 && TYPE_MODE (type) == VOIDmode);      size = 1;    }  else    size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  if (type == 0)    align = size;  else if (TYPE_ALIGN (type) >= BITS_PER_WORD)    align = TYPE_ALIGN (type) / BITS_PER_WORD;  else    align = 1;  *size_out  = size;  *align_out = align;}/* On the 80960 the first 12 args are in registers and the rest are pushed.   Any arg that is bigger than 4 words is placed on the stack and all   subsequent arguments are placed on the stack.   Additionally, parameters with an alignment requirement stronger than   a word must be be aligned appropriately.  *//* Update CUM to advance past an argument described by MODE and TYPE.  */voidi960_function_arg_advance (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  int size, align;  i960_arg_size_and_align (mode, type, &size, &align);  if (named == 0 || size > 4 || cum->ca_nstackparms != 0      || (size + ROUND (cum->ca_nregparms, align)) > NPARM_REGS      || MUST_PASS_IN_STACK (mode, type))    cum->ca_nstackparms = ROUND (cum->ca_nstackparms, align) + size;  else    cum->ca_nregparms = ROUND (cum->ca_nregparms, align) + size;}/* Return the register that the argument described by MODE and TYPE is   passed in, or else return 0 if it is passed on the stack.  */rtxi960_function_arg (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  rtx ret;  int size, align;  i960_arg_size_and_align (mode, type, &size, &align);  if (named == 0 || size > 4 || cum->ca_nstackparms != 0      || (size + ROUND (cum->ca_nregparms, align)) > NPARM_REGS      || MUST_PASS_IN_STACK (mode, type))    {      cum->ca_nstackparms = ROUND (cum->ca_nstackparms, align);      ret = 0;    }  else    {      cum->ca_nregparms = ROUND (cum->ca_nregparms, align);      ret = gen_rtx (REG, mode, cum->ca_nregparms);    }  return ret;}/* Floating-point support.  */voidi960_output_double (file, value)     FILE *file;     double value;{  if (REAL_VALUE_ISINF (value))    {      fprintf (file, "\t.word	0\n");      fprintf (file, "\t.word	0x7ff00000	# Infinity\n");    }  else    fprintf (file, "\t.double 0d%.17e\n", (value));}voidi960_output_float (file, value)     FILE *file;     double value;{  if (REAL_VALUE_ISINF (value))    fprintf (file, "\t.word	0x7f800000	# Infinity\n");  else    fprintf (file, "\t.float 0f%.12e\n", (value));}/* Return the number of bits that an object of size N bytes is aligned to.  */inti960_object_bytes_bitalign (n)     int n;{  if (n > 8)      n = 128;  else if (n > 4) n = 64;  else if (n > 2) n = 32;  else if (n > 1) n = 16;  else            n = 8;  return n;}/* Compute the size of an aggregate type TSIZE.  */treei960_round_size (tsize)     tree tsize;{  int size, byte_size, align;  if (TREE_CODE (tsize) != INTEGER_CST)    return tsize;  size = TREE_INT_CST_LOW (tsize);  byte_size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;  align = i960_object_bytes_bitalign (byte_size);  /* Handle #pragma align.  */  if (align > i960_maxbitalignment)    align = i960_maxbitalignment;  if (size % align)    size = ((size / align) + 1) * align;  return size_int (size);}/* Compute the alignment for an aggregate type TSIZE.  */inti960_round_align (align, tsize)     int align;     tree tsize;{  int byte_size;  if (TREE_CODE (tsize) != INTEGER_CST)    return align;  byte_size = (TREE_INT_CST_LOW (tsize) + BITS_PER_UNIT - 1) / BITS_PER_UNIT;  align = i960_object_bytes_bitalign (byte_size);  return align;}/* Do any needed setup for a varargs function.  For the i960, we must   create a register parameter block if one doesn't exist, and then copy   all register parameters to memory.  */voidi960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int *pretend_size;     int no_rtl;{  if (cum->ca_nregparms < NPARM_REGS)    {      int first_reg_offset = cum->ca_nregparms;      if (first_reg_offset > NPARM_REGS)	first_reg_offset = NPARM_REGS;      if (! (no_rtl) && first_reg_offset != NPARM_REGS)	{	  rtx label = gen_label_rtx ();	  emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx));	  emit_jump_insn (gen_bne (label));	  emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx,			      stack_pointer_rtx));	  emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx,			      memory_address (SImode,					      plus_constant (stack_pointer_rtx,							     48))));	  emit_label (label);	  move_block_from_reg	    (first_reg_offset,	     gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx),	     NPARM_REGS - first_reg_offset);	}      *pretend_size = (NPARM_REGS - first_reg_offset) * UNITS_PER_WORD;    }}/* Calculate the final size of the reg parm stack space for the current   function, based on how many bytes would be allocated on the stack.  */inti960_final_reg_parm_stack_space (const_size, var_size)     int const_size;     tree var_size;{  if (var_size || const_size > 48)    return 48;  else    return 0;}/* Calculate the size of the reg parm stack space.  This is a bit complicated   on the i960.  */inti960_reg_parm_stack_space (fndecl)     tree fndecl;{  /* In this case, we are called from emit_library_call, and we don't need     to pretend we have more space for parameters than what's apparent.  */  if (fndecl == 0)    return 0;  /* In this case, we are called from locate_and_pad_parms when we're     not IN_REGS, so we have an arg block.  */  if (fndecl != current_function_decl)    return 48;  /* Otherwise, we have an arg block if the current function has more than     48 bytes of parameters.  */  if (current_function_args_size != 0)    return 48;  else    return 0;}/* Return the register class of a scratch register needed to copy IN into   or out of a register in CLASS in MODE.  If it can be done directly,   NO_REGS is returned.  */enum reg_classsecondary_reload_class (class, mode, in)     enum reg_class class;     enum machine_mode mode;     rtx in;{  int regno = -1;  if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)    regno = true_regnum (in);  /* We can place anything into LOCAL_OR_GLOBAL_REGS and can put     LOCAL_OR_GLOBAL_REGS into anything.  */  if (class == LOCAL_OR_GLOBAL_REGS || class == LOCAL_REGS      || class == GLOBAL_REGS || (regno >= 0 && regno < 32))    return NO_REGS;  /* We can place any hard register, 0.0, and 1.0 into FP_REGS.  */  if (class == FP_REGS      && ((regno >= 0 && regno <= FIRST_PSEUDO_REGISTER)	  || in == CONST0_RTX (mode) || in == CONST1_RTX (mode)))    return NO_REGS;  return LOCAL_OR_GLOBAL_REGS;}/* Look at the opcode P, and set i96_last_insn_type to indicate which   function unit it executed on.  *//* ??? This would make more sense as an attribute.  */voidi960_scan_opcode (p)     char *p;{  switch (*p)    {    case 'a':    case 'd':    case 'e':    case 'm':    case 'n':    case 'o':    case 'r':      /* Ret is not actually of type REG, but it won't matter, because no	 insn will ever follow it.  */    case 'u':    case 'x':      i960_last_insn_type = I_TYPE_REG;      break;    case 'b':      if (p[1] == 'x' || p[3] == 'x')        i960_last_insn_type = I_TYPE_MEM;      i960_last_insn_type = I_TYPE_CTRL;      break;    case 'f':    case 't':      i960_last_insn_type = I_TYPE_CTRL;      break;    case 'c':      if (p[1] == 'a')	{	  if (p[4] == 'x')	    i960_last_insn_type = I_TYPE_MEM;	  else	    i960_last_insn_type = I_TYPE_CTRL;	}      else if (p[1] == 'm')	{	  if (p[3] == 'd')	    i960_last_insn_type = I_TYPE_REG;	  else if (p[4] == 'b' || p[4] == 'j')	    i960_last_insn_type = I_TYPE_CTRL;	  else	    i960_last_insn_type = I_TYPE_REG;	}      else        i960_last_insn_type = I_TYPE_REG;      break;    case 'l':      i960_last_insn_type = I_TYPE_MEM;      break;    case 's':      if (p[1] == 't')        i960_last_insn_type = I_TYPE_MEM;      else        i960_last_insn_type = I_TYPE_REG;      break;    }}

⌨️ 快捷键说明

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