📄 sh.h
字号:
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \{ \ if (GET_CODE (X) == PLUS \ && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8) \ && GET_CODE (XEXP (X, 1)) == CONST_INT \ && BASE_REGISTER_RTX_P (XEXP (X, 0)) \ && ! (TARGET_SH4 && (MODE) == DFmode) \ && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS)) \ { \ rtx index_rtx = XEXP (X, 1); \ HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base; \ rtx sum; \ \ if (TARGET_SH3E && MODE == SFmode) \ { \ X = copy_rtx (X); \ push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL_PTR, \ INDEX_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \ (TYPE)); \ goto WIN; \ } \ /* Instead of offset_base 128..131 use 124..127, so that \ simple add suffices. */ \ if (offset > 127) \ { \ offset_base = ((offset + 4) & ~60) - 4; \ } \ else \ offset_base = offset & ~60; \ /* Sometimes the normal form does not suit DImode. We \ could avoid that by using smaller ranges, but that \ would give less optimized code when SImode is \ prevalent. */ \ if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64) \ { \ sum = gen_rtx (PLUS, Pmode, XEXP (X, 0), \ GEN_INT (offset_base)); \ X = gen_rtx (PLUS, Pmode, sum, GEN_INT (offset - offset_base));\ push_reload (sum, NULL_RTX, &XEXP (X, 0), NULL_PTR, \ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \ (TYPE)); \ goto WIN; \ } \ } \ /* We must re-recognize what we created before. */ \ else if (GET_CODE (X) == PLUS \ && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8) \ && GET_CODE (XEXP (X, 0)) == PLUS \ && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0)) \ && GET_CODE (XEXP (X, 1)) == CONST_INT \ && ! (TARGET_SH3E && MODE == SFmode)) \ { \ /* Because this address is so complex, we know it must have \ been created by LEGITIMIZE_RELOAD_ADDRESS before; thus, \ it is already unshared, and needs no further unsharing. */ \ push_reload (XEXP ((X), 0), NULL_RTX, &XEXP ((X), 0), NULL_PTR, \ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), (TYPE));\ goto WIN; \ } \}/* Go to LABEL if ADDR (a legitimate address expression) has an effect that depends on the machine mode it is used for. ??? Strictly speaking, we should also include all indexed addressing, because the index scale factor is the length of the operand. However, the impact of GO_IF_MODE_DEPENDENT_ADDRESS would be to high if we did that. So we rely on reload to fix things up. */#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \{ \ if (GET_CODE(ADDR) == PRE_DEC || GET_CODE(ADDR) == POST_INC) \ goto LABEL; \}/* Specify the machine mode that this machine uses for the index in the tablejump instruction. */#define CASE_VECTOR_MODE (TARGET_BIGTABLE ? SImode : HImode)#define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 127 \ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode) \ : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255 \ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode) \ : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 ? HImode \ : SImode)/* Define as C expression which evaluates to nonzero if the tablejump instruction expects the table to contain offsets from the address of the table. Do not define this if the table should contain absolute addresses. */#define CASE_VECTOR_PC_RELATIVE 1/* Specify the tree operation to be used to convert reals to integers. */#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR/* This is the kind of divide that is easiest to do in the general case. */#define EASY_DIV_EXPR TRUNC_DIV_EXPR/* Since the SH3e has only `float' support, it is desirable to make all floating point types equivalent to `float'. */#define DOUBLE_TYPE_SIZE ((TARGET_SH3E && ! TARGET_SH4) ? 32 : 64)/* 'char' is signed by default. */#define DEFAULT_SIGNED_CHAR 1/* The type of size_t unsigned int. */#define SIZE_TYPE "unsigned int"#define WCHAR_TYPE "short unsigned int"#define WCHAR_TYPE_SIZE 16/* Don't cse the address of the function being compiled. *//*#define NO_RECURSIVE_FUNCTION_CSE 1*//* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */#define MOVE_MAX 4/* Max number of bytes we want move_by_pieces to be able to copy efficiently. */#define MOVE_MAX_PIECES (TARGET_SH4 ? 8 : 4)/* Define if operations between registers always perform the operation on the full register even if a narrower mode is specified. */#define WORD_REGISTER_OPERATIONS/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD will either zero-extend or sign-extend. The value of this macro should be the code that says which one of the two operations is implicitly done, NIL if none. */#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND/* Define if loading short immediate values into registers sign extends. */#define SHORT_IMMEDIATES_SIGN_EXTEND/* Define this if zero-extension is slow (more than one real instruction). On the SH, it's only one instruction. *//* #define SLOW_ZERO_EXTEND *//* Nonzero if access to memory by bytes is no faster than for words. */#define SLOW_BYTE_ACCESS 1/* Force sizeof(bool) == 1 to maintain binary compatibility; otherwise, the change in SLOW_BYTE_ACCESS would have changed it to 4. */#define BOOL_TYPE_SIZE (flag_new_abi ? INT_TYPE_SIZE : CHAR_TYPE_SIZE)/* We assume that the store-condition-codes instructions store 0 for false and some other value for true. This is the value stored for true. */#define STORE_FLAG_VALUE 1/* Immediate shift counts are truncated by the output routines (or was it the assembler?). Shift counts in a register are truncated by SH. Note that the native compiler puts too large (> 32) immediate shift counts into a register and shifts by the register, letting the SH decide what to do instead of doing that itself. *//* ??? The library routines in lib1funcs.asm truncate the shift count. However, the SH3 has hardware shifts that do not truncate exactly as gcc expects - the sign bit is significant - so it appears that we need to leave this zero for correct SH3 code. */#define SHIFT_COUNT_TRUNCATED (! TARGET_SH3)/* All integers have the same format so truncation is easy. */#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1/* Define this if addresses of constant functions shouldn't be put through pseudo regs where they can be cse'd. Desirable on machines where ordinary constants are expensive but a CALL with constant address is cheap. *//*#define NO_FUNCTION_CSE 1*//* Chars and shorts should be passed as ints. */#define PROMOTE_PROTOTYPES 1/* The machine modes of pointers and functions. */#define Pmode SImode#define FUNCTION_MODE Pmode/* The relative costs of various types of constants. Note that cse.c defines REG = 1, SUBREG = 2, any node = (2 + sum of subnodes). */#define CONST_COSTS(RTX, CODE, OUTER_CODE) \ case CONST_INT: \ if (INTVAL (RTX) == 0) \ return 0; \ else if (CONST_OK_FOR_I (INTVAL (RTX))) \ return 1; \ else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \ && CONST_OK_FOR_L (INTVAL (RTX))) \ return 1; \ else \ return 8; \ case CONST: \ case LABEL_REF: \ case SYMBOL_REF: \ return 5; \ case CONST_DOUBLE: \ return 10;#define RTX_COSTS(X, CODE, OUTER_CODE) \ case PLUS: \ return (COSTS_N_INSNS (1) \ + rtx_cost (XEXP ((X), 0), PLUS) \ + (rtx_equal_p (XEXP ((X), 0), XEXP ((X), 1))\ ? 0 : rtx_cost (XEXP ((X), 1), PLUS)));\ case AND: \ return COSTS_N_INSNS (andcosts (X)); \ case MULT: \ return COSTS_N_INSNS (multcosts (X)); \ case ASHIFT: \ case ASHIFTRT: \ case LSHIFTRT: \ /* Add one extra unit for the matching constraint. \ Otherwise loop strength reduction would think that\ a shift with different sourc and destination is \ as cheap as adding a constant to a register. */ \ return (COSTS_N_INSNS (shiftcosts (X)) \ + rtx_cost (XEXP ((X), 0), (CODE)) \ + 1); \ case DIV: \ case UDIV: \ case MOD: \ case UMOD: \ return COSTS_N_INSNS (20); \ case FLOAT: \ case FIX: \ return 100;/* The multiply insn on the SH1 and the divide insns on the SH1 and SH2 are actually function calls with some special constraints on arguments and register usage. These macros tell reorg that the references to arguments and register clobbers for insns of type sfunc do not appear to happen until after the millicode call. This allows reorg to put insns which set the argument registers into the delay slot of the millicode call -- thus they act more like traditional CALL_INSNs. get_attr_is_sfunc will try to recognize the given insn, so make sure to filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns in particular. */#define INSN_SETS_ARE_DELAYED(X) \ ((GET_CODE (X) == INSN \ && GET_CODE (PATTERN (X)) != SEQUENCE \ && GET_CODE (PATTERN (X)) != USE \ && GET_CODE (PATTERN (X)) != CLOBBER \ && get_attr_is_sfunc (X)))#define INSN_REFERENCES_ARE_DELAYED(X) \ ((GET_CODE (X) == INSN \ && GET_CODE (PATTERN (X)) != SEQUENCE \ && GET_CODE (PATTERN (X)) != USE \ && GET_CODE (PATTERN (X)) != CLOBBER \ && get_attr_is_sfunc (X)))/* Compute the cost of an address. For the SH, all valid addresses are the same cost. *//* ??? Perhaps we should make reg+reg addresses have higher cost because they add to register pressure on r0. */#define ADDRESS_COST(RTX) 1/* Compute extra cost of moving data between one register class and another. *//* Regclass always uses 2 for moves in the same register class; If SECONDARY*_RELOAD_CLASS says something about the src/dst pair, it uses this information. Hence, the general register <-> floating point register information here is not used for SFmode. */#define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \ ((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REG)) ? 10 \ : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS || (DSTCLASS) == DF_REGS) \ && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS)) \ || (((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS) \ && ((SRCCLASS) == FP0_REGS || (SRCCLASS) == FP_REGS \ || (SRCCLASS) == DF_REGS))) \ ? TARGET_FMOVD ? 8 : 12 \ : (((DSTCLASS) == FPUL_REGS \ && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS)) \ || (SRCCLASS == FPUL_REGS \ && ((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS))) \ ? 5 \ : (((DSTCLASS) == FPUL_REGS \ && ((SRCCLASS) == PR_REGS || (SRCCLASS) == MAC_REGS)) \ || ((SRCCLASS) == FPUL_REGS \ && ((DSTCLASS) == PR_REGS || (DSTCLASS) == MAC_REGS))) \ ? 7 \ : 2)/* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option? This would be so that people would slow memory systems could generate different code that does fewer memory accesses. *//* Assembler output control. *//* A C string constant describing how to begin a comment in the target assembler language. The compiler assumes that the comment will end at the end of the line. */#define ASM_COMMENT_START "!"/* The text to go at the start of the assembler file. */#define ASM_FILE_START(STREAM) \ output_file_start (STREAM)#define ASM_FILE_END(STREAM)#define ASM_APP_ON ""#define ASM_APP_OFF ""#define FILE_ASM_OP "\t.file\n"#define IDENT_ASM_OP "\t.ident\n"#define SET_ASM_OP ".set"/* How to change between sections. */#define TEXT_SECTION_ASM_OP "\t.text"#define DATA_SECTION_ASM_OP "\t.data"#define CTORS_SECTION_ASM_OP "\t.section\t.ctors\n"#define DTORS_SECTION_ASM_OP "\t.section\t.dtors\n"#define EXTRA_SECTIONS in_ctors, in_dtors#define EXTRA_SECTION_FUNCTIONS \void \ctors_section() \{ \ if (in_section != in_ctors) \ { \ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ in_section = in_ctors; \ } \} \void \dtors_section() \{ \ if (in_section != in_dtors) \ { \ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ in_section = in_dtors; \ } \}/* Define this so that jump tables go in same section as the current function, which could be text or it could be a user defined section. */#define JUMP_TABLES_IN_TEXT_SECTION 1/* A C statement to output something to the assembler file to switch to section NAME for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -