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

📄 mmix.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
	}      if (string < string_end)	{	  fprintf (stream, "#%x", *string & 255);	  string++;	  if (string < string_end)	    fprintf (stream, ",");	}    }}/* ASM_OUTPUT_SOURCE_LINE.  */voidmmix_asm_output_source_line  (stream, lineno)     FILE * stream;     int lineno;{  fprintf (stream, "# %d ", lineno);  OUTPUT_QUOTED_STRING (stream, main_input_filename);  fprintf (stream, "\n");}/* Target hook for assembling integer objects.  Use mmix_print_operand   for WYDE and TETRA.  Use mmix_output_octa to output 8-byte   CONST_DOUBLEs.  */static boolmmix_assemble_integer (x, size, aligned_p)     rtx x;     unsigned int size;     int aligned_p;{  if (aligned_p)    switch (size)      {	/* We handle a limited number of types of operands in here.  But	   that's ok, because we can punt to generic functions.  We then	   pretend that aligned data isn't needed, so the usual .<pseudo>	   syntax is used (which works for aligned data too).  We actually	   *must* do that, since we say we don't have simple aligned	   pseudos, causing this function to be called.  We just try and	   keep as much compatibility as possible with mmixal syntax for	   normal cases (i.e. without GNU extensions and C only).  */      case 1:	if (GET_CODE (x) != CONST_INT)	  {	    aligned_p = 0;	    break;	  }	fputs ("\tBYTE\t", asm_out_file);	mmix_print_operand (asm_out_file, x, 'B');	fputc ('\n', asm_out_file);	return true;      case 2:	if (GET_CODE (x) != CONST_INT)	  {	    aligned_p = 0;	    break;	  }	fputs ("\tWYDE\t", asm_out_file);	mmix_print_operand (asm_out_file, x, 'W');	fputc ('\n', asm_out_file);	return true;      case 4:	if (GET_CODE (x) != CONST_INT)	  {	    aligned_p = 0;	    break;	  }	fputs ("\tTETRA\t", asm_out_file);	mmix_print_operand (asm_out_file, x, 'L');	fputc ('\n', asm_out_file);	return true;      case 8:	if (GET_CODE (x) == CONST_DOUBLE)	  /* We don't get here anymore for CONST_DOUBLE, because DImode	     isn't expressed as CONST_DOUBLE, and DFmode is handled	     elsewhere.  */	  abort ();	assemble_integer_with_op ("\tOCTA\t", x);	return true;      }  return default_assemble_integer (x, size, aligned_p);}/* ASM_OUTPUT_ASCII.  */voidmmix_asm_output_ascii (stream, string, length)     FILE *stream;     const char *string;     int length;{  while (length > 0)    {      int chunk_size = length > 60 ? 60 : length;      fprintf (stream, "\tBYTE ");      mmix_output_quoted_string (stream, string, chunk_size);      string += chunk_size;      length -= chunk_size;      fprintf (stream, "\n");    }}/* ASM_OUTPUT_ALIGNED_COMMON.  */voidmmix_asm_output_aligned_common (stream, name, size, align)     FILE *stream;     const char *name;     int size;     int align;{  /* This is mostly the elfos.h one.  There doesn't seem to be a way to     express this in a mmixal-compatible way.  */  fprintf (stream, "\t.comm\t");  assemble_name (stream, name);  fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",	   size, align / BITS_PER_UNIT);}/* ASM_OUTPUT_ALIGNED_LOCAL.  */voidmmix_asm_output_aligned_local (stream, name, size, align)     FILE * stream;     const char * name;     int size;     int align;{  data_section ();  ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));  assemble_name (stream, name);  fprintf (stream, "\tLOC @+%d\n", size);}/* ASM_OUTPUT_LABEL.  */voidmmix_asm_output_label (stream, name)     FILE *stream;     const char * name;{  assemble_name (stream, name);  fprintf (stream, "\tIS @\n");}/* ASM_DECLARE_REGISTER_GLOBAL.  */voidmmix_asm_declare_register_global (stream, decl, regno, name)     FILE *stream ATTRIBUTE_UNUSED;     tree decl ATTRIBUTE_UNUSED;     int regno ATTRIBUTE_UNUSED;     const char *name ATTRIBUTE_UNUSED;{  /* Nothing to do here, but there *will* be, therefore the framework is     here.  */}/* ASM_WEAKEN_LABEL.  */voidmmix_asm_weaken_label (stream, name)     FILE * stream ATTRIBUTE_UNUSED;     const char * name ATTRIBUTE_UNUSED;{  fprintf (stream, "\t.weak ");  assemble_name (stream, name);  fprintf (stream, " ! mmixal-incompatible\n");}/* MAKE_DECL_ONE_ONLY.  */voidmmix_make_decl_one_only (decl)     tree decl;{  DECL_WEAK (decl) = 1;}/* ASM_OUTPUT_LABELREF.   Strip GCC's '*' and our own '@'.  No order is assumed.  */voidmmix_asm_output_labelref (stream, name)     FILE *stream;     const char *name;{  int is_extern = 1;  for (; (*name == '@' || *name == '*'); name++)    if (*name == '@')      is_extern = 0;  asm_fprintf (stream, "%s%U%s",	       is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",	       name);}/* ASM_OUTPUT_INTERNAL_LABEL.  */voidmmix_asm_output_internal_label (stream, name, num)     FILE * stream;     const char * name;     int num;{  fprintf (stream, "%s:%d\tIS @\n", name, num);}/* ASM_OUTPUT_DEF.  */voidmmix_asm_output_def (stream, name, value)     FILE * stream;     const char * name;     const char * value;{  assemble_name (stream, name);  fprintf (stream, "\tIS ");  assemble_name (stream, value);  fputc ('\n', stream);}/* PRINT_OPERAND.  */voidmmix_print_operand (stream, x, code)     FILE * stream;     rtx x;     int code;{  /* When we add support for different codes later, we can, when needed,     drop through to the main handler with a modified operand.  */  rtx modified_x = x;  int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;  switch (code)    {      /* Unrelated codes are in alphabetic order.  */    case '+':      /* For conditional branches, output "P" for a probable branch.  */      if (TARGET_BRANCH_PREDICT)	{	  x = find_reg_note (current_output_insn, REG_BR_PROB, 0);	  if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)	    putc ('P', stream);	}      return;    case '.':      /* For the %d in POP %d,0.  */      fprintf (stream, "%d", MMIX_POP_ARGUMENT ());      return;    case 'B':      if (GET_CODE (x) != CONST_INT)	fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);      fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));      return;    case 'H':      /* Highpart.  Must be general register, and not the last one, as	 that one cannot be part of a consecutive register pair.  */      if (regno > MMIX_LAST_GENERAL_REGISTER - 1)	internal_error ("MMIX Internal: Bad register: %d", regno);      /* This is big-endian, so the high-part is the first one.  */      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);      return;    case 'L':      /* Lowpart.  Must be CONST_INT or general register, and not the last	 one, as that one cannot be part of a consecutive register pair.  */      if (GET_CODE (x) == CONST_INT)	{	  fprintf (stream, "#%lx",		   (unsigned long) (INTVAL (x)				    & ((unsigned int) 0x7fffffff * 2 + 1)));	  return;	}      if (GET_CODE (x) == SYMBOL_REF)	{	  output_addr_const (stream, x);	  return;	}      if (regno > MMIX_LAST_GENERAL_REGISTER - 1)	internal_error ("MMIX Internal: Bad register: %d", regno);      /* This is big-endian, so the low-part is + 1.  */      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);      return;      /* Can't use 'a' because that's a generic modifier for address	 output.  */    case 'A':      mmix_output_shiftvalue_op_from_str (stream, "ANDN",					  ~(unsigned HOST_WIDEST_INT)					  mmix_intval (x));      return;    case 'i':      mmix_output_shiftvalue_op_from_str (stream, "INC",					  (unsigned HOST_WIDEST_INT)					  mmix_intval (x));      return;    case 'o':      mmix_output_shiftvalue_op_from_str (stream, "OR",					  (unsigned HOST_WIDEST_INT)					  mmix_intval (x));      return;    case 's':      mmix_output_shiftvalue_op_from_str (stream, "SET",					  (unsigned HOST_WIDEST_INT)					  mmix_intval (x));      return;    case 'd':    case 'D':      mmix_output_condition (stream, x, (code == 'D'));      return;    case 'e':      /* Output an extra "e" to make fcmpe, fune.  */      if (TARGET_FCMP_EPSILON)	fprintf (stream, "e");      return;    case 'm':      /* Output the number minus 1.  */      if (GET_CODE (x) != CONST_INT)	{	  fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",		      x);	}      fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,	       (HOST_WIDEST_INT) (mmix_intval (x) - 1));      return;    case 'p':      /* Store the number of registers we want to save.  This was setup	 by the prologue.  The actual operand contains the number of	 registers to pass, but we don't use it currently.  Anyway, we	 need to output the number of saved registers here.  */      fprintf (stream, "%d",	       cfun->machine->highest_saved_stack_register + 1);      return;    case 'r':      /* Store the register to output a constant to.  */      if (! REG_P (x))	fatal_insn ("MMIX Internal: Expected a register, not this", x);      mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);      return;    case 'I':      /* Output the constant.  Note that we use this for floats as well.  */      if (GET_CODE (x) != CONST_INT	  && (GET_CODE (x) != CONST_DOUBLE	      || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode		  && GET_MODE (x) != SFmode)))	fatal_insn ("MMIX Internal: Expected a constant, not this", x);      mmix_output_register_setting (stream,				    mmix_output_destination_register,				    mmix_intval (x), 0);      return;    case 'U':      /* An U for unsigned, if TARGET_ZERO_EXTEND.  Ignore the operand.  */      if (TARGET_ZERO_EXTEND)	putc ('U', stream);      return;    case 'v':      mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));      return;    case 'V':      mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));      return;    case 'W':      if (GET_CODE (x) != CONST_INT)	fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);      fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));      return;    case 0:      /* Nothing to do.  */      break;    default:      /* Presumably there's a missing case above if we get here.  */      internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);    }  switch (GET_CODE (modified_x))    {    case REG:      regno = REGNO (modified_x);      if (regno >= FIRST_PSEUDO_REGISTER)	internal_error ("MMIX Internal: Bad register: %d", regno);      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);      return;    case MEM:      output_address (XEXP (modified_x, 0));      return;    case CONST_INT:      /* For -2147483648, mmixal complains that the constant does not fit	 in 4 bytes, so let's output it as hex.  Take care to handle hosts	 where HOST_WIDE_INT is longer than an int.	 Print small constants +-255 using decimal.  */      if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)	fprintf (stream, "%d", (int) (INTVAL (modified_x)));      else	fprintf (stream, "#%x",		 (int) (INTVAL (modified_x)) & (unsigned int) ~0);      return;    case CONST_DOUBLE:      /* Do somewhat as CONST_INT.  */      mmix_output_octa (stream, mmix_intval (modified_x), 0);      return;    case CONST:      output_addr_const (stream, modified_x);      return;    default:      /* No need to test for all strange things.  Let output_addr_const do	 it for us.  */      if (CONSTANT_P (modified_x)	  /* Strangely enough, this is not included in CONSTANT_P.	     FIXME: Ask/check about sanity here.  */	  || GET_CODE (modified_x) == CODE_LABEL)	{	  output_addr_const (stream, modified_x);	  return;	}      /* We need the original here.  */      fatal_insn ("MMIX Internal: Cannot decode this operand", x);    }

⌨️ 快捷键说明

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