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

📄 mmix.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
			  fold (build (GT_EXPR, sizetype,				       rounded_size,				       align)),			  size_zero_node,			  fold (build (MINUS_EXPR, sizetype,				       rounded_size,				       type_size))));	 tree addr_tree1	   = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,			  addend));	 /* If this type is larger than what fits in a register, then it	    is passed by reference.  */	 addr_tree	   = fold (build (COND_EXPR, TREE_TYPE (addr_tree1),			  fold (build (GT_EXPR, sizetype,				       rounded_size,				       ptr_size)),			  build1 (INDIRECT_REF, build_pointer_type (type),				  addr_tree1),			  addr_tree1));       }   }  addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);  addr = copy_to_reg (addr);  if (!integer_zerop (rounded_size))    {      /* Compute new value for AP.  For MMIX, it is always advanced by the	 size of a register.  */      tree t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,		      build (PLUS_EXPR, TREE_TYPE (valist), valist,			     ptr_size));      TREE_SIDE_EFFECTS (t) = 1;      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);    }  return addr;}/* TRAMPOLINE_SIZE.  *//* Four 4-byte insns plus two 8-byte values.  */int mmix_trampoline_size = 32;/* TRAMPOLINE_TEMPLATE.  */voidmmix_trampoline_template (stream)     FILE * stream;{  /* Read a value into the static-chain register and jump somewhere.  The     static chain is stored at offset 16, and the function address is     stored at offset 24.  */  /* FIXME: GCC copies this using *intsize* (tetra), when it should use     register size (octa).  */  fprintf (stream, "\tGETA $255,1F\n\t");  fprintf (stream, "LDOU %s,$255,0\n\t",	   reg_names[MMIX_STATIC_CHAIN_REGNUM]);  fprintf (stream, "LDOU $255,$255,8\n\t");  fprintf (stream, "GO $255,$255,0\n");  fprintf (stream, "1H\tOCTA 0\n\t");  fprintf (stream, "OCTA 0\n");}/* INITIALIZE_TRAMPOLINE.  *//* Set the static chain and function pointer field in the trampoline.   We also SYNCID here to be sure (doesn't matter in the simulator, but   some day it will).  */voidmmix_initialize_trampoline (trampaddr, fnaddr, static_chain)     rtx trampaddr;     rtx fnaddr;     rtx static_chain;{  emit_move_insn (gen_rtx_MEM (DImode, plus_constant (trampaddr, 16)),		  static_chain);  emit_move_insn (gen_rtx_MEM (DImode,			       plus_constant (trampaddr, 24)),		  fnaddr);  emit_insn (gen_sync_icache (validize_mem (gen_rtx_MEM (DImode,							 trampaddr)),			      GEN_INT (mmix_trampoline_size - 1)));}/* We must exclude constant addresses that have an increment that is not a   multiple of four bytes because of restrictions of the GETA   instruction, unless TARGET_BASE_ADDRESSES.  */intmmix_constant_address_p (x)     rtx x;{  RTX_CODE code = GET_CODE (x);  int addend = 0;  /* When using "base addresses", anything constant goes.  */  int constant_ok = TARGET_BASE_ADDRESSES != 0;  switch (code)    {    case LABEL_REF:    case SYMBOL_REF:      return 1;    case CONSTANT_P_RTX:    case HIGH:      /* FIXME: Don't know how to dissect these.  Avoid them for now,	 except we know they're constants.  */      return constant_ok;    case CONST_INT:      addend = INTVAL (x);      break;    case CONST_DOUBLE:      if (GET_MODE (x) != VOIDmode)	/* Strange that we got here.  FIXME: Check if we do.  */	return constant_ok;      addend = CONST_DOUBLE_LOW (x);      break;    case CONST:      /* Note that expressions with arithmetic on forward references don't	 work in mmixal.  People using gcc assembly code with mmixal might	 need to move arrays and such to before the point of use.  */      if (GET_CODE (XEXP (x, 0)) == PLUS)	{	  rtx x0 = XEXP (XEXP (x, 0), 0);	  rtx x1 = XEXP (XEXP (x, 0), 1);	  if ((GET_CODE (x0) == SYMBOL_REF	       || GET_CODE (x0) == LABEL_REF)	      && (GET_CODE (x1) == CONST_INT		  || (GET_CODE (x1) == CONST_DOUBLE		      && GET_MODE (x1) == VOIDmode)))	    addend = mmix_intval (x1);	  else	    return constant_ok;	}      else	return constant_ok;      break;    default:      return 0;    }  return constant_ok || (addend & 3) == 0;}/* Return 1 if the address is OK, otherwise 0.   Used by GO_IF_LEGITIMATE_ADDRESS.  */intmmix_legitimate_address (mode, x, strict_checking)     enum machine_mode mode ATTRIBUTE_UNUSED;     rtx x;     int strict_checking;{#define MMIX_REG_OK(X)							\  ((strict_checking							\    && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER				\	|| (reg_renumber[REGNO (X)] > 0					\	    && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER)))	\   || (!strict_checking							\       && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER			\	   || REGNO (X) >= FIRST_PSEUDO_REGISTER			\	   || REGNO (X) == ARG_POINTER_REGNUM)))  /* We only accept:     (mem reg)     (mem (plus reg reg))     (mem (plus reg 0..255)).     unless TARGET_BASE_ADDRESSES, in which case we accept all     (mem constant_address) too.  */    /* (mem reg) */  if (REG_P (x) && MMIX_REG_OK (x))    return 1;  if (GET_CODE(x) == PLUS)    {      rtx x1 = XEXP (x, 0);      rtx x2 = XEXP (x, 1);      /* Try swapping the order.  FIXME: Do we need this?  */      if (! REG_P (x1))	{	  rtx tem = x1;	  x1 = x2;	  x2 = tem;	}      /* (mem (plus (reg?) (?))) */      if (!REG_P (x1) || !MMIX_REG_OK (x1))	return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);      /* (mem (plus (reg) (reg?))) */      if (REG_P (x2) && MMIX_REG_OK (x2))	return 1;      /* (mem (plus (reg) (0..255?))) */      if (GET_CODE (x2) == CONST_INT	  && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))	return 1;      return 0;    }  return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);}/* LEGITIMATE_CONSTANT_P.  */intmmix_legitimate_constant_p (x)     rtx x;{  RTX_CODE code = GET_CODE (x);  /* We must allow any number due to the way the cse passes works; if we     do not allow any number here, general_operand will fail, and insns     will fatally fail recognition instead of "softly".  */  if (code == CONST_INT || code == CONST_DOUBLE)    return 1;  return CONSTANT_ADDRESS_P (x);}/* SELECT_CC_MODE.  */enum machine_modemmix_select_cc_mode (op, x, y)     RTX_CODE op;     rtx x;     rtx y ATTRIBUTE_UNUSED;{  /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to     output different compare insns.  Note that we do not check the     validity of the comparison here.  */  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)    {      if (op == ORDERED || op == UNORDERED || op == UNGE	  || op == UNGT || op == UNLE || op == UNLT)	return CC_FUNmode;      if (op == EQ || op == NE)	return CC_FPEQmode;      return CC_FPmode;    }  if (op == GTU || op == LTU || op == GEU || op == LEU)    return CC_UNSmode;  return CCmode;}/* REVERSIBLE_CC_MODE.  */intmmix_reversible_cc_mode (mode)     enum machine_mode mode;{  /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float     compares.  */  return mode != CC_FPmode;}/* DEFAULT_RTX_COSTS.  */intmmix_rtx_cost_recalculated (x, code, outer_code, costp)     rtx x ATTRIBUTE_UNUSED;     RTX_CODE code ATTRIBUTE_UNUSED;     RTX_CODE outer_code ATTRIBUTE_UNUSED;     int *costp ATTRIBUTE_UNUSED;{  /* For the time being, this is just a stub and we'll accept the     generic calculations, until we can do measurements, at least.     Say we did not modify any calculated costs.  */  return 0;}/* ADDRESS_COST.  */intmmix_address_cost (addr)     rtx addr ATTRIBUTE_UNUSED;{  /* There's no difference in the address costs and we have lots of     registers.  Some targets use constant 0, many others use 1 to say     this.  Let's start with 1.  */  return 1;}/* REGISTER_MOVE_COST.  */intmmix_register_move_cost (mode, from, to)     enum machine_mode mode ATTRIBUTE_UNUSED;     enum reg_class from;     enum reg_class to;{  return (from == GENERAL_REGS && from == to) ? 2 : 3;}/* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a   compile-time constant; it's used in an asm in crtstuff.c, compiled for   the target.  *//* DATA_SECTION_ASM_OP.  */const char *mmix_data_section_asm_op (){  return "\t.data ! mmixal:= 8H LOC 9B";}static voidmmix_encode_section_info (decl, first)     tree decl;     int first;{  /* Test for an external declaration, and do nothing if it is one.  */  if ((TREE_CODE (decl) == VAR_DECL       && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))      || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))    ;  else if (first && DECL_P (decl))    {      /* For non-visible declarations, add a "@" prefix, which we skip	 when the label is output.  If the label does not have this	 prefix, a ":" is output if -mtoplevel-symbols.	 Note that this does not work for data that is declared extern and	 later defined as static.  If there's code in between, that code	 will refer to the extern declaration, and vice versa.  This just	 means that when -mtoplevel-symbols is in use, we can just handle	 well-behaved ISO-compliant code.  */      const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);      int len = strlen (str);      char *newstr;      /* Why is the return type of ggc_alloc_string const?  */      newstr = (char *) ggc_alloc_string ("", len + 1);      strcpy (newstr + 1, str);      *newstr = '@';      XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;    }  /* Set SYMBOL_REF_FLAG for things that we want to access with GETA.  We     may need different options to reach for different things with GETA.     For now, functions and things we know or have been told are constant.  */  if (TREE_CODE (decl) == FUNCTION_DECL      || TREE_CONSTANT (decl)      || (TREE_CODE (decl) == VAR_DECL	  && TREE_READONLY (decl)	  && !TREE_SIDE_EFFECTS (decl)	  && (!DECL_INITIAL (decl)	      || TREE_CONSTANT (DECL_INITIAL (decl)))))    {      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'                 ? TREE_CST_RTL (decl) : DECL_RTL (decl));      SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;    }}static const char *mmix_strip_name_encoding (name)     const char *name;{  for (; (*name == '@' || *name == '*'); name++)    ;  return name;}/* ASM_FILE_START.  */voidmmix_asm_file_start (stream)     FILE * stream;{  /* We just emit a little comment for the time being.  FIXME: Perhaps add     -mstandalone and some segment and prefix setup here.  */  ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);  fprintf (stream, "! mmixal:= 8H LOC Data_Section\n");  /* Make sure each file starts with the text section. */  text_section ();}/* ASM_FILE_END.  */voidmmix_asm_file_end (stream)     FILE * stream ATTRIBUTE_UNUSED;{  /* Make sure each file ends with the data section. */  data_section ();}/* ASM_OUTPUT_SOURCE_FILENAME.  */voidmmix_asm_output_source_filename (stream, name)     FILE * stream;     const char * name;{  fprintf (stream, "# 1 ");  OUTPUT_QUOTED_STRING (stream, name);  fprintf (stream, "\n");}/* OUTPUT_QUOTED_STRING.  */voidmmix_output_quoted_string (stream, string, length)     FILE * stream;     const char * string;     int length;{  const char * string_end = string + length;  static const char *const unwanted_chars = "\"[]\\";  /* Output "any character except newline and double quote character".  We     play it safe and avoid all control characters too.  We also do not     want [] as characters, should input be passed through m4 with [] as     quotes.  Further, we avoid "\", because the GAS port handles it as a     quoting character.  */  while (string < string_end)    {      if (*string	  && (unsigned char) *string < 128	  && !ISCNTRL (*string)	  && strchr (unwanted_chars, *string) == NULL)	{	  fputc ('"', stream);	  while (*string		 && (unsigned char) *string < 128		 && !ISCNTRL (*string)		 && strchr (unwanted_chars, *string) == NULL		 && string < string_end)	    {	      fputc (*string, stream);	      string++;	    }	  fputc ('"', stream);	  if (string < string_end)	    fprintf (stream, ",");

⌨️ 快捷键说明

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