📄 xtensa.h
字号:
/* Identify valid Xtensa addresses. */#define GO_IF_LEGITIMATE_ADDRESS(MODE, ADDR, LABEL) \ do { \ rtx xinsn = (ADDR); \ \ /* allow constant pool addresses */ \ if ((MODE) != BLKmode && GET_MODE_SIZE (MODE) >= UNITS_PER_WORD \ && !TARGET_CONST16 && constantpool_address_p (xinsn)) \ goto LABEL; \ \ while (GET_CODE (xinsn) == SUBREG) \ xinsn = SUBREG_REG (xinsn); \ \ /* allow base registers */ \ if (GET_CODE (xinsn) == REG && REG_OK_FOR_BASE_P (xinsn)) \ goto LABEL; \ \ /* check for "register + offset" addressing */ \ if (GET_CODE (xinsn) == PLUS) \ { \ rtx xplus0 = XEXP (xinsn, 0); \ rtx xplus1 = XEXP (xinsn, 1); \ enum rtx_code code0; \ enum rtx_code code1; \ \ while (GET_CODE (xplus0) == SUBREG) \ xplus0 = SUBREG_REG (xplus0); \ code0 = GET_CODE (xplus0); \ \ while (GET_CODE (xplus1) == SUBREG) \ xplus1 = SUBREG_REG (xplus1); \ code1 = GET_CODE (xplus1); \ \ /* swap operands if necessary so the register is first */ \ if (code0 != REG && code1 == REG) \ { \ xplus0 = XEXP (xinsn, 1); \ xplus1 = XEXP (xinsn, 0); \ code0 = GET_CODE (xplus0); \ code1 = GET_CODE (xplus1); \ } \ \ if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) \ && code1 == CONST_INT \ && xtensa_mem_offset (INTVAL (xplus1), (MODE))) \ { \ goto LABEL; \ } \ } \ } while (0)/* A C expression that is 1 if the RTX X is a constant which is a valid address. This is defined to be the same as 'CONSTANT_P (X)', but rejecting CONST_DOUBLE. */#define CONSTANT_ADDRESS_P(X) \ ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ || (GET_CODE (X) == CONST)))/* Nonzero if the constant value X is a legitimate general operand. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */#define LEGITIMATE_CONSTANT_P(X) 1/* A C expression that is nonzero if X is a legitimate immediate operand on the target machine when generating position independent code. */#define LEGITIMATE_PIC_OPERAND_P(X) \ ((GET_CODE (X) != SYMBOL_REF \ || (SYMBOL_REF_LOCAL_P (X) && !SYMBOL_REF_EXTERNAL_P (X))) \ && GET_CODE (X) != LABEL_REF \ && GET_CODE (X) != CONST)/* Tell GCC how to use ADDMI to generate addresses. */#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ do { \ rtx xinsn = (X); \ if (GET_CODE (xinsn) == PLUS) \ { \ rtx plus0 = XEXP (xinsn, 0); \ rtx plus1 = XEXP (xinsn, 1); \ \ if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG) \ { \ plus0 = XEXP (xinsn, 1); \ plus1 = XEXP (xinsn, 0); \ } \ \ if (GET_CODE (plus0) == REG \ && GET_CODE (plus1) == CONST_INT \ && !xtensa_mem_offset (INTVAL (plus1), MODE) \ && !xtensa_simm8 (INTVAL (plus1)) \ && xtensa_mem_offset (INTVAL (plus1) & 0xff, MODE) \ && xtensa_simm8x256 (INTVAL (plus1) & ~0xff)) \ { \ rtx temp = gen_reg_rtx (Pmode); \ emit_insn (gen_rtx_SET (Pmode, temp, \ gen_rtx_PLUS (Pmode, plus0, \ GEN_INT (INTVAL (plus1) & ~0xff)))); \ (X) = gen_rtx_PLUS (Pmode, temp, \ GEN_INT (INTVAL (plus1) & 0xff)); \ goto WIN; \ } \ } \ } while (0)/* Treat constant-pool references as "mode dependent" since they can only be accessed with SImode loads. This works around a bug in the combiner where a constant pool reference is temporarily converted to an HImode load, which is then assumed to zero-extend based on our definition of LOAD_EXTEND_OP. This is wrong because the high bits of a 16-bit value in the constant pool are now sign-extended by default. */#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ do { \ if (constantpool_address_p (ADDR)) \ goto LABEL; \ } while (0)/* Specify the machine mode that this machine uses for the index in the tablejump instruction. */#define CASE_VECTOR_MODE (SImode)/* Define this as 1 if 'char' should by default be signed; else as 0. */#define DEFAULT_SIGNED_CHAR 0/* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */#define MOVE_MAX 4#define MAX_MOVE_MAX 4/* Prefer word-sized loads. */#define SLOW_BYTE_ACCESS 1/* Shift instructions ignore all but the low-order few bits. */#define SHIFT_COUNT_TRUNCATED 1/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1/* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. */#define Pmode SImode/* A function address in a call instruction is a word address (for indexing purposes) so give the MEM rtx a words's mode. */#define FUNCTION_MODE SImode/* A C expression for the cost of moving data from a register in class FROM to one in class TO. The classes are expressed using the enumeration values such as 'GENERAL_REGS'. A value of 2 is the default; other values are interpreted relative to that. */#define REGISTER_MOVE_COST(MODE, FROM, TO) \ (((FROM) == (TO) && (FROM) != BR_REGS && (TO) != BR_REGS) \ ? 2 \ : (reg_class_subset_p ((FROM), AR_REGS) \ && reg_class_subset_p ((TO), AR_REGS) \ ? 2 \ : (reg_class_subset_p ((FROM), AR_REGS) \ && (TO) == ACC_REG \ ? 3 \ : ((FROM) == ACC_REG \ && reg_class_subset_p ((TO), AR_REGS) \ ? 3 \ : 10))))#define MEMORY_MOVE_COST(MODE, CLASS, IN) 4#define BRANCH_COST 3/* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */#define REGISTER_NAMES \{ \ "a0", "sp", "a2", "a3", "a4", "a5", "a6", "a7", \ "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", \ "fp", "argp", "b0", \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ "acc" \}/* If defined, a C initializer for an array of structures containing a name and a register number. This macro defines additional names for hard registers, thus allowing the 'asm' option in declarations to refer to registers using alternate names. */#define ADDITIONAL_REGISTER_NAMES \{ \ { "a1", 1 + GP_REG_FIRST } \}#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)/* Recognize machine-specific patterns that may appear within constants. Used for PIC-specific UNSPECs. */#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ do { \ if (flag_pic && GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \ { \ switch (XINT ((X), 1)) \ { \ case UNSPEC_PLT: \ output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \ fputs ("@PLT", (STREAM)); \ break; \ default: \ goto FAIL; \ } \ break; \ } \ else \ goto FAIL; \ } while (0)/* Globalizing directive for a label. */#define GLOBAL_ASM_OP "\t.global\t"/* Declare an uninitialized external linkage data object. */#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)/* This is how to output an element of a case-vector that is absolute. */#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ fprintf (STREAM, "%s%sL%u\n", integer_asm_op (4, TRUE), \ LOCAL_LABEL_PREFIX, VALUE)/* This is how to output an element of a case-vector that is relative. This is used for pc-relative code. */#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ do { \ fprintf (STREAM, "%s%sL%u-%sL%u\n", integer_asm_op (4, TRUE), \ LOCAL_LABEL_PREFIX, (VALUE), \ LOCAL_LABEL_PREFIX, (REL)); \ } while (0)/* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes. */#define ASM_OUTPUT_ALIGN(STREAM, LOG) \ do { \ if ((LOG) != 0) \ fprintf (STREAM, "\t.align\t%d\n", 1 << (LOG)); \ } while (0)/* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)/* Define the strings to put out for each section in the object file. */#define TEXT_SECTION_ASM_OP "\t.text"#define DATA_SECTION_ASM_OP "\t.data"#define BSS_SECTION_ASM_OP "\t.section\t.bss"/* Define output to appear before the constant pool. If the function has been assigned to a specific ELF section, or if it goes into a unique section, set the name of that section to be the literal prefix. */#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE) \ do { \ tree fnsection; \ resolve_unique_section ((FUNDECL), 0, flag_function_sections); \ fnsection = DECL_SECTION_NAME (FUNDECL); \ if (fnsection != NULL_TREE) \ { \ const char *fnsectname = TREE_STRING_POINTER (fnsection); \ fprintf (FILE, "\t.begin\tliteral_prefix %s\n", \ strcmp (fnsectname, ".text") ? fnsectname : ""); \ } \ if ((SIZE) > 0) \ { \ function_section (FUNDECL); \ fprintf (FILE, "\t.literal_position\n"); \ } \ } while (0)/* Define code to write out the ".end literal_prefix" directive for a function in a special section. This is appended to the standard ELF code for ASM_DECLARE_FUNCTION_SIZE. */#define XTENSA_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ if (DECL_SECTION_NAME (DECL) != NULL_TREE) \ fprintf (FILE, "\t.end\tliteral_prefix\n")/* A C statement (with or without semicolon) to output a constant in the constant pool, if it needs special treatment. */#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, JUMPTO) \ do { \ xtensa_output_literal (FILE, X, MODE, LABELNO); \ goto JUMPTO; \ } while (0)/* How to start an assembler comment. */#define ASM_COMMENT_START "#"/* Exception handling TODO!! */#define DWARF_UNWIND_INFO 0/* Xtensa constant pool breaks the devices in crtstuff.c to control section in where code resides. We have to write it as asm code. Use a MOVI and let the assembler relax it -- for the .init and .fini sections, the assembler knows to put the literal in the right place. */#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ asm (SECTION_OP "\n\ movi\ta8, " USER_LABEL_PREFIX #FUNC "\n\ callx8\ta8\n" \ TEXT_SECTION_ASM_OP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -