📄 c4x.h
字号:
gen_rtx_REG (TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0. */#define LIBCALL_VALUE(MODE) \ gen_rtx_REG (MODE, R0_REGNO) /* Return in R0. */#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == R0_REGNO)/* How Large Values Are Returned. */#define DEFAULT_PCC_STRUCT_RETURN 0/* Generating Code for Profiling. *//* Note that the generated assembly uses the ^ operator to load the 16 MSBs of the address. This is not supported by the TI assembler. The FUNCTION profiler needs a function mcount which gets passed a pointer to the LABELNO. */#define FUNCTION_PROFILER(FILE, LABELNO) \ if (! TARGET_C3X) \ { \ fprintf (FILE, "\tpush\tar2\n"); \ fprintf (FILE, "\tldhi\t^LP%d,ar2\n", (LABELNO)); \ fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ fprintf (FILE, "\tcall\tmcount\n"); \ fprintf (FILE, "\tpop\tar2\n"); \ } \ else \ { \ fprintf (FILE, "\tpush\tar2\n"); \ fprintf (FILE, "\tldiu\t^LP%d,ar2\n", (LABELNO)); \ fprintf (FILE, "\tlsh\t16,ar2\n"); \ fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ fprintf (FILE, "\tcall\tmcount\n"); \ fprintf (FILE, "\tpop\tar2\n"); \ }/* CC_NOOVmode should be used when the first operand is a PLUS, MINUS, NEG or MULT. CCmode should be used when no special processing is needed. */#define SELECT_CC_MODE(OP,X,Y) \ ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ || GET_CODE (X) == NEG || GET_CODE (X) == MULT \ || GET_MODE (X) == ABS \ || GET_CODE (Y) == PLUS || GET_CODE (Y) == MINUS \ || GET_CODE (Y) == NEG || GET_CODE (Y) == MULT \ || GET_MODE (Y) == ABS) \ ? CC_NOOVmode : CCmode)/* Addressing Modes. */#define HAVE_POST_INCREMENT 1#define HAVE_PRE_INCREMENT 1#define HAVE_POST_DECREMENT 1#define HAVE_PRE_DECREMENT 1#define HAVE_PRE_MODIFY_REG 1#define HAVE_POST_MODIFY_REG 1#define HAVE_PRE_MODIFY_DISP 1#define HAVE_POST_MODIFY_DISP 1/* The number of insns that can be packed into a single opcode. */#define PACK_INSNS 2/* Recognize any constant value that is a valid address. We could allow arbitrary constant addresses in the large memory model but for the small memory model we can only accept addresses within the data page. I suppose we could also allow CONST PLUS SYMBOL_REF. */#define CONSTANT_ADDRESS_P(X) (GET_CODE (X) == SYMBOL_REF)/* Maximum number of registers that can appear in a valid memory address. */#define MAX_REGS_PER_ADDRESS 2/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. We have two alternate definitions for each of them. The usual definition accepts all pseudo regs; the other rejects them unless they have been allocated suitable hard regs. The symbol REG_OK_STRICT causes the latter definition to be used. Most source files want to accept pseudo regs in the hope that they will get allocated to the class that the insn wants them to be in. Source files for reload pass need to be strict. After reload, it makes no difference, since pseudo regs have been eliminated by then. */#ifndef REG_OK_STRICT/* Nonzero if X is a hard or pseudo reg that can be used as a base. */#define REG_OK_FOR_BASE_P(X) IS_ADDR_OR_PSEUDO_REG(X)/* Nonzero if X is a hard or pseudo reg that can be used as an index. */#define REG_OK_FOR_INDEX_P(X) IS_INDEX_OR_PSEUDO_REG(X)#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \{ \ if (c4x_legitimate_address_p (MODE, X, 0)) \ goto ADDR; \}#else/* Nonzero if X is a hard reg that can be used as an index. */#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))/* Nonzero if X is a hard reg that can be used as a base reg. */#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \{ \ if (c4x_legitimate_address_p (MODE, X, 1)) \ goto ADDR; \}#endif#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \{ \ rtx new; \ \ new = c4x_legitimize_address (X, MODE); \ if (new != NULL_RTX) \ { \ (X) = new; \ goto WIN; \ } \}#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \{ \ if (MODE != HImode \ && MODE != HFmode \ && GET_MODE (X) != HImode \ && GET_MODE (X) != HFmode \ && (GET_CODE (X) == CONST \ || GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == LABEL_REF)) \ { \ if (! TARGET_SMALL) \ { \ int i; \ (X) = gen_rtx_LO_SUM (GET_MODE (X), \ gen_rtx_HIGH (GET_MODE (X), X), X); \ i = push_reload (XEXP (X, 0), NULL_RTX, \ &XEXP (X, 0), NULL, \ DP_REG, GET_MODE (X), VOIDmode, 0, 0, \ OPNUM, TYPE); \ /* The only valid reg is DP. This is a fixed reg and will \ normally not be used so force it. */ \ rld[i].reg_rtx = gen_rtx_REG (Pmode, DP_REGNO); \ rld[i].nocombine = 1; \ } \ else \ { \ /* make_memloc in reload will substitute invalid memory \ references. We need to fix them up. */ \ (X) = gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, DP_REGNO), (X)); \ } \ goto WIN; \ } \ else if (MODE != HImode \ && MODE != HFmode \ && GET_MODE (X) != HImode \ && GET_MODE (X) != HFmode \ && GET_CODE (X) == LO_SUM \ && GET_CODE (XEXP (X,0)) == HIGH \ && (GET_CODE (XEXP (XEXP (X,0),0)) == CONST \ || GET_CODE (XEXP (XEXP (X,0),0)) == SYMBOL_REF \ || GET_CODE (XEXP (XEXP (X,0),0)) == LABEL_REF)) \ { \ if (! TARGET_SMALL) \ { \ int i = push_reload (XEXP (X, 0), NULL_RTX, \ &XEXP (X, 0), NULL, \ DP_REG, GET_MODE (X), VOIDmode, 0, 0, \ OPNUM, TYPE); \ /* The only valid reg is DP. This is a fixed reg and will \ normally not be used so force it. */ \ rld[i].reg_rtx = gen_rtx_REG (Pmode, DP_REGNO); \ rld[i].nocombine = 1; \ } \ goto WIN; \ } \}/* No mode-dependent addresses on the C4x are autoincrements. */#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ if (GET_CODE (ADDR) == PRE_DEC \ || GET_CODE (ADDR) == POST_DEC \ || GET_CODE (ADDR) == PRE_INC \ || GET_CODE (ADDR) == POST_INC \ || GET_CODE (ADDR) == POST_MODIFY \ || GET_CODE (ADDR) == PRE_MODIFY) \ goto LABEL/* Nonzero if the constant value X is a legitimate general operand. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. The C4x can only load 16-bit immediate values, so we only allow a restricted subset of CONST_INT and CONST_DOUBLE. Disallow LABEL_REF and SYMBOL_REF (except on the C40 with the big memory model) so that the symbols will be forced into the constant pool. On second thoughts, let's do this with the move expanders since the alias analysis has trouble if we force constant addresses into memory.*/#define LEGITIMATE_CONSTANT_P(X) \ ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \ || (GET_CODE (X) == CONST_INT) \ || (GET_CODE (X) == SYMBOL_REF) \ || (GET_CODE (X) == LABEL_REF) \ || (GET_CODE (X) == CONST) \ || (GET_CODE (X) == HIGH && ! TARGET_C3X) \ || (GET_CODE (X) == LO_SUM && ! TARGET_C3X))#define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X))/* Describing Relative Cost of Operations. */#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \if (REG_P (OP1) && ! REG_P (OP0)) \{ \ rtx tmp = OP0; OP0 = OP1 ; OP1 = tmp; \ CODE = swap_condition (CODE); \}#define EXT_CLASS_P(CLASS) (reg_class_subset_p (CLASS, EXT_REGS))#define ADDR_CLASS_P(CLASS) (reg_class_subset_p (CLASS, ADDR_REGS))#define INDEX_CLASS_P(CLASS) (reg_class_subset_p (CLASS, INDEX_REGS))#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \ || INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG)/* Compute extra cost of moving data between one register class and another. */#define REGISTER_MOVE_COST(MODE, FROM, TO) 2/* Memory move cost is same as fast register move. Maybe this should be bumped up?. */#define MEMORY_MOVE_COST(M,C,I) 4/* Branches are kind of expensive (even with delayed branching) so make their cost higher. */#define BRANCH_COST 8#define WORD_REGISTER_OPERATIONS/* Dividing the Output into Sections. */#define TEXT_SECTION_ASM_OP "\t.text"#define DATA_SECTION_ASM_OP "\t.data"#define READONLY_DATA_SECTION_ASM_OP "\t.sect\t\".const\""/* Do not use .init section so __main will be called on startup. This will call __do_global_ctors and prepare for __do_global_dtors on exit. */#if 0#define INIT_SECTION_ASM_OP "\t.sect\t\".init\""#endif#define FINI_SECTION_ASM_OP "\t.sect\t\".fini\""#undef EXTRA_SECTIONS#define EXTRA_SECTIONS in_init, in_fini#undef EXTRA_SECTION_FUNCTIONS#define EXTRA_SECTION_FUNCTIONS \ INIT_SECTION_FUNCTION \ FINI_SECTION_FUNCTION#define INIT_SECTION_FUNCTION \extern void init_section (void); \void \init_section (void) \{ \ if (in_section != in_init) \ { \ fprintf (asm_out_file, ";\t.init\n"); \ in_section = in_init; \ } \}#define FINI_SECTION_FUNCTION \void \fini_section () \{ \ if (in_section != in_fini) \ { \ fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ in_section = in_fini; \ } \}/* Switch into a generic section. */#define TARGET_ASM_NAMED_SECTION c4x_asm_named_section/* Overall Framework of an Assembler File. */#define ASM_COMMENT_START ";"#define ASM_APP_ON ""#define ASM_APP_OFF ""#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) c4x_output_ascii (FILE, PTR, LEN)/* Output and Generation of Labels. */#define NO_DOT_IN_LABEL /* Only required for TI format. *//* Globalizing directive for a label. */#define GLOBAL_ASM_OP "\t.global\t"#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \c4x_external_ref (NAME)/* The prefix to add to user-visible assembler symbols. */#define USER_LABEL_PREFIX "_"/* This is how to store into the string LABEL the symbol_ref name of an internal numbered label where PREFIX is the class of label and NUM is the number within the class. This is suitable for output with `assemble_name'. */#define ASM_GENERATE_INTERNAL_LABEL(BUFFER, PREFIX, NUM) \ sprintf (BUFFER, "*%s%lu", PREFIX, (unsigned long)(NUM))/* A C statement to output to the stdio stream STREAM assembler code which defines (equates) the symbol NAME to have the value VALUE. */#define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) \do { \ assemble_name (STREAM, NAME); \ fprintf (STREAM, "\t.set\t%s\n", VALUE); \} while (0)/* Output of Dispatch Tables. *//* This is how to output an element of a case-vector that is absolute. */#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ fprintf (FILE, "\t.long\tL%d\n", VALUE);/* This is how to output an element of a case-vector that is relative. */#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long\tL%d-L%d\n", VALUE, REL);#undef SIZE_TYPE#define SIZE_TYPE "unsigned int"#undef PTRDIFF_TYPE#define PTRDIFF_TYPE "int"#undef WCHAR_TYPE#define WCHAR_TYPE "long int"#undef WCHAR_TYPE_SIZE#define WCHAR_TYPE_SIZE 32#define INT_TYPE_SIZE 32#define LONG_LONG_TYPE_SIZE 64#define FLOAT_TYPE_SIZE 32#define DOUBLE_TYPE_SIZE 32#define LONG_DOUBLE_TYPE_SIZE 64 /* Actually only 40. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -