X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Fc4x%2Fc4x.h;h=1112ab82736fd77a57fd0013e55271d3e3ee7d1c;hp=ca80cd77d9fac0d483753a24329761ac142b6107;hb=f054eb3c16ec5aec863986d2e14a6174a77e3cd4;hpb=6a7f5ce58a9dc8219d926503105456841d7bbc06 diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h index ca80cd77d9f..1112ab82736 100644 --- a/gcc/config/c4x/c4x.h +++ b/gcc/config/c4x/c4x.h @@ -1,33 +1,84 @@ /* Definitions of target machine for GNU compiler. TMS320C[34]x - Copyright (C) 1994, 1995, 1996, 1997, 1998, - 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 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 GNU CC. + This file is part of GCC. - GNU CC is free software; you can redistribute it and/or modify + GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - GNU CC is distributed in the hope that it will be useful, + GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with GNU CC; see the file COPYING. If not, write to + along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "hwint.h" - /* RUN-TIME TARGET SPECIFICATION. */ #define C4x 1 +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + extern int flag_inline_trees; \ + if (!TARGET_SMALL) \ + builtin_define ("_BIGMODEL"); \ + if (!TARGET_MEMPARM) \ + builtin_define ("_REGPARM"); \ + if (flag_inline_functions) \ + builtin_define ("_INLINE"); \ + if (TARGET_C3X) \ + { \ + builtin_define ("_TMS320C3x"); \ + builtin_define ("_C3x"); \ + if (TARGET_C30) \ + { \ + builtin_define ("_TMS320C30"); \ + builtin_define ("_C30"); \ + } \ + else if (TARGET_C31) \ + { \ + builtin_define ("_TMS320C31"); \ + builtin_define ("_C31"); \ + } \ + else if (TARGET_C32) \ + { \ + builtin_define ("_TMS320C32"); \ + builtin_define ("_C32"); \ + } \ + else if (TARGET_C33) \ + { \ + builtin_define ("_TMS320C33"); \ + builtin_define ("_C33"); \ + } \ + } \ + else \ + { \ + builtin_define ("_TMS320C4x"); \ + builtin_define ("_C4x"); \ + if (TARGET_C40) \ + { \ + builtin_define ("_TMS320C40"); \ + builtin_define ("_C40"); \ + } \ + else if (TARGET_C44) \ + { \ + builtin_define ("_TMS320C44"); \ + builtin_define ("_C44"); \ + } \ + } \ + } \ + while (0) + /* Name of the c4x assembler. */ #define ASM_PROG "c4x-as" @@ -40,23 +91,21 @@ #define ASM_SPEC "\ %{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=33:%{!mcpu=40:%{!mcpu=44:\ -%{!m30:%{!m40:-m40}}}}}}}} \ -%{mcpu=30:-m30} \ -%{mcpu=31:-m31} \ -%{mcpu=32:-m32} \ -%{mcpu=33:-m33} \ -%{mcpu=40:-m40} \ -%{mcpu=44:-m44} \ -%{m30:-m30} \ -%{m31:-m31} \ -%{m32:-m32} \ -%{m33:-m33} \ -%{m40:-m40} \ -%{m44:-m44} \ -%{mmemparm:-p} %{mregparm:-r} \ -%{!mmemparm:%{!mregparm:-r}} \ -%{mbig:-b} %{msmall:-s} \ -%{!msmall:%{!mbig:-b}}" +%{!m30:%{!m31:%{!m32:%{!m33:%{!m40:%{!m44:-m40}}}}}}}}}}}} \ +%{mcpu=30} \ +%{mcpu=31} \ +%{mcpu=32} \ +%{mcpu=33} \ +%{mcpu=40} \ +%{mcpu=44} \ +%{m30} \ +%{m31} \ +%{m32} \ +%{m33} \ +%{m40} \ +%{m44} \ +%{mmemparm} %{mregparm} %{!mmemparm:%{!mregparm:-mregparm}} \ +%{mbig} %{msmall} %{!msmall:%{!mbig:-mbig}}" /* Define linker options. */ @@ -70,30 +119,6 @@ %{mcpu=32:--architecture c3x} \ %{mcpu=33:--architecture c3x}" -/* Define C preprocessor options. */ - -#define CPP_SPEC "\ -%{!m30:%{!m31:%{!m32:%{!m33:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=33:\ -%{!mcpu=40:%{!mcpu=44:%{\ -!m40:%{!m44:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40}}}}}}}}}}}} \ -%{mcpu=30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \ -%{m30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \ -%{mcpu=31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \ -%{m31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \ -%{mcpu=32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \ -%{m32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \ -%{mcpu=33:-D_TMS320C3x -D_C3x -D_TMS320C33 -D_C33 } \ -%{m33:-D_TMS320C3x -D_C3x -D_TMS320C33 -D_C33 } \ -%{mcpu=40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \ -%{m40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \ -%{mcpu=44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \ -%{m44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \ -%{mmemparm:-U_REGPARM }%{mregparm:-D_REGPARM } \ -%{!mmemparm:%{!mregparm:-D_REGPARM }} \ -%{msmall:-U_BIGMODEL } %{mbig:-D_BIGMODEL } \ -%{!msmall:%{!mbig:-D_BIGMODEL }} \ -%{finline-functions:-D_INLINE }" - /* Specify the end file to link with. */ #define ENDFILE_SPEC "" @@ -124,7 +149,7 @@ #define C30_FLAG 0x0100000 /* Emit C30 code. */ #define C31_FLAG 0x0200000 /* Emit C31 code. */ #define C32_FLAG 0x0400000 /* Emit C32 code. */ -#define C33_FLAG 0x0400000 /* Emit C33 code. */ +#define C33_FLAG 0x0800000 /* Emit C33 code. */ #define C40_FLAG 0x1000000 /* Emit C40 code. */ #define C44_FLAG 0x2000000 /* Emit C44 code. */ @@ -210,7 +235,7 @@ { "no-force", -FORCE_FLAG, \ N_("Allow RTL generation to emit invalid 3 operand insns") }, \ { "loop-unsigned", LOOP_UNSIGNED_FLAG, \ - N_("Allow unsigned interation counts for RPTB/DB") }, \ + N_("Allow unsigned iteration counts for RPTB/DB") }, \ { "no-loop-unsigned", -LOOP_UNSIGNED_FLAG, \ N_("Disallow unsigned iteration counts for RPTB/DB") }, \ { "preserve-float", PRESERVE_FLOAT_FLAG, \ @@ -279,44 +304,32 @@ extern int target_flags; #define TARGET_C40 (target_flags & C40_FLAG) #define TARGET_C44 (target_flags & C44_FLAG) -/* Define some options to control code generation. */ +/* Nonzero to use load_immed_addr pattern rather than forcing memory + addresses into memory. */ #define TARGET_LOAD_ADDRESS (1 || (! TARGET_C3X && ! TARGET_SMALL)) + +/* Nonzero to convert direct memory references into HIGH/LO_SUM pairs + during RTL generation. */ #define TARGET_EXPOSE_LDP 0 +/* Nonzero to force loading of direct memory references into a register. */ +#define TARGET_LOAD_DIRECT_MEMS 0 + /* -mrpts allows the use of the RPTS instruction irregardless. -mrpts=max-cycles will use RPTS if the number of cycles is constant and less than max-cycles. */ #define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles) -#define BCT_CHECK_LOOP_ITERATIONS !(TARGET_LOOP_UNSIGNED) - /* -mcpu=XX with XX = target DSP version number. */ -/* This macro is similar to `TARGET_SWITCHES' but defines names of - command options that have values. Its definition is an - initializer with a subgrouping for each command option. - - Each subgrouping contains a string constant, that defines the - fixed part of the option name, and the address of a variable. - The variable, type `char *', is set to the variable part of the - given option if the fixed part matches. The actual option name - is made by appending `-m' to the specified name. - - Here is an example which defines `-mshort-data-NUMBER'. If the - given option is `-mshort-data-512', the variable `m88k_short_data' - will be set to the string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ - extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; #define TARGET_OPTIONS \ { {"rpts=", &c4x_rpts_cycles_string, \ - N_("Specify maximum number of iterations for RPTS") }, \ + N_("Specify maximum number of iterations for RPTS"), 0}, \ {"cpu=", &c4x_cpu_version_string, \ - N_("Select CPU to generate code for") } } + N_("Select CPU to generate code for"), 0} } /* Sometimes certain combinations of command options do not make sense on a particular target machine. You can define a macro @@ -352,9 +365,7 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; sizeof(int) = sizeof(long) = sizeof(float) = sizeof(double) = 1. */ #define BITS_PER_UNIT 32 -#define BITS_PER_WORD 32 #define UNITS_PER_WORD 1 -#define POINTER_SIZE 32 #define PARM_BOUNDARY 32 #define STACK_BOUNDARY 32 #define FUNCTION_BOUNDARY 32 @@ -365,19 +376,15 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; #define MAX_FIXED_MODE_SIZE 64 /* HImode. */ /* If a structure has a floating point field then force structure - to have BLKMODE. */ -#define STRUCT_FORCE_BLK(FIELD) (TREE_CODE (TREE_TYPE (FIELD)) == REAL_TYPE) + to have BLKMODE, unless it is the only field. */ +#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ + (TREE_CODE (TREE_TYPE (FIELD)) == REAL_TYPE && (MODE) == VOIDmode) /* Number of bits in the high and low parts of a two stage load of an immediate constant. */ #define BITS_PER_HIGH 16 #define BITS_PER_LO_SUM 16 -/* Use the internal floating point stuff in the compiler and not the - host floating point stuff. */ - -#define REAL_ARITHMETIC - /* Define register numbers. */ /* Extended-precision registers. */ @@ -488,6 +495,9 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; || IS_BK_REGNO(r)) #define IS_INT_REGNO(r) (IS_EXT_REGNO(r) || IS_STD_REGNO(r)) #define IS_GROUP1_REGNO(r) (IS_ADDR_OR_INDEX_REGNO(r) || IS_BK_REGNO(r)) +#define IS_INT_CALL_SAVED_REGNO(r) (((r) == R4_REGNO) || ((r) == R5_REGNO) \ + || ((r) == R8_REGNO)) +#define IS_FLOAT_CALL_SAVED_REGNO(r) (((r) == R6_REGNO) || ((r) == R7_REGNO)) #define IS_PSEUDO_REGNO(r) ((r) >= FIRST_PSEUDO_REGISTER) #define IS_R0R1_OR_PSEUDO_REGNO(r) (IS_R0R1_REGNO(r) || IS_PSEUDO_REGNO(r)) @@ -610,6 +620,11 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; IR0_REGNO, IR1_REGNO, \ SP_REGNO, DP_REGNO, ST_REGNO, IE_REGNO, IF_REGNO, IOF_REGNO} +/* A C expression that is nonzero if hard register number REGNO2 can be + considered for use as a rename register for REGNO1 */ + +#define HARD_REGNO_RENAME_OK(REGNO1,REGNO2) \ + c4x_hard_regno_rename_ok((REGNO1), (REGNO2)) /* Determine which register classes are very likely used by spill registers. local-alloc.c won't allocate pseudos that have these classes as their @@ -617,12 +632,16 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; #define CLASS_LIKELY_SPILLED_P(CLASS) ((CLASS) == INDEX_REGS) -/* CCmode is wrongly defined in machmode.def It should have a size - of UNITS_PER_WORD. */ +/* CCmode is wrongly defined in machmode.def. It should have a size + of UNITS_PER_WORD. HFmode is 40-bits and thus fits within a single + extended precision register. Similarly, HCmode fits within two + extended precision registers. */ #define HARD_REGNO_NREGS(REGNO, MODE) \ -(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \ -((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) +(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : \ + ((MODE) == HFmode) ? 1 : \ + ((MODE) == HCmode) ? 2 : \ + ((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) /* A C expression that is nonzero if the hard register REGNO is preserved @@ -630,13 +649,13 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; registers. */ #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \ - ((((REGNO) == R6_REGNO || (REGNO) == R7_REGNO) && ! ((MODE) == QFmode)) \ - || (((REGNO) == R4_REGNO || (REGNO) == R5_REGNO || (REGNO == R8_REGNO)) \ + ((IS_FLOAT_CALL_SAVED_REGNO (REGNO) && ! ((MODE) == QFmode)) \ + || (IS_INT_CALL_SAVED_REGNO (REGNO) \ && ! ((MODE) == QImode || (MODE) == HImode || (MODE) == Pmode))) /* Specify the modes required to caller save a given hard regno. */ -#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) (c4x_caller_save_map[REGNO]) +#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) (c4x_caller_save_map[REGNO]) #define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE) @@ -755,9 +774,9 @@ enum reg_class is defined since the MPY|ADD insns require the classes R0R1_REGS and R2R3_REGS which are used by the function return registers (R0,R1) and the register arguments (R2,R3), respectively. I'm reluctant to define - this macro since it stomps on many potential optimisations. Ideally + this macro since it stomps on many potential optimizations. Ideally it should have a register class argument so that not all the register - classes gets penalised for the sake of a naughty few... For long + classes gets penalized for the sake of a naughty few... For long double arithmetic we need two additional registers that we can use as spill registers. */ @@ -1048,8 +1067,7 @@ enum reg_class for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ offset += TARGET_PRESERVE_FLOAT \ - && ((regno == R6_REGNO) || (regno == R7_REGNO)) \ - ? 2 : 1; \ + && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ (DEPTH) = -(offset + get_frame_size ()); \ } @@ -1068,17 +1086,15 @@ enum reg_class for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ offset += TARGET_PRESERVE_FLOAT \ - && ((regno == R6_REGNO) || (regno == R7_REGNO)) \ - ? 2 : 1; \ + && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ (OFFSET) = -(offset + get_frame_size ()); \ } /* Passing Function Arguments on the Stack. */ -#if 0 +#define PUSH_ARGS 1 #define PUSH_ROUNDING(BYTES) (BYTES) -#endif #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 /* The following structure is used by calls.c, function.c, c4x.c. */ @@ -1096,7 +1112,7 @@ typedef struct c4x_args } CUMULATIVE_ARGS; -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ (c4x_init_cumulative_args (&CUM, FNTYPE, LIBNAME)) #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ @@ -1112,12 +1128,6 @@ CUMULATIVE_ARGS; #define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 -/* Never pass data by reference. */ - -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 - /* 1 if N is a possible register number for function argument passing. */ #define FUNCTION_ARG_REGNO_P(REGNO) \ @@ -1133,31 +1143,16 @@ CUMULATIVE_ARGS; /* How Scalar Function Values Are Returned. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx(REG, TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0. */ + gen_rtx_REG (TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0. */ #define LIBCALL_VALUE(MODE) \ - gen_rtx(REG, MODE, R0_REGNO) /* Return in R0. */ + 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 -#define STRUCT_VALUE_REGNUM AR0_REGNO /* AR0. */ - -/* Varargs handling. */ - -#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \ - c4x_va_start (stdarg, valist, nextarg) - -#define EXPAND_BUILTIN_VA_ARG(valist, type) \ - c4x_va_arg (valist, type) - -/* Function Entry and Exit. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) c4x_function_prologue(FILE, SIZE) -#define FUNCTION_EPILOGUE(FILE, SIZE) c4x_function_epilogue(FILE, SIZE) - /* Generating Code for Profiling. */ @@ -1185,432 +1180,6 @@ CUMULATIVE_ARGS; fprintf (FILE, "\tpop\tar2\n"); \ } -/* There are three profiling modes for basic blocks available. - The modes are selected at compile time by using the options - -a or -ax of the gnu compiler. - The variable `profile_block_flag' will be set according to the - selected option. - - profile_block_flag == 0, no option used: - - No profiling done. - - profile_block_flag == 1, -a option used. - - Count frequency of execution of every basic block. - - profile_block_flag == 2, -ax option used. - - Generate code to allow several different profiling modes at run time. - Available modes are: - Produce a trace of all basic blocks. - Count frequency of jump instructions executed. - In every mode it is possible to start profiling upon entering - certain functions and to disable profiling of some other functions. - - The result of basic-block profiling will be written to a file `bb.out'. - If the -ax option is used parameters for the profiling will be read - from file `bb.in'. - -*/ - -#define FUNCTION_BLOCK_PROFILER(FILE, BLOCKNO) \ - if (profile_block_flag == 2) \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldhi\t%d,r2\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldi\t%d,r2\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tlsh\t16,r2\n"); \ - fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } \ - else \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - fprintf (FILE, "\tcmpi\t0,*ar2\n"); \ - fprintf (FILE, "\tbne\t$+2\n"); \ - fprintf (FILE, "\tcall\t___bb_init_func\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - fprintf (FILE, "\tldi\t*ar2,r2\n"); \ - fprintf (FILE, "\tbne\t$+2\n"); \ - fprintf (FILE, "\tcall\t___bb_init_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } - -#define BLOCK_PROFILER(FILE, BLOCKNO) \ - if (profile_block_flag == 2) \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldhi\t^___bb,ar2\n"); \ - fprintf (FILE, "\tor\t#___bb,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldhi\t%d,ar0\n", (BLOCKNO) >> 16);\ - fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar0\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_func\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldiu\t^___bb,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#___bb,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldi\t%d,ar0\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tlsh\t16,ar0\n"); \ - fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar0\n"); \ - fprintf (FILE, "\tlsh\t16,ar0\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_func\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } \ - else \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldhi\t^LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\taddi3\t1,*ar2,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldiu\t^LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tldiu\t*ar2,ar0\n"); \ - fprintf (FILE, "\taddi\t1,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - } - -#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_ret\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } - -#define MACHINE_STATE_SAVE(ID) \ - asm(" push r0"); \ - asm(" pushf r0"); \ - asm(" push r1"); \ - asm(" pushf r1"); \ - asm(" push r2"); \ - asm(" pushf r2"); \ - asm(" push r3"); \ - asm(" pushf r3"); \ - asm(" push ar0"); \ - asm(" push ar1"); \ - asm(" .if .BIGMODEL"); \ - asm(" push dp"); \ - asm(" .endif"); \ - asm(" push ir0"); \ - asm(" push ir1"); \ - asm(" push bk"); \ - asm(" push rs"); \ - asm(" push re"); \ - asm(" push rc"); \ - asm(" .if .tms320C40"); \ - asm(" push r9"); \ - asm(" pushf r9"); \ - asm(" push r10"); \ - asm(" pushf r10"); \ - asm(" push r11"); \ - asm(" pushf r11"); \ - asm(" .endif"); - -#define MACHINE_STATE_RESTORE(ID) \ - asm(" .if .tms320C40"); \ - asm(" popf r11"); \ - asm(" pop r11"); \ - asm(" popf r10"); \ - asm(" pop r10"); \ - asm(" popf r9"); \ - asm(" pop r9"); \ - asm(" .endif"); \ - asm(" pop rc"); \ - asm(" pop re"); \ - asm(" pop rs"); \ - asm(" pop bk"); \ - asm(" pop ir1"); \ - asm(" pop ir0"); \ - asm(" .if .BIGMODEL"); \ - asm(" pop dp"); \ - asm(" .endif"); \ - asm(" pop ar1"); \ - asm(" pop ar0"); \ - asm(" popf r3"); \ - asm(" pop r3"); \ - asm(" popf r2"); \ - asm(" pop r2"); \ - asm(" popf r1"); \ - asm(" pop r1"); \ - asm(" popf r0"); \ - asm(" pop r0"); \ - -/* Implicit Calls to Library Routines. */ - -#define MULQI3_LIBCALL "__mulqi3" -#define DIVQI3_LIBCALL "__divqi3" -#define UDIVQI3_LIBCALL "__udivqi3" -#define MODQI3_LIBCALL "__modqi3" -#define UMODQI3_LIBCALL "__umodqi3" - -#define DIVQF3_LIBCALL "__divqf3" - -#define MULHF3_LIBCALL "__mulhf3" -#define DIVHF3_LIBCALL "__divhf3" - -#define MULHI3_LIBCALL "__mulhi3" -#define SMULHI3_LIBCALL "__smulhi3_high" -#define UMULHI3_LIBCALL "__umulhi3_high" -#define DIVHI3_LIBCALL "__divhi3" -#define UDIVHI3_LIBCALL "__udivhi3" -#define MODHI3_LIBCALL "__modhi3" -#define UMODHI3_LIBCALL "__umodhi3" - -#define FLOATHIQF2_LIBCALL "__floathiqf2" -#define FLOATUNSHIQF2_LIBCALL "__ufloathiqf2" -#define FIX_TRUNCQFHI2_LIBCALL "__fix_truncqfhi2" -#define FIXUNS_TRUNCQFHI2_LIBCALL "__ufix_truncqfhi2" - -#define FLOATHIHF2_LIBCALL "__floathihf2" -#define FLOATUNSHIHF2_LIBCALL "__ufloathihf2" -#define FIX_TRUNCHFHI2_LIBCALL "__fix_trunchfhi2" -#define FIXUNS_TRUNCHFHI2_LIBCALL "__ufix_trunchfhi2" - -#define FFS_LIBCALL "__ffs" - -#define INIT_TARGET_OPTABS \ - do { \ - smul_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (MULQI3_LIBCALL); \ - sdiv_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (DIVQI3_LIBCALL); \ - udiv_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (UDIVQI3_LIBCALL); \ - smod_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (MODQI3_LIBCALL); \ - umod_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (UMODQI3_LIBCALL); \ - flodiv_optab->handlers[(int) QFmode].libfunc \ - = init_one_libfunc (DIVQF3_LIBCALL); \ - smul_optab->handlers[(int) HFmode].libfunc \ - = init_one_libfunc (MULHF3_LIBCALL); \ - flodiv_optab->handlers[(int) HFmode].libfunc \ - = init_one_libfunc (DIVHF3_LIBCALL); \ - smul_optab->handlers[(int) HImode].libfunc \ - = init_one_libfunc (MULHI3_LIBCALL); \ - sdiv_optab->handlers[(int) HImode].libfunc \ - = init_one_libfunc (DIVHI3_LIBCALL); \ - udiv_optab->handlers[(int) HImode].libfunc \ - = init_one_libfunc (UDIVHI3_LIBCALL); \ - smod_optab->handlers[(int) HImode].libfunc \ - = init_one_libfunc (MODHI3_LIBCALL); \ - umod_optab->handlers[(int) HImode].libfunc \ - = init_one_libfunc (UMODHI3_LIBCALL); \ - ffs_optab->handlers[(int) QImode].libfunc \ - = init_one_libfunc (FFS_LIBCALL); \ - smulhi3_libfunc \ - = init_one_libfunc(SMULHI3_LIBCALL); \ - umulhi3_libfunc \ - = init_one_libfunc(UMULHI3_LIBCALL); \ - fix_truncqfhi2_libfunc \ - = init_one_libfunc(FIX_TRUNCQFHI2_LIBCALL); \ - fixuns_truncqfhi2_libfunc \ - = init_one_libfunc(FIXUNS_TRUNCQFHI2_LIBCALL); \ - fix_trunchfhi2_libfunc \ - = init_one_libfunc(FIX_TRUNCHFHI2_LIBCALL); \ - fixuns_trunchfhi2_libfunc \ - = init_one_libfunc(FIXUNS_TRUNCHFHI2_LIBCALL); \ - floathiqf2_libfunc \ - = init_one_libfunc(FLOATHIQF2_LIBCALL); \ - floatunshiqf2_libfunc \ - = init_one_libfunc(FLOATUNSHIQF2_LIBCALL); \ - floathihf2_libfunc \ - = init_one_libfunc(FLOATHIHF2_LIBCALL); \ - floatunshihf2_libfunc \ - = init_one_libfunc(FLOATUNSHIHF2_LIBCALL); \ - } while (0) - -#define TARGET_MEM_FUNCTIONS - -/* Add any extra modes needed to represent the condition code. - - On the C4x, we have a "no-overflow" mode which is used when an ADD, - SUB, NEG, or MPY insn is used to set the condition code. This is - to prevent the combiner from optimising away a following CMP of the - result with zero when a signed conditional branch or load insn - follows. - - The problem is a subtle one and deals with the manner in which the - negative condition (N) flag is used on the C4x. This flag does not - reflect the status of the actual result but of the ideal result had - no overflow occured (when considering signed operands). - - For example, 0x7fffffff + 1 => 0x80000000 Z=0 V=1 N=0 C=0. Here - the flags reflect the untruncated result, not the actual result. - While the actual result is less than zero, the N flag is not set - since the ideal result of the addition without truncation would - have been positive. - - Note that the while the N flag is handled differently to most other - architectures, the use of it is self consistent and is not the - cause of the problem. - - Logical operations set the N flag to the MSB of the result so if - the result is negative, N is 1. However, integer and floating - point operations set the N flag to be the MSB of the result - exclusive ored with the overflow (V) flag. Thus if an overflow - occurs and the result does not have the MSB set (i.e., the result - looks like a positive number), the N flag is set. Conversely, if - an overflow occurs and the MSB of the result is set, N is set to 0. - Thus the N flag represents the sign of the result if it could have - been stored without overflow but does not represent the apparent - sign of the result. Note that most architectures set the N flag to - be the MSB of the result. - - The C4x approach to setting the N flag simplifies signed - conditional branches and loads which only have to test the state of - the N flag, whereas most architectures have to look at both the N - and V flags. The disadvantage is that there is no flag giving the - status of the sign bit of the operation. However, there are no - conditional load or branch instructions that make use of this - feature (e.g., BMI---branch minus) instruction. Note that BN and - BLT are identical in the C4x. - - To handle the problem where the N flag is set differently whenever - there is an overflow we use a different CC mode, CC_NOOVmode which - says that the CC reflects the comparison of the result against zero - if no overflow occured. - - For example, - - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "") - (minus:QI (match_dup 1) - (match_dup 2)))] - - Note that there is no problem for insns that don't return a result - like CMP, since the CC reflects the effect of operation. - - An example of a potential problem is when GCC - converts (LTU (MINUS (0x80000000) (0x7fffffff) (0x80000000))) - to (LEU (MINUS (0x80000000) (0x7fffffff) (0x7fffffff))) - to (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) - - Now (MINUS (0x80000000) (0x7fffffff)) returns 0x00000001 but the - C4x sets the N flag since the result without overflow would have - been 0xffffffff when treating the operands as signed integers. - Thus (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) sets the N - flag but (GE (0x00000001)) does not set the N flag. - - The upshot is that we can not use signed branch and conditional - load instructions after an add, subtract, neg, abs or multiply. - We must emit a compare insn to check the result against 0. */ - -#define EXTRA_CC_MODES CC(CC_NOOVmode, "CC_NOOV") - /* 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. */ @@ -1663,7 +1232,7 @@ CUMULATIVE_ARGS; #ifndef REG_OK_STRICT -/* Nonzero if X is a hard or pseudo reg that can be used as an base. */ +/* 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) @@ -1673,7 +1242,7 @@ CUMULATIVE_ARGS; #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { \ - if (c4x_check_legit_addr (MODE, X, 0)) \ + if (c4x_legitimate_address_p (MODE, X, 0)) \ goto ADDR; \ } @@ -1689,7 +1258,7 @@ CUMULATIVE_ARGS; #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { \ - if (c4x_check_legit_addr (MODE, X, 1)) \ + if (c4x_legitimate_address_p (MODE, X, 1)) \ goto ADDR; \ } @@ -1698,6 +1267,7 @@ CUMULATIVE_ARGS; #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ { \ rtx new; \ + \ new = c4x_legitimize_address (X, MODE); \ if (new != NULL_RTX) \ { \ @@ -1708,18 +1278,61 @@ CUMULATIVE_ARGS; #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ { \ - rtx new; \ - new = c4x_legitimize_reload_address (X, MODE, insn); \ - if (new != NULL_RTX) \ - { \ - (X) = new; \ - /* We do not have to call push_reload because we do not require \ - any more reloads. */ \ - goto 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) \ @@ -1755,126 +1368,7 @@ CUMULATIVE_ARGS; #define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X)) -/* Define this macro if references to a symbol must be treated - differently depending on something about the variable or - function named by the symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the - rtl for DECL or other node is created. - The value of the rtl will be a `mem' whose address is a - `symbol_ref'. - - The usual thing for this macro to do is to a flag in the - `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified - name string in the `symbol_ref' (if one bit is not enough - information). - - On the C4x we use this to indicate if a symbol is in text or - data space. */ - -#define ENCODE_SECTION_INFO(DECL) c4x_encode_section_info (DECL); - -/* Descripting Relative Cost of Operations. */ - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. - - Note that we return, rather than break so that rtx_cost doesn't - include CONST_COSTS otherwise expand_mult will think that it is - cheaper to synthesise a multiply rather than to use a multiply - instruction. I think this is because the algorithm synth_mult - doesn't take into account the loading of the operands, whereas the - calculation of mult_cost does. -*/ - - -#define RTX_COSTS(RTX, CODE, OUTER_CODE) \ - case PLUS: \ - case MINUS: \ - case AND: \ - case IOR: \ - case XOR: \ - case ASHIFT: \ - case ASHIFTRT: \ - case LSHIFTRT: \ - return COSTS_N_INSNS (1); \ - case MULT: \ - return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \ - || TARGET_MPYI ? 1 : 14); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \ - ? 15 : 50); - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. - - An insn is assumed to cost 4 units. - COSTS_N_INSNS (N) is defined as (N) * 4 - 2. - - Some small integers are effectively free for the C40. We should - also consider if we are using the small memory model. With - the big memory model we require an extra insn for a constant - loaded from memory. - - This is used by expand_binop to decide whether to force a constant - into a register. If the cost is greater than 2 and the constant - is used within a short loop, it gets forced into a register. - Ideally, there should be some weighting as to how mnay times it is used - within the loop. */ - -#define SHIFT_CODE_P(C) ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT) - -#define LOGICAL_CODE_P(C) ((C) == NOT || (C) == AND \ - || (C) == IOR || (C) == XOR) - -#define NON_COMMUTATIVE_CODE_P ((C) == MINUS || (C) == COMPARE) - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (c4x_J_constant (RTX)) \ - return 0; \ - if (! TARGET_C3X \ - && OUTER_CODE == AND \ - && GET_CODE (RTX) == CONST_INT \ - && (INTVAL (RTX) == 255 || INTVAL (RTX) == 65535)) \ - return 0; \ - if (! TARGET_C3X \ - && (OUTER_CODE == ASHIFTRT || OUTER_CODE == LSHIFTRT) \ - && GET_CODE (RTX) == CONST_INT \ - && (INTVAL (RTX) == 16 || INTVAL (RTX) == 24)) \ - return 0; \ - if (TARGET_C3X && SHIFT_CODE_P (OUTER_CODE)) \ - return 3; \ - if (LOGICAL_CODE_P (OUTER_CODE) \ - ? c4x_L_constant (RTX) : c4x_I_constant (RTX)) \ - return 2; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 4; \ - case CONST_DOUBLE: \ - if (c4x_H_constant (RTX)) \ - return 2; \ - if (GET_MODE (RTX) == QFmode) \ - return 4; \ - else \ - return 8; - -/* Compute the cost of an address. This is meant to approximate the size - and/or execution delay of an insn using that address. If the cost is - approximated by the RTL complexity, including CONST_COSTS above, as - is usually the case for CISC machines, this macro should not be defined. - For aggressively RISCy machines, only one insn format is allowed, so - this macro should be a constant. The value of this macro only matters - for valid addresses. We handle the most common address without - a call to c4x_address_cost. */ - -#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : c4x_address_cost (ADDR)) +/* Describing Relative Cost of Operations. */ #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ if (REG_P (OP1) && ! REG_P (OP0)) \ @@ -1892,7 +1386,7 @@ if (REG_P (OP1) && ! REG_P (OP0)) \ /* Compute extra cost of moving data between one register class and another. */ -#define REGISTER_MOVE_COST(FROM, TO) 2 +#define REGISTER_MOVE_COST(MODE, FROM, TO) 2 /* Memory move cost is same as fast register move. Maybe this should be bumped up?. */ @@ -1904,11 +1398,6 @@ if (REG_P (OP1) && ! REG_P (OP0)) \ #define BRANCH_COST 8 -/* Adjust the cost of dependencies. */ - -#define ADJUST_COST(INSN,LINK,DEP,COST) \ - (COST) = c4x_adjust_cost (INSN, LINK, DEP, COST) - #define WORD_REGISTER_OPERATIONS /* Dividing the Output into Sections. */ @@ -1917,9 +1406,7 @@ if (REG_P (OP1) && ! REG_P (OP0)) \ #define DATA_SECTION_ASM_OP "\t.data" -#define USE_CONST_SECTION 1 - -#define CONST_SECTION_ASM_OP "\t.sect\t\".const\"" +#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. */ @@ -1930,52 +1417,18 @@ if (REG_P (OP1) && ! REG_P (OP0)) \ #define FINI_SECTION_ASM_OP "\t.sect\t\".fini\"" -/* Support const sections and the ctors and dtors sections for g++. - Note that there appears to be two different ways to support const - sections at the moment. You can either #define the symbol - READONLY_DATA_SECTION (giving it some code which switches to the - readonly data section) or else you can #define the symbols - EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and - SELECT_RTX_SECTION. We do both here just to be on the safe side. */ - -/* Define a few machine-specific details of the implementation of - constructors. - - The __CTORS_LIST__ goes in the .ctors section. Define CTOR_LIST_BEGIN - and CTOR_LIST_END to contribute to the .ctors section an instruction to - push a word containing 0 (or some equivalent of that). - - Define ASM_OUTPUT_CONSTRUCTOR to push the address of the constructor. */ - -#define CTORS_SECTION_ASM_OP "\t.sect\t\".ctors\"" -#define DTORS_SECTION_ASM_OP "\t.sect\t\".dtors\"" - -/* Constructor list on stack is in reverse order. Go to the end of the - list and go backwards to call constructors in the right order. */ - -#define DO_GLOBAL_CTORS_BODY \ -do { \ - extern func_ptr __CTOR_LIST__[]; \ - func_ptr *p, *beg = __CTOR_LIST__ + 1; \ - for (p = beg; *p ; p++) ; \ - while (p != beg) \ - (*--p) (); \ -} while (0) - #undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors +#define EXTRA_SECTIONS in_init, in_fini #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ INIT_SECTION_FUNCTION \ - FINI_SECTION_FUNCTION \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION + FINI_SECTION_FUNCTION #define INIT_SECTION_FUNCTION \ +extern void init_section (void); \ void \ -init_section () \ +init_section (void) \ { \ if (in_section != in_init) \ { \ @@ -1990,283 +1443,54 @@ fini_section () \ { \ if (in_section != in_fini) \ { \ - fprintf (asm_out_file, "\t%s\n", FINI_SECTION_ASM_OP); \ + fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ in_section = in_fini; \ } \ } -#define READONLY_DATA_SECTION() const_section () - -#define CONST_SECTION_FUNCTION \ -void \ -const_section () \ -{ \ - if (! USE_CONST_SECTION) \ - text_section(); \ - else if (in_section != in_const) \ - { \ - fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ - in_section = in_const; \ - } \ -} - -#define ASM_STABS_OP "\t.stabs" - -/* The ctors and dtors sections are not normally put into use - by EXTRA_SECTIONS and EXTRA_SECTION_FUNCTIONS as defined in svr3.h, - but it can't hurt to define these macros for whatever systems use them. */ - -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} - -#define DTORS_SECTION_FUNCTION \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ - fprintf (FILE, "\t.sect\t\"%s\"\n", NAME); - -/* This is machine-dependent because it needs to push something - on the stack. */ - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t.word\t "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t.word\t "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement or statements to switch to the appropriate - section for output of DECL. DECL is either a `VAR_DECL' node - or a constant of some sort. RELOC indicates whether forming - the initial value of DECL requires link-time relocations. */ - -#define SELECT_SECTION(DECL, RELOC) \ -{ \ - if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (! flag_writable_strings) \ - const_section (); \ - else \ - data_section (); \ - } \ - else if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if ((0 && RELOC) /* Should be (flag_pic && RELOC). */ \ - || ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ - || ! DECL_INITIAL (DECL) \ - || (DECL_INITIAL (DECL) != error_mark_node \ - && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - data_section (); \ - else \ - const_section (); \ - } \ - else \ - const_section (); \ -} - -/* The TI assembler wants to have hex numbers this way. */ - -#undef HOST_WIDE_INT_PRINT_HEX -#ifndef HOST_WIDE_INT_PRINT_HEX -# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT -# define HOST_WIDE_INT_PRINT_HEX "0%xh" -# else -# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG -# define HOST_WIDE_INT_PRINT_HEX "0%lxh" -# else -# define HOST_WIDE_INT_PRINT_HEX "0%llxh" -# endif -# endif -#endif /* ! HOST_WIDE_INT_PRINT_HEX */ - -/* A C statement or statements to switch to the appropriate - section for output of RTX in mode MODE. RTX is some kind - of constant in RTL. The argument MODE is redundant except - in the case of a `const_int' rtx. Currently, these always - go into the const section. */ - -#define SELECT_RTX_SECTION(MODE, RTX) const_section() +/* Switch into a generic section. */ +#define TARGET_ASM_NAMED_SECTION c4x_asm_named_section /* Overall Framework of an Assembler File. */ -#define ASM_FILE_START(FILE) \ -{ \ - int dspversion = 0; \ - if (TARGET_C30) dspversion = 30; \ - if (TARGET_C31) dspversion = 31; \ - if (TARGET_C32) dspversion = 32; \ - if (TARGET_C40) dspversion = 40; \ - if (TARGET_C44) dspversion = 44; \ - fprintf (FILE, "\t.version\t%d\n", dspversion); \ - fprintf (FILE, "\t.file\t"); \ - if (TARGET_TI) \ - { \ - char *p; \ - char *after_dir = main_input_filename; \ - for (p = main_input_filename; *p; p++) \ - if (*p == '/') \ - after_dir = p + 1; \ - output_quoted_string (FILE, after_dir); \ - } \ - else \ - output_quoted_string (FILE, main_input_filename); \ - fprintf (FILE, "\n"); \ -} - -/* We need to have a data section we can identify so that we can set - the DP register back to a data pointer in the small memory model. - This is only required for ISRs if we are paranoid that someone - may have quietly changed this register on the sly. */ - -#define ASM_IDENTIFY_GCC(FILE) \ - if (! TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \ - fputs ("\t.data\ndata_sec:\n", FILE); - #define ASM_COMMENT_START ";" #define ASM_APP_ON "" #define ASM_APP_OFF "" -/* Output float/double constants QFmode. */ - -#define ASM_OUTPUT_BYTE_FLOAT(FILE, VALUE) \ - do { \ - long l; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "\t.word\t0%08xh\t; %s\n", l, str);\ - else \ - fprintf (FILE, "\t.word\t0%08lxh\t; %s\n", l, str);\ - } while (0); - -/* Output long double constants HFmode. - The first word contains the exponent and first part of the mantissa - in the same manner as QFmode. The second word contains the full - mantissa. We should ensure that the two words are allocated within - the same page for the large memory model since we only output a single - LDP instruction. FIXME. The simplest solution probably is to output - a LDP for each load. */ - -#define ASM_OUTPUT_SHORT_FLOAT(FILE, VALUE) \ - do { \ - long l[2]; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \ - l[1] = (l[0] << 8) | ((l[1] >> 24) & 0xff); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "\t.word\t0%08xh\t; %s\n\t.word\t0%08xh\n", \ - l[0], str, l[1]); \ - else \ - fprintf (FILE, "\t.word\t0%08lxh\t; %s\n\t.word\t0%08lxh\n", \ - l[0], str, l[1]); \ - } while (0); - -#define ASM_OUTPUT_CHAR(FILE, VALUE) \ - do { \ - fprintf (FILE, "\t.word\t"); \ - output_addr_const (FILE, VALUE); \ - if (GET_CODE (VALUE) != SYMBOL_REF) \ - fprintf (FILE, " ; 0%08xh\n", INTVAL (VALUE)); \ - else \ - fputc ('\n', FILE); \ - } while (0); - -#define ASM_OUTPUT_BYTE(FILE, VALUE) \ - fprintf (FILE, "\t.word\t0%xh\n", (VALUE)) - #define ASM_OUTPUT_ASCII(FILE, PTR, LEN) c4x_output_ascii (FILE, PTR, LEN) -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - - /* Output and Generation of Labels. */ #define NO_DOT_IN_LABEL /* Only required for TI format. */ -#define ASM_OUTPUT_LABEL(FILE, NAME) \ -do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0); - -#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ - do { \ - fprintf (FILE, "\t.global\t"); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ - c4x_global_label (NAME); \ - } while (0); +/* Globalizing directive for a label. */ +#define GLOBAL_ASM_OP "\t.global\t" #define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ c4x_external_ref (NAME) -/* A C statement to output on FILE an assembler pseudo-op to - declare a library function named external. - (Only needed to keep asm30 happy for ___divqf3 etc.) */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ -c4x_external_ref (XSTR (FUN, 0)) - -#define ASM_FILE_END(FILE) \ -c4x_file_end (FILE) - /* The prefix to add to user-visible assembler symbols. */ #define USER_LABEL_PREFIX "_" -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ -asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) - /* 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%d", PREFIX, NUM) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ + sprintf (BUFFER, "*%s%lu", PREFIX, (unsigned long)(NUM)) -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s$%d", (NAME), (LABELNO))) +/* 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. */ @@ -2298,17 +1522,11 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) #define DOUBLE_TYPE_SIZE 32 #define LONG_DOUBLE_TYPE_SIZE 64 /* Actually only 40. */ -/* Allow #sccs in preprocessor. */ - -#define SCCS_DIRECTIVE - /* Output #ident as a .ident. */ #define ASM_OUTPUT_IDENT(FILE, NAME) \ fprintf (FILE, "\t.ident \"%s\"\n", NAME); -#define CPP_PREDEFINES "" - /* Output of Uninitialized Variables. */ /* This says how to output an assembler line to define a local @@ -2318,7 +1536,7 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ( fputs ("\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (ROUNDED))) + fprintf (FILE, ",%u\n", (int)(ROUNDED))) /* This says how to output an assembler line to define a global uninitialized variable. */ @@ -2329,7 +1547,7 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) assemble_name (FILE, (NAME)), \ fputs ("\n\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (ROUNDED))) + fprintf (FILE, ",%u\n", (int)(ROUNDED))) #undef ASM_OUTPUT_BSS #define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ @@ -2337,7 +1555,7 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) assemble_name (FILE, (NAME)), \ fputs ("\n\t.bss\t", FILE), \ assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (SIZE))) + fprintf (FILE, ",%u\n", (int)(SIZE))) /* Macros Controlling Initialization Routines. */ @@ -2375,20 +1593,19 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) #define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X) -/* Define this macro if you want to implement any pragmas. If defined, it - should be a C expression to be executed when #pragma is seen. The - argument STREAM is the stdio input stream from which the source - text can be read. CH is the first character after the #pragma. The - result of the expression is the terminating character found - (newline or EOF). */ -#define HANDLE_PRAGMA(GETC, UNGETC, NAME) \ - c4x_handle_pragma (GETC, UNGETC, NAME) - -#define SET_DEFAULT_DECL_ATTRIBUTES(DECL, ATTRIBUTES) \ - c4x_set_default_attributes (DECL, &ATTRIBUTES) - -#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \ - (c4x_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS)) +/* 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. */ @@ -2411,7 +1628,7 @@ asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM) to avoid conflict with TI's use of .def). */ #define SDB_DELIM "\n" -#define SDB_DEBUGGING_INFO +#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) @@ -2455,21 +1672,6 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \ "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \ SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0) - -/* Define results of standard character escape sequences. */ - -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* This is the kind of divide that is easiest to do in the general case. */ - -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - /* Define this as 1 if `char' should by default be signed; else as 0. */ #define DEFAULT_SIGNED_CHAR 1 @@ -2522,27 +1724,27 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \ { \ if (TARGET_C3X) \ { \ - asm_fprintf (FILE, "\tldiu\t0,ar1\n"); \ - asm_fprintf (FILE, "\tlsh\t16,ar1\n"); \ - asm_fprintf (FILE, "\tor\t0,ar1\n"); \ - asm_fprintf (FILE, "\tldiu\t0,ar0\n"); \ - asm_fprintf (FILE, "\tbud\tar1\n"); \ - asm_fprintf (FILE, "\tlsh\t16,ar0\n"); \ - asm_fprintf (FILE, "\tor\t0,ar0\n"); \ - asm_fprintf (FILE, "\tor\t1000h,st\n"); \ + 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 \ { \ - asm_fprintf (FILE, "\tlaj\t$+4\n"); \ - asm_fprintf (FILE, "\taddi3\t4,r11,ar0\n"); \ - asm_fprintf (FILE, "\tlda\t*ar0,ar1\n"); \ - asm_fprintf (FILE, "\tlda\t*+ar0(1),ar0\n"); \ - asm_fprintf (FILE, "\tbud\tar1\n"); \ - asm_fprintf (FILE, "\tnop\n"); \ - asm_fprintf (FILE, "\tnop\n"); \ - asm_fprintf (FILE, "\tor\t1000h,st\n"); \ - asm_fprintf (FILE, "\t.word\t0\n"); \ - asm_fprintf (FILE, "\t.word\t0\n"); \ + 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"); \ } \ } @@ -2554,41 +1756,35 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \ tmp1 = expand_shift (RSHIFT_EXPR, QImode, FNADDR, \ size_int (16), 0, 1); \ tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - gen_rtx (CONST_INT, VOIDmode, 0x5069), \ - size_int (16), 0, 1); \ + 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 (FNADDR, gen_rtx (CONST_INT, VOIDmode, \ - 0xffff), 0); \ + 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_rtx (CONST_INT, VOIDmode, 0x1069), \ - size_int (16), 0, 1); \ + 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); \ + 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_rtx (CONST_INT, VOIDmode, 0x5068), \ - size_int (16), 0, 1); \ + 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 (CXT, gen_rtx (CONST_INT, VOIDmode, \ - 0xffff), 0); \ + 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_rtx (CONST_INT, VOIDmode, 0x1068), \ - size_int (16), 0, 1); \ + 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); \ + emit_move_insn (gen_rtx_MEM (QImode, \ + plus_constant (TRAMP, 6)), tmp1); \ } \ else \ { \ - emit_move_insn (gen_rtx (MEM, QImode, \ + emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 8)), FNADDR); \ - emit_move_insn (gen_rtx (MEM, QImode, \ + emit_move_insn (gen_rtx_MEM (QImode, \ plus_constant (TRAMP, 9)), CXT); \ } \ } @@ -2606,49 +1802,41 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \ /* MOVE_RATIO is the number of move instructions that is better than a block move. */ -#define MOVE_RATIO 2 /* Default value. */ +#define MOVE_RATIO 3 -#define BSS_SECTION_ASM_OP ".bss" +#define BSS_SECTION_ASM_OP "\t.bss" #define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ - asm_fprintf (FILE, "\tpush\t%s\n", reg_names[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) \ - asm_fprintf (FILE, "\tpop\t%s\n", reg_names[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 DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* We need to use direct addressing for large constants and addresses - that cannot fit within an instruction. We must check for these - after after the final jump optimisation pass, since this may - introduce a local_move insn for a SYMBOL_REF. This pass - must come before delayed branch slot filling since it can generate - additional instructions. */ - -#define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS) - -#define DBR_OUTPUT_SEQEND(FILE) \ -if (final_sequence != NULL_RTX) \ -{ \ - int count; \ - int laj = GET_CODE (XVECEXP (final_sequence, 0, 0)) == CALL_INSN; \ - \ - count = dbr_sequence_length(); \ - while (count < (laj ? 2 : 3)) \ - { \ - fputs("\tnop\n", FILE); \ - count++; \ - } \ - if (laj) \ - fputs("\tpush\tr11\n", FILE); \ +#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 @@ -2684,8 +1872,29 @@ if (final_sequence != NULL_RTX) \ {"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. */ +#undef HAVE_GAS_HIDDEN