📄 cris.c
字号:
/* Definitions for GCC. Part of the machine description for CRIS. Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Axis Communications. Written by Hans-Peter Nilsson.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 "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-attr.h"#include "flags.h"#include "tree.h"#include "expr.h"#include "except.h"#include "function.h"#include "toplev.h"#include "recog.h"#include "tm_p.h"#include "debug.h"#include "output.h"#include "target.h"#include "target-def.h"#include "ggc.h"/* Usable when we have an amount to add or subtract, and want the optimal size of the insn. */#define ADDITIVE_SIZE_MODIFIER(size) \ ((size) <= 63 ? "q" : (size) <= 255 ? "u.b" : (size) <= 65535 ? "u.w" : ".d")#define ASSERT_PLT_UNSPEC(x) \ do \ { \ if (XEXP (x, 1) != NULL_RTX \ || (GET_CODE (XVECEXP (x, 0, 0)) != SYMBOL_REF \ && GET_CODE (XVECEXP (x, 0, 0)) != LABEL_REF)) \ abort (); \ } while (0)#define LOSE_AND_RETURN(msgid, x) \ do \ { \ cris_operand_lossage (msgid, x); \ return; \ } while (0)/* Per-function machine data. */struct machine_function GTY(()) { int needs_return_address_on_stack; };/* This little fix suppresses the 'u' or 's' when '%e' in assembly pattern. */static char cris_output_insn_is_bound = 0;/* This one suppresses printing out the "rPIC+" in "rPIC+sym:GOTOFF+offset" when doing PIC. For a PLT symbol, it suppresses outputting it as [rPIC+sym:GOTPLT] and outputs similarly just the "sym:GOTOFF" part. */static int cris_pic_sympart_only = 0;/* Fix for reg_overlap_mentioned_p. */static int cris_reg_overlap_mentioned_p PARAMS ((rtx, rtx));static void cris_print_base PARAMS ((rtx, FILE *));static void cris_print_index PARAMS ((rtx, FILE *));static struct machine_function * cris_init_machine_status PARAMS ((void));static int cris_initial_frame_pointer_offset PARAMS ((void));static int saved_regs_mentioned PARAMS ((rtx));static void cris_target_asm_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void cris_target_asm_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void cris_encode_section_info PARAMS ((tree, int));static void cris_operand_lossage PARAMS ((const char *, rtx));static void cris_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));/* The function cris_target_asm_function_epilogue puts the last insn to output here. It always fits; there won't be a symbol operand. Used in delay_slots_for_epilogue and function_epilogue. */static char save_last[80];/* This is the argument from the "-max-stack-stackframe=" option. */const char *cris_max_stackframe_str;/* This is the argument from the "-march=" option. */const char *cris_cpu_str;/* This is the argument from the "-mtune=" option. */const char *cris_tune_str;/* This is the argument from the "-melinux-stacksize=" option. */const char *cris_elinux_stacksize_str;/* This is the parsed result of the "-max-stack-stackframe=" option. If it (still) is zero, then there was no such option given. */int cris_max_stackframe = 0;/* This is the parsed result of the "-march=" option, if given. */int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.dword\t"#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"/* We need to define these, since the 2byte, 4byte, 8byte op:s are only available in ELF. These "normal" pseudos do not have any alignment constraints or side-effects. */#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE cris_target_asm_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE cris_target_asm_function_epilogue#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO cris_encode_section_info#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK cris_asm_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcallstruct gcc_target targetm = TARGET_INITIALIZER;/* Predicate functions. *//* This checks a part of an address, the one that is not a plain register for an addressing mode using BDAP. Allowed operands is either: a) a register b) a CONST operand (but not a symbol when generating PIC) c) a [r] or [r+] in SImode, or sign-extend from HI or QI. */intcris_bdap_operand (op, mode) rtx op; enum machine_mode mode;{ register enum rtx_code code = GET_CODE (op); if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode)) return 0; /* Just return whether this is a simple register or constant. */ if (register_operand (op, mode) || (CONSTANT_P (op) && !(flag_pic && cris_symbol (op)))) return 1; /* Is it a [r] or possibly a [r+]? */ if (code == MEM) { rtx tem = XEXP (op, 0); if (mode == SImode && (register_operand (tem, SImode) || (GET_CODE (tem) == POST_INC && register_operand (XEXP (tem, 0), SImode)))) return 1; else return 0; } /* Perhaps a sign-extended mem: [r].(b|w) or [r+].(b|w)? */ if (code == SIGN_EXTEND) { rtx tem = XEXP (op, 0); if (GET_CODE (tem) != MEM) return 0; tem = XEXP (tem, 0); if (mode == SImode && (register_operand (tem, SImode) || (GET_CODE (tem) == POST_INC && register_operand (XEXP (tem, 0), SImode)))) return 1; else return 0; } return 0;}/* This is similar to cris_bdap_operand: It checks a part of an address, the one that is not a plain register for an addressing mode using BDAP *or* BIAP. Allowed operands is either: a) a register b) a CONST operand (but not a symbol when generating PIC) c) a mult of (1, 2 or 4) and a register d) a [r] or [r+] in SImode, or sign-extend from HI or QI. */intcris_bdap_biap_operand (op, mode) rtx op; enum machine_mode mode;{ register enum rtx_code code = GET_CODE (op); rtx reg; rtx val; /* Check for bdap operand. */ if (cris_bdap_operand (op, mode)) return 1; if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode)) return 0; /* Check that we're looking at a BIAP operand. */ if (code != MULT) return 0; /* Canonicalize register and multiplicand. */ if (GET_CODE (XEXP (op, 0)) == CONST_INT) { val = XEXP (op, 0); reg = XEXP (op, 1); } else { val = XEXP (op, 1); reg = XEXP (op, 0); } /* Check that the operands are correct after canonicalization. */ if (! register_operand (reg, SImode) || GET_CODE (val) != CONST_INT) return 0; /* Check that the multiplicand has a valid value. */ if ((code == MULT && (INTVAL (val) == 1 || INTVAL (val) == 2 || INTVAL (val) == 4))) return 1; return 0;}/* Check if MODE is same as mode for X, and X is PLUS, MINUS, IOR or AND or UMIN. */intcris_orthogonal_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == PLUS || code == MINUS || code == IOR || code == AND || code == UMIN));}/* Check if MODE is same as mode for X, and X is PLUS, IOR or AND or UMIN. */intcris_commutative_orth_op (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == PLUS || code == IOR || code == AND || code == UMIN));}/* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN. */intcris_operand_extend_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == PLUS || code == MINUS || code == UMIN));}/* Check if MODE is same as mode for X, and X is PLUS or MINUS. */intcris_additive_operand_extend_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == PLUS || code == MINUS));}/* Check to see if MODE is same as mode for X, and X is SIGN_EXTEND or ZERO_EXTEND. */intcris_extend_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == SIGN_EXTEND || code == ZERO_EXTEND));}/* Check to see if MODE is same as mode for X, and X is PLUS or BOUND. */intcris_plus_or_bound_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (mode == VOIDmode) mode = GET_MODE (x); return (GET_MODE (x) == mode && (code == UMIN || code == PLUS));}/* Since with -fPIC, not all symbols are valid PIC symbols or indeed general_operands, we have to have a predicate that matches it for the "movsi" expander. */intcris_general_operand_or_symbol (op, mode) rtx op; enum machine_mode mode;{ return general_operand (op, mode) || (CONSTANT_P (op) && cris_symbol (op));}/* Since a PIC symbol without a GOT entry is not a general_operand, we have to have a predicate that matches it. We use this in the expanded "movsi" anonymous pattern for PIC symbols. */intcris_general_operand_or_gotless_symbol (op, mode) rtx op; enum machine_mode mode;{ return general_operand (op, mode) || (CONSTANT_P (op) && cris_gotless_symbol (op));}/* Since a PLT symbol is not a general_operand, we have to have a predicate that matches it when we need it. We use this in the expanded "call" and "call_value" anonymous patterns. */intcris_general_operand_or_plt_symbol (op, mode) rtx op; enum machine_mode mode;{ return general_operand (op, mode) || (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == UNSPEC && !TARGET_AVOID_GOTPLT);}/* This matches a (MEM (general_operand)) or (MEM (cris_general_operand_or_symbol)). The second one isn't a valid memory_operand, so we need this predicate to recognize call destinations before we change them to a PLT operand (by wrapping in UNSPEC 0). */intcris_mem_call_operand (op, mode) rtx op; enum machine_mode mode;{ rtx xmem; if (GET_CODE (op) != MEM) return 0; if (memory_operand (op, mode)) return 1; xmem = XEXP (op, 0); return cris_general_operand_or_symbol (xmem, GET_MODE (op));}/* The CONDITIONAL_REGISTER_USAGE worker. */voidcris_conditional_register_usage (){ /* FIXME: This isn't nice. We should be able to use that register for something else if the PIC table isn't needed. */ if (flag_pic) fixed_regs[PIC_OFFSET_TABLE_REGNUM] = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;}/* Return current_function_uses_pic_offset_table. For use in cris.md, since some generated files do not include function.h. */int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -