📄 c4x.c
字号:
/* Subroutines for assembler code output on the TMS320C[34]x Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).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. *//* Some output-actions in c4x.md need these. */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "tree.h"#include "regs.h"#include "hard-reg-set.h"#include "basic-block.h"#include "real.h"#include "insn-config.h"#include "insn-attr.h"#include "conditions.h"#include "output.h"#include "function.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "flags.h"#include "recog.h"#include "ggc.h"#include "cpplib.h"#include "toplev.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "langhooks.h"rtx smulhi3_libfunc;rtx umulhi3_libfunc;rtx fix_truncqfhi2_libfunc;rtx fixuns_truncqfhi2_libfunc;rtx fix_trunchfhi2_libfunc;rtx fixuns_trunchfhi2_libfunc;rtx floathiqf2_libfunc;rtx floatunshiqf2_libfunc;rtx floathihf2_libfunc;rtx floatunshihf2_libfunc;static int c4x_leaf_function;static const char *const float_reg_names[] = FLOAT_REGISTER_NAMES;/* Array of the smallest class containing reg number REGNO, indexed by REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these registers are available and set the class to NO_REGS for registers that the target switches say are unavailable. */enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] ={ /* Reg Modes Saved. */ R0R1_REGS, /* R0 QI, QF, HF No. */ R0R1_REGS, /* R1 QI, QF, HF No. */ R2R3_REGS, /* R2 QI, QF, HF No. */ R2R3_REGS, /* R3 QI, QF, HF No. */ EXT_LOW_REGS, /* R4 QI, QF, HF QI. */ EXT_LOW_REGS, /* R5 QI, QF, HF QI. */ EXT_LOW_REGS, /* R6 QI, QF, HF QF. */ EXT_LOW_REGS, /* R7 QI, QF, HF QF. */ ADDR_REGS, /* AR0 QI No. */ ADDR_REGS, /* AR1 QI No. */ ADDR_REGS, /* AR2 QI No. */ ADDR_REGS, /* AR3 QI QI. */ ADDR_REGS, /* AR4 QI QI. */ ADDR_REGS, /* AR5 QI QI. */ ADDR_REGS, /* AR6 QI QI. */ ADDR_REGS, /* AR7 QI QI. */ DP_REG, /* DP QI No. */ INDEX_REGS, /* IR0 QI No. */ INDEX_REGS, /* IR1 QI No. */ BK_REG, /* BK QI QI. */ SP_REG, /* SP QI No. */ ST_REG, /* ST CC No. */ NO_REGS, /* DIE/IE No. */ NO_REGS, /* IIE/IF No. */ NO_REGS, /* IIF/IOF No. */ INT_REGS, /* RS QI No. */ INT_REGS, /* RE QI No. */ RC_REG, /* RC QI No. */ EXT_REGS, /* R8 QI, QF, HF QI. */ EXT_REGS, /* R9 QI, QF, HF No. */ EXT_REGS, /* R10 QI, QF, HF No. */ EXT_REGS, /* R11 QI, QF, HF No. */};enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] ={ /* Reg Modes Saved. */ HFmode, /* R0 QI, QF, HF No. */ HFmode, /* R1 QI, QF, HF No. */ HFmode, /* R2 QI, QF, HF No. */ HFmode, /* R3 QI, QF, HF No. */ QFmode, /* R4 QI, QF, HF QI. */ QFmode, /* R5 QI, QF, HF QI. */ QImode, /* R6 QI, QF, HF QF. */ QImode, /* R7 QI, QF, HF QF. */ QImode, /* AR0 QI No. */ QImode, /* AR1 QI No. */ QImode, /* AR2 QI No. */ QImode, /* AR3 QI QI. */ QImode, /* AR4 QI QI. */ QImode, /* AR5 QI QI. */ QImode, /* AR6 QI QI. */ QImode, /* AR7 QI QI. */ VOIDmode, /* DP QI No. */ QImode, /* IR0 QI No. */ QImode, /* IR1 QI No. */ QImode, /* BK QI QI. */ VOIDmode, /* SP QI No. */ VOIDmode, /* ST CC No. */ VOIDmode, /* DIE/IE No. */ VOIDmode, /* IIE/IF No. */ VOIDmode, /* IIF/IOF No. */ QImode, /* RS QI No. */ QImode, /* RE QI No. */ VOIDmode, /* RC QI No. */ QFmode, /* R8 QI, QF, HF QI. */ HFmode, /* R9 QI, QF, HF No. */ HFmode, /* R10 QI, QF, HF No. */ HFmode, /* R11 QI, QF, HF No. */};/* Test and compare insns in c4x.md store the information needed to generate branch and scc insns here. */rtx c4x_compare_op0;rtx c4x_compare_op1;const char *c4x_rpts_cycles_string;int c4x_rpts_cycles = 0; /* Max. cycles for RPTS. */const char *c4x_cpu_version_string;int c4x_cpu_version = 40; /* CPU version C30/31/32/33/40/44. *//* Pragma definitions. */tree code_tree = NULL_TREE;tree data_tree = NULL_TREE;tree pure_tree = NULL_TREE;tree noreturn_tree = NULL_TREE;tree interrupt_tree = NULL_TREE;tree naked_tree = NULL_TREE;/* Forward declarations */static int c4x_isr_reg_used_p (unsigned int);static int c4x_leaf_function_p (void);static int c4x_naked_function_p (void);static int c4x_immed_float_p (rtx);static int c4x_a_register (rtx);static int c4x_x_register (rtx);static int c4x_immed_int_constant (rtx);static int c4x_immed_float_constant (rtx);static int c4x_K_constant (rtx);static int c4x_N_constant (rtx);static int c4x_O_constant (rtx);static int c4x_R_indirect (rtx);static int c4x_S_indirect (rtx);static void c4x_S_address_parse (rtx , int *, int *, int *, int *);static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int);static void c4x_file_start (void);static void c4x_file_end (void);static void c4x_check_attribute (const char *, tree, tree, tree *);static int c4x_r11_set_p (rtx);static int c4x_rptb_valid_p (rtx, rtx);static void c4x_reorg (void);static int c4x_label_ref_used_p (rtx, rtx);static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);const struct attribute_spec c4x_attribute_table[];static void c4x_insert_attributes (tree, tree *);static void c4x_asm_named_section (const char *, unsigned int, tree);static int c4x_adjust_cost (rtx, rtx, rtx, int);static void c4x_globalize_label (FILE *, const char *);static bool c4x_rtx_costs (rtx, int, int, int *);static int c4x_address_cost (rtx);static void c4x_init_libfuncs (void);static void c4x_external_libcall (rtx);static rtx c4x_struct_value_rtx (tree, int);static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);/* Initialize the GCC target structure. */#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\t.word\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP NULL#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP NULL#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START c4x_file_start#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true#undef TARGET_ASM_FILE_END#define TARGET_ASM_FILE_END c4x_file_end#undef TARGET_ASM_EXTERNAL_LIBCALL#define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table#undef TARGET_INSERT_ATTRIBUTES#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS c4x_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN c4x_expand_builtin#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST c4x_adjust_cost#undef TARGET_ASM_GLOBALIZE_LABEL#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS c4x_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST c4x_address_cost#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG c4x_reorg#undef TARGET_INIT_LIBFUNCS#define TARGET_INIT_LIBFUNCS c4x_init_libfuncs#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx#undef TARGET_GIMPLIFY_VA_ARG_EXPR#define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_exprstruct gcc_target targetm = TARGET_INITIALIZER;/* Override command line options. Called once after all options have been parsed. Mostly we process the processor type and sometimes adjust other TARGET_ options. */voidc4x_override_options (void){ if (c4x_rpts_cycles_string) c4x_rpts_cycles = atoi (c4x_rpts_cycles_string); else c4x_rpts_cycles = 0; if (TARGET_C30) c4x_cpu_version = 30; else if (TARGET_C31) c4x_cpu_version = 31; else if (TARGET_C32) c4x_cpu_version = 32; else if (TARGET_C33) c4x_cpu_version = 33; else if (TARGET_C40) c4x_cpu_version = 40; else if (TARGET_C44) c4x_cpu_version = 44; else c4x_cpu_version = 40; /* -mcpu=xx overrides -m40 etc. */ if (c4x_cpu_version_string) { const char *p = c4x_cpu_version_string; /* Also allow -mcpu=c30 etc. */ if (*p == 'c' || *p == 'C') p++; c4x_cpu_version = atoi (p); } target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG | C40_FLAG | C44_FLAG); switch (c4x_cpu_version) { case 30: target_flags |= C30_FLAG; break; case 31: target_flags |= C31_FLAG; break; case 32: target_flags |= C32_FLAG; break; case 33: target_flags |= C33_FLAG; break; case 40: target_flags |= C40_FLAG; break; case 44: target_flags |= C44_FLAG; break; default: warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version); c4x_cpu_version = 40; target_flags |= C40_FLAG; } if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33) target_flags |= C3X_FLAG; else target_flags &= ~C3X_FLAG; /* Convert foo / 8.0 into foo * 0.125, etc. */ set_fast_math_flags (1); /* We should phase out the following at some stage. This provides compatibility with the old -mno-aliases option. */ if (! TARGET_ALIASES && ! flag_argument_noalias) flag_argument_noalias = 1;}/* This is called before c4x_override_options. */voidc4x_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED){ /* Scheduling before register allocation can screw up global register allocation, especially for functions that use MPY||ADD instructions. The benefit we gain we get by scheduling before register allocation is probably marginal anyhow. */ flag_schedule_insns = 0;}/* Write an ASCII string. */#define C4X_ASCII_LIMIT 40voidc4x_output_ascii (FILE *stream, const char *ptr, int len){ char sbuf[C4X_ASCII_LIMIT + 1]; int s, l, special, first = 1, onlys; if (len) fprintf (stream, "\t.byte\t"); for (s = l = 0; len > 0; --len, ++ptr) { onlys = 0; /* Escape " and \ with a \". */ special = *ptr == '\"' || *ptr == '\\'; /* If printable - add to buff. */ if ((! TARGET_TI || ! special) && *ptr >= 0x20 && *ptr < 0x7f) { if (special) sbuf[s++] = '\\'; sbuf[s++] = *ptr; if (s < C4X_ASCII_LIMIT - 1) continue; onlys = 1; } if (s) { if (first) first = 0; else { fputc (',', stream); l++; } sbuf[s] = 0; fprintf (stream, "\"%s\"", sbuf); l += s + 2; if (TARGET_TI && l >= 80 && len > 1) { fprintf (stream, "\n\t.byte\t"); first = 1; l = 0; } s = 0; } if (onlys) continue; if (first) first = 0; else { fputc (',', stream); l++; } fprintf (stream, "%d", *ptr); l += 3; if (TARGET_TI && l >= 80 && len > 1) { fprintf (stream, "\n\t.byte\t"); first = 1; l = 0; } } if (s) { if (! first) fputc (',', stream); sbuf[s] = 0; fprintf (stream, "\"%s\"", sbuf); s = 0; } fputc ('\n', stream);}intc4x_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode){ switch (mode) {#if Pmode != QImode case Pmode: /* Pointer (24/32 bits). */#endif case QImode: /* Integer (32 bits). */ return IS_INT_REGNO (regno); case QFmode: /* Float, Double (32 bits). */ case HFmode: /* Long Double (40 bits). */ return IS_EXT_REGNO (regno); case CCmode: /* Condition Codes. */ case CC_NOOVmode: /* Condition Codes. */ return IS_ST_REGNO (regno); case HImode: /* Long Long (64 bits). */ /* We need two registers to store long longs. Note that it is much easier to constrain the first register to start on an even boundary. */ return IS_INT_REGNO (regno) && IS_INT_REGNO (regno + 1) && (regno & 1) == 0; default: return 0; /* We don't support these modes. */ } return 0;}/* Return nonzero if REGNO1 can be renamed to REGNO2. */intc4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2){ /* We cannot copy call saved registers from mode QI into QF or from mode QF into QI. */ if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2)) return 0; if (IS_INT_CALL_SAVED_REGNO (regno1) && IS_FLOAT_CALL_SAVED_REGNO (regno2)) return 0; /* We cannot copy from an extended (40 bit) register to a standard (32 bit) register because we only set the condition codes for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -