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

📄 mmix.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Definitions of target machine for GNU compiler, for MMIX.   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.   Contributed by Hans-Peter Nilsson (hp@bitrange.com)This file is part of GCC.GCC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GCC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "hashtab.h"#include "insn-config.h"#include "output.h"#include "flags.h"#include "tree.h"#include "function.h"#include "expr.h"#include "toplev.h"#include "recog.h"#include "ggc.h"#include "dwarf2.h"#include "debug.h"#include "tm_p.h"#include "integrate.h"#include "target.h"#include "target-def.h"#include "real.h"/* First some local helper definitions.  */#define MMIX_FIRST_GLOBAL_REGNUM 32/* We'd need a current_function_has_landing_pad.  It's marked as such when   a nonlocal_goto_receiver is expanded.  Not just a C++ thing, but   mostly.  */#define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)/* We have no means to tell DWARF 2 about the register stack, so we need   to store the return address on the stack if an exception can get into   this function.  FIXME: Narrow condition.  Before any whole-function   analysis, regs_ever_live[] isn't initialized.  We know it's up-to-date   after reload_completed; it may contain incorrect information some time   before that.  Within a RTL sequence (after a call to start_sequence,   such as in RTL expanders), leaf_function_p doesn't see all insns   (perhaps any insn).  But regs_ever_live is up-to-date when   leaf_function_p () isn't, so we "or" them together to get accurate   information.  FIXME: Some tweak to leaf_function_p might be   preferable.  */#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS			\ (flag_exceptions						\  && ((reload_completed && regs_ever_live[MMIX_rJ_REGNUM])	\      || !leaf_function_p ()))#define IS_MMIX_EH_RETURN_DATA_REG(REGNO)	\ (current_function_calls_eh_return		\  && (EH_RETURN_DATA_REGNO (0) == REGNO		\      || EH_RETURN_DATA_REGNO (1) == REGNO	\      || EH_RETURN_DATA_REGNO (2) == REGNO	\      || EH_RETURN_DATA_REGNO (3) == REGNO))/* For the default ABI, we rename registers at output-time to fill the gap   between the (statically partitioned) saved registers and call-clobbered   registers.  In effect this makes unused call-saved registers to be used   as call-clobbered registers.  The benefit comes from keeping the number   of local registers (value of rL) low, since there's a cost of   increasing rL and clearing unused (unset) registers with lower numbers.   Don't translate while outputting the prologue.  */#define MMIX_OUTPUT_REGNO(N)					\ (TARGET_ABI_GNU 						\  || (int) (N) < MMIX_RETURN_VALUE_REGNUM			\  || (int) (N) > MMIX_LAST_STACK_REGISTER_REGNUM		\  || cfun == NULL 						\  || cfun->machine == NULL 					\  || cfun->machine->in_prologue					\  ? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM			\	   + cfun->machine->highest_saved_stack_register + 1))/* The %d in "POP %d,0".  */#define MMIX_POP_ARGUMENT()						\ ((! TARGET_ABI_GNU							\   && current_function_return_rtx != NULL				\   && ! current_function_returns_struct)				\  ? (GET_CODE (current_function_return_rtx) == PARALLEL			\     ? GET_NUM_ELEM (XVEC (current_function_return_rtx, 0)) : 1)	\  : 0)/* The canonical saved comparison operands for non-cc0 machines, set in   the compare expander.  */rtx mmix_compare_op0;rtx mmix_compare_op1;/* We ignore some options with arguments.  They are passed to the linker,   but also ends up here because they start with "-m".  We tell the driver   to store them in a variable we don't inspect.  */const char *mmix_cc1_ignored_option;/* Declarations of locals.  *//* Intermediate for insn output.  */static int mmix_output_destination_register;static void mmix_output_shiftvalue_op_from_str  (FILE *, const char *, HOST_WIDEST_INT);static void mmix_output_shifted_value (FILE *, HOST_WIDEST_INT);static void mmix_output_condition (FILE *, rtx, int);static HOST_WIDEST_INT mmix_intval (rtx);static void mmix_output_octa (FILE *, HOST_WIDEST_INT, int);static bool mmix_assemble_integer (rtx, unsigned int, int);static struct machine_function *mmix_init_machine_status (void);static void mmix_encode_section_info (tree, rtx, int);static const char *mmix_strip_name_encoding (const char *);static void mmix_emit_sp_add (HOST_WIDE_INT offset);static void mmix_target_asm_function_prologue (FILE *, HOST_WIDE_INT);static void mmix_target_asm_function_end_prologue (FILE *);static void mmix_target_asm_function_epilogue (FILE *, HOST_WIDE_INT);static void mmix_reorg (void);static void mmix_asm_output_mi_thunk  (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);static void mmix_setup_incoming_varargs  (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);static void mmix_file_start (void);static void mmix_file_end (void);static bool mmix_rtx_costs (rtx, int, int, int *);static rtx mmix_struct_value_rtx (tree, int);static bool mmix_pass_by_reference (const CUMULATIVE_ARGS *,				    enum machine_mode, tree, bool);/* Target structure macros.  Listed by node.  See `Using and Porting GCC'   for a general description.  *//* Node: Function Entry */#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP NULL#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP NULL#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP NULL#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP NULL#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER mmix_assemble_integer#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue#undef TARGET_ASM_FUNCTION_END_PROLOGUE#define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO  mmix_encode_section_info#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING  mmix_strip_name_encoding#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START mmix_file_start#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true#undef TARGET_ASM_FILE_END#define TARGET_ASM_FILE_END mmix_file_end#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS mmix_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST hook_int_rtx_0#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg#undef TARGET_PROMOTE_FUNCTION_ARGS#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true#if 0/* Apparently not doing TRT if int < register-size.  FIXME: Perhaps   FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say.  */#undef TARGET_PROMOTE_FUNCTION_RETURN#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true#endif#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx#undef TARGET_SETUP_INCOMING_VARARGS#define TARGET_SETUP_INCOMING_VARARGS mmix_setup_incoming_varargs#undef TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference#undef TARGET_CALLEE_COPIES#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_truestruct gcc_target targetm = TARGET_INITIALIZER;/* Functions that are expansions for target macros.   See Target Macros in `Using and Porting GCC'.  *//* OVERRIDE_OPTIONS.  */voidmmix_override_options (void){  /* Should we err or should we warn?  Hmm.  At least we must neutralize     it.  For example the wrong kind of case-tables will be generated with     PIC; we use absolute address items for mmixal compatibility.  FIXME:     They could be relative if we just elide them to after all pertinent     labels.  */  if (flag_pic)    {      warning ("-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");      flag_pic = 0;    }}/* INIT_EXPANDERS.  */voidmmix_init_expanders (void){  init_machine_status = mmix_init_machine_status;}/* Set the per-function data.  */static struct machine_function *mmix_init_machine_status (void){  return ggc_alloc_cleared (sizeof (struct machine_function));}/* DATA_ALIGNMENT.   We have trouble getting the address of stuff that is located at other   than 32-bit alignments (GETA requirements), so try to give everything   at least 32-bit alignment.  */intmmix_data_alignment (tree type ATTRIBUTE_UNUSED, int basic_align){  if (basic_align < 32)    return 32;  return basic_align;}/* CONSTANT_ALIGNMENT.  */intmmix_constant_alignment (tree constant ATTRIBUTE_UNUSED, int basic_align){  if (basic_align < 32)    return 32;  return basic_align;}/* LOCAL_ALIGNMENT.  */intmmix_local_alignment (tree type ATTRIBUTE_UNUSED, int basic_align){  if (basic_align < 32)    return 32;  return basic_align;}/* CONDITIONAL_REGISTER_USAGE.  */voidmmix_conditional_register_usage (void){  int i;  if (TARGET_ABI_GNU)    {      static const int gnu_abi_reg_alloc_order[]	= MMIX_GNU_ABI_REG_ALLOC_ORDER;      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];      /* Change the default from the mmixware ABI.  For the GNU ABI,	 $15..$30 are call-saved just as $0..$14.  There must be one	 call-clobbered local register for the "hole" that holds the	 number of saved local registers saved by PUSHJ/PUSHGO during the	 function call, receiving the return value at return.  So best is	 to use the highest, $31.  It's already marked call-clobbered for	 the mmixware ABI.  */      for (i = 15; i <= 30; i++)	call_used_regs[i] = 0;      /* "Unfix" the parameter registers.  */      for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;	   i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;	   i++)	fixed_regs[i] = 0;    }  /* Step over the ":" in special register names.  */  if (! TARGET_TOPLEVEL_SYMBOLS)    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)      if (reg_names[i][0] == ':')	reg_names[i]++;}/* LOCAL_REGNO.   All registers that are part of the register stack and that will be   saved are local.  */intmmix_local_regno (int regno){  return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && !call_used_regs[regno];}/* PREFERRED_RELOAD_CLASS.   We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */enum reg_classmmix_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class){  /* FIXME: Revisit.  */  return GET_CODE (x) == MOD && GET_MODE (x) == DImode    ? REMAINDER_REG : class;}/* PREFERRED_OUTPUT_RELOAD_CLASS.   We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */enum reg_classmmix_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED,				    enum reg_class class){  /* FIXME: Revisit.  */  return GET_CODE (x) == MOD && GET_MODE (x) == DImode    ? REMAINDER_REG : class;}/* SECONDARY_RELOAD_CLASS.   We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere.  */enum reg_classmmix_secondary_reload_class (enum reg_class class,			     enum machine_mode mode ATTRIBUTE_UNUSED,			     rtx x ATTRIBUTE_UNUSED,			     int in_p ATTRIBUTE_UNUSED){  if (class == REMAINDER_REG      || class == HIMULT_REG      || class == SYSTEM_REGS)    return GENERAL_REGS;  return NO_REGS;}/* CONST_OK_FOR_LETTER_P.  */intmmix_const_ok_for_letter_p (HOST_WIDE_INT value, int c){  return    (c == 'I' ? value >= 0 && value <= 255     : c == 'J' ? value >= 0 && value <= 65535     : c == 'K' ? value <= 0 && value >= -255     : c == 'L' ? mmix_shiftable_wyde_value (value)     : c == 'M' ? value == 0     : c == 'N' ? mmix_shiftable_wyde_value (~value)     : c == 'O' ? (value == 3 || value == 5 || value == 9		   || value == 17)     : 0);}/* CONST_DOUBLE_OK_FOR_LETTER_P.  */intmmix_const_double_ok_for_letter_p (rtx value, int c){  return    (c == 'G' ? value == CONST0_RTX (GET_MODE (value))     : 0);}/* EXTRA_CONSTRAINT.   We need this since our constants are not always expressible as   CONST_INT:s, but rather often as CONST_DOUBLE:s.  */intmmix_extra_constraint (rtx x, int c, int strict){  HOST_WIDEST_INT value;  /* When checking for an address, we need to handle strict vs. non-strict     register checks.  Don't use address_operand, but instead its     equivalent (its callee, which it is just a wrapper for),     memory_operand_p and the strict-equivalent strict_memory_address_p.  */  if (c == 'U')    return      strict      ? strict_memory_address_p (Pmode, x)      : memory_address_p (Pmode, x);  /* R asks whether x is to be loaded with GETA or something else.  Right     now, only a SYMBOL_REF and LABEL_REF can fit for     TARGET_BASE_ADDRESSES.     Only constant symbolic addresses apply.  With TARGET_BASE_ADDRESSES,     we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG     set right now; only function addresses and code labels.  If we change     to let SYMBOL_REF_FLAG be set on other symbols, we have to check     inside CONST expressions.  When TARGET_BASE_ADDRESSES is not in     effect, a "raw" constant check together with mmix_constant_address_p     is all that's needed; we want all constant addresses to be loaded     with GETA then.  */  if (c == 'R')    return      GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE      && mmix_constant_address_p (x)      && (! TARGET_BASE_ADDRESSES	  || (GET_CODE (x) == LABEL_REF	      || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));  if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)    return 0;

⌨️ 快捷键说明

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