📄 c4x.h
字号:
/* Output #ident as a .ident. */#define ASM_OUTPUT_IDENT(FILE, NAME) \ fprintf (FILE, "\t.ident \"%s\"\n", NAME);/* Output of Uninitialized Variables. *//* This says how to output an assembler line to define a local uninitialized variable. */#undef ASM_OUTPUT_LOCAL#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \( fputs ("\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ fprintf (FILE, ",%u\n", (int)(ROUNDED)))/* This says how to output an assembler line to define a global uninitialized variable. */#undef ASM_OUTPUT_COMMON#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \( fputs ("\t.globl\t", FILE), \ assemble_name (FILE, (NAME)), \ fputs ("\n\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ fprintf (FILE, ",%u\n", (int)(ROUNDED)))#undef ASM_OUTPUT_BSS#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ALIGN) \( fputs ("\t.globl\t", FILE), \ assemble_name (FILE, (NAME)), \ fputs ("\n\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ fprintf (FILE, ",%u\n", (int)(SIZE)))/* Macros Controlling Initialization Routines. */#define OBJECT_FORMAT_COFF#define REAL_NM_FILE_NAME "c4x-nm"/* Output of Assembler Instructions. *//* Register names when used for integer modes. */#define REGISTER_NAMES \{ \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ "iif", "rs", "re", "rc", "r8", "r9", "r10", "r11" \}/* Alternate register names when used for floating point modes. */#define FLOAT_REGISTER_NAMES \{ \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ "iif", "rs", "re", "rc", "f8", "f9", "f10", "f11" \}#define PRINT_OPERAND(FILE, X, CODE) c4x_print_operand(FILE, X, CODE)/* Determine which codes are valid without a following integer. These must not be alphabetic. */#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#')#define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X)/* C4x specific pragmas. */#define REGISTER_TARGET_PRAGMAS() do { \ c_register_pragma (0, "CODE_SECTION", c4x_pr_CODE_SECTION); \ c_register_pragma (0, "DATA_SECTION", c4x_pr_DATA_SECTION); \ c_register_pragma (0, "FUNC_CANNOT_INLINE", c4x_pr_ignored); \ c_register_pragma (0, "FUNC_EXT_CALLED", c4x_pr_ignored); \ c_register_pragma (0, "FUNC_IS_PURE", c4x_pr_FUNC_IS_PURE); \ c_register_pragma (0, "FUNC_IS_SYSTEM", c4x_pr_ignored); \ c_register_pragma (0, "FUNC_NEVER_RETURNS", c4x_pr_FUNC_NEVER_RETURNS); \ c_register_pragma (0, "FUNC_NO_GLOBAL_ASG", c4x_pr_ignored); \ c_register_pragma (0, "FUNC_NO_IND_ASG", c4x_pr_ignored); \ c_register_pragma (0, "INTERRUPT", c4x_pr_INTERRUPT); \} while (0)/* Assembler Commands for Alignment. */#define ASM_OUTPUT_SKIP(FILE, SIZE) \{ int c = SIZE; \ for (; c > 0; --c) \ fprintf (FILE,"\t.word\t0\n"); \}#define ASM_NO_SKIP_IN_TEXT 1/* I'm not sure about this one. FIXME. */#define ASM_OUTPUT_ALIGN(FILE, LOG) \ if ((LOG) != 0) \ fprintf (FILE, "\t.align\t%d\n", (1 << (LOG)))/* Macros for SDB and DWARF Output (use .sdef instead of .def to avoid conflict with TI's use of .def). */#define SDB_DELIM "\n"#define SDB_DEBUGGING_INFO 1/* Don't use octal since this can confuse gas for the c4x. */#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0x%x%s", a, SDB_DELIM)#define PUT_SDB_DEF(A) \do { fprintf (asm_out_file, "\t.sdef\t"); \ ASM_OUTPUT_LABELREF (asm_out_file, A); \ fprintf (asm_out_file, SDB_DELIM); } while (0)#define PUT_SDB_PLAIN_DEF(A) \ fprintf (asm_out_file,"\t.sdef\t.%s%s", A, SDB_DELIM)#define PUT_SDB_BLOCK_START(LINE) \ fprintf (asm_out_file, \ "\t.sdef\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)#define PUT_SDB_BLOCK_END(LINE) \ fprintf (asm_out_file, \ "\t.sdef\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)#define PUT_SDB_FUNCTION_START(LINE) \ fprintf (asm_out_file, \ "\t.sdef\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)/* Note we output relative line numbers for .ef which gas converts to absolute line numbers. The TI compiler outputs absolute line numbers in the .sym directive which gas does not support. */#define PUT_SDB_FUNCTION_END(LINE) \ fprintf (asm_out_file, \ "\t.sdef\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM, \ (LINE), SDB_DELIM)#define PUT_SDB_EPILOGUE_END(NAME) \do { fprintf (asm_out_file, "\t.sdef\t"); \ ASM_OUTPUT_LABELREF (asm_out_file, NAME); \ fprintf (asm_out_file, \ "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)/* Define this as 1 if `char' should by default be signed; else as 0. */#define DEFAULT_SIGNED_CHAR 1/* A function address in a call instruction is a byte address (for indexing purposes) so give the MEM rtx a byte's mode. */#define FUNCTION_MODE QImode#define SLOW_BYTE_ACCESS 0/* 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 QImode/* On the C4x we can write the following code. We have to clear the cache every time we execute it because the data in the stack could change. laj $+4 addi3 4,r11,ar0 lda *ar0,ar1 lda *+ar0(1),ar0 bud ar1 nop nop or 1000h,st .word FNADDR .word CXT On the c3x this is a bit more difficult. We have to write self modifying code here. So we have to clear the cache every time we execute it because the data in the stack could change. ldiu TOP_OF_FUNCTION,ar1 lsh 16,ar1 or BOTTOM_OF_FUNCTION,ar1 ldiu TOP_OF_STATIC,ar0 bud ar1 lsh 16,ar0 or BOTTOM_OF_STATIC,ar0 or 1000h,st */#define TRAMPOLINE_SIZE (TARGET_C3X ? 8 : 10)#define TRAMPOLINE_TEMPLATE(FILE) \{ \ if (TARGET_C3X) \ { \ fprintf (FILE, "\tldiu\t0,ar1\n"); \ fprintf (FILE, "\tlsh\t16,ar1\n"); \ fprintf (FILE, "\tor\t0,ar1\n"); \ fprintf (FILE, "\tldiu\t0,ar0\n"); \ fprintf (FILE, "\tbud\tar1\n"); \ fprintf (FILE, "\tlsh\t16,ar0\n"); \ fprintf (FILE, "\tor\t0,ar0\n"); \ fprintf (FILE, "\tor\t1000h,st\n"); \ } \ else \ { \ fprintf (FILE, "\tlaj\t$+4\n"); \ fprintf (FILE, "\taddi3\t4,r11,ar0\n"); \ fprintf (FILE, "\tlda\t*ar0,ar1\n"); \ fprintf (FILE, "\tlda\t*+ar0(1),ar0\n"); \ fprintf (FILE, "\tbud\tar1\n"); \ fprintf (FILE, "\tnop\n"); \ fprintf (FILE, "\tnop\n"); \ fprintf (FILE, "\tor\t1000h,st\n"); \ fprintf (FILE, "\t.word\t0\n"); \ fprintf (FILE, "\t.word\t0\n"); \ } \}#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \{ \ if (TARGET_C3X) \ { \ rtx tmp1, tmp2; \ tmp1 = expand_shift (RSHIFT_EXPR, QImode, FNADDR, \ size_int (16), 0, 1); \ tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ GEN_INT (0x5069), size_int (16), 0, 1); \ emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 0)), tmp1); \ tmp1 = expand_and (QImode, FNADDR, GEN_INT (0xffff), 0); \ tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ GEN_INT (0x1069), size_int (16), 0, 1); \ emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 2)), tmp1); \ tmp1 = expand_shift (RSHIFT_EXPR, QImode, CXT, \ size_int (16), 0, 1); \ tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ GEN_INT (0x5068), size_int (16), 0, 1); \ emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 3)), tmp1); \ tmp1 = expand_and (QImode, CXT, GEN_INT (0xffff), 0); \ tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ GEN_INT (0x1068), size_int (16), 0, 1); \ emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 6)), tmp1); \ } \ else \ { \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 8)), FNADDR); \ emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 9)), CXT); \ } \}/* Specify the machine mode that this machine uses for the index in the tablejump instruction. */#define CASE_VECTOR_MODE Pmode/* Max number of (32-bit) bytes we can move from memory to memory in one reasonably fast instruction. */#define MOVE_MAX 1/* MOVE_RATIO is the number of move instructions that is better than a block move. */#define MOVE_RATIO 3#define BSS_SECTION_ASM_OP "\t.bss"#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ fprintf (FILE, "\tpush\t%s\n", reg_names[REGNO])/* This is how to output an insn to pop a register from the stack. It need not be very fast code. */#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ fprintf (FILE, "\tpop\t%s\n", reg_names[REGNO])/* 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#define DBR_OUTPUT_SEQEND(FILE) \if (final_sequence != NULL_RTX) \{ \ int count; \ rtx insn = XVECEXP (final_sequence, 0, 0); \ int laj = GET_CODE (insn) == CALL_INSN \ || (GET_CODE (insn) == INSN \ && GET_CODE (PATTERN (insn)) == TRAP_IF);\ \ count = dbr_sequence_length(); \ while (count < (laj ? 2 : 3)) \ { \ fputs("\tnop\n", FILE); \ count++; \ } \ if (laj) \ fputs("\tpush\tr11\n", FILE); \}#define NO_FUNCTION_CSE/* We don't want a leading tab. */#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING)/* Define the codes that are matched by predicates in c4x.c. */#define PREDICATE_CODES \ {"fp_zero_operand", {CONST_DOUBLE}}, \ {"const_operand", {CONST_INT, CONST_DOUBLE}}, \ {"stik_const_operand", {CONST_INT}}, \ {"not_const_operand", {CONST_INT}}, \ {"reg_operand", {REG, SUBREG}}, \ {"reg_or_const_operand", {REG, SUBREG, CONST_INT, CONST_DOUBLE}},\ {"r0r1_reg_operand", {REG, SUBREG}}, \ {"r2r3_reg_operand", {REG, SUBREG}}, \ {"ext_low_reg_operand", {REG, SUBREG}}, \ {"ext_reg_operand", {REG, SUBREG}}, \ {"std_reg_operand", {REG, SUBREG}}, \ {"std_or_reg_operand", {REG, SUBREG}}, \ {"addr_reg_operand", {REG, SUBREG}}, \ {"index_reg_operand", {REG, SUBREG}}, \ {"dp_reg_operand", {REG}}, \ {"sp_reg_operand", {REG}}, \ {"st_reg_operand", {REG}}, \ {"rc_reg_operand", {REG}}, \ {"call_address_operand", {REG, SYMBOL_REF, LABEL_REF, CONST}}, \ {"dst_operand", {SUBREG, REG, MEM}}, \ {"src_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ {"src_hi_operand", {SUBREG, REG, MEM, CONST_DOUBLE}}, \ {"lsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ {"tsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ {"nonimmediate_src_operand", {SUBREG, REG, MEM}}, \ {"nonimmediate_lsrc_operand", {SUBREG, REG, MEM}}, \ {"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ {"par_ind_operand", {MEM}}, \ {"parallel_operand", {SUBREG, REG, MEM}}, \ {"symbolic_address_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \ {"mem_operand", {MEM}}, /* Define the intrinsic functions for the c3x/c4x. */enum c4x_builtins{ /* intrinsic name */ C4X_BUILTIN_FIX, /* fast_ftoi */ C4X_BUILTIN_FIX_ANSI, /* ansi_ftoi */ C4X_BUILTIN_MPYI, /* fast_imult (only C3x) */ C4X_BUILTIN_TOIEEE, /* toieee (only C4x) */ C4X_BUILTIN_FRIEEE, /* frieee (only C4x) */ C4X_BUILTIN_RCPF /* fast_invf (only C4x) */};/* Hack to overcome use of libgcc2.c using auto-host.h to determine HAVE_GAS_HIDDEN.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -