/* Definitions of target machine for GNU compiler. TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 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 \
+ { \
+ /* ??? HACK. We shouldn't have flag_inline_trees at all. */ \
+ extern int flag_inline_trees; \
+ if (!TARGET_SMALL) \
+ builtin_define ("_BIGMODEL"); \
+ if (!TARGET_MEMPARM) \
+ builtin_define ("_REGPARM"); \
+ if (flag_inline_functions \
+ || flag_inline_trees) \
+ 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"
#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. */
%{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 ""
#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. */
{ "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, \
#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
#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
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
#define MAX_FIXED_MODE_SIZE 64 /* HImode. */
/* If a structure has a floating point field then force structure
- to have BLKMODE. */
-#define MEMBER_TYPE_FORCES_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. */
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. */
/* 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. */
}
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) \
#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. */
/* 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)
/* Generating Code for Profiling. */
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 \
- { \
- emit_insn (gen_push_st ()); \
- emit_insn (gen_pushqi ( \
- gen_rtx_REG (QImode, AR2_REGNO))); \
- emit_call_insn (gen_nodb_call ( \
- gen_rtx_SYMBOL_REF (QImode, "__bb_trace_ret")));\
- emit_insn (gen_popqi_unspec ( \
- gen_rtx_REG (QImode, AR2_REGNO))); \
- emit_insn (gen_pop_st ()); \
- }
-
-#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. */
#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)
#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; \
}
#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; \
}
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
{ \
rtx new; \
+ \
new = c4x_legitimize_address (X, MODE); \
if (new != NULL_RTX) \
{ \
if (! TARGET_SMALL) \
{ \
int i; \
- X = gen_rtx_LO_SUM (GET_MODE (X), \
+ (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, \
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 \
#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))
-
#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
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. */
#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. */
#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) \
{ \
} \
}
-#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\t"
-/* 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. */
-/* 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_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); \
- fputs ("\n\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. */
-
-#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
-( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
- sprintf ((OUTPUT), "%s$%d", (NAME), (LABELNO)))
+ sprintf (BUFFER, "*%s%lu", PREFIX, (unsigned long)(NUM))
/* A C statement to output to the stdio stream STREAM assembler code which
defines (equates) the symbol NAME to have the value VALUE. */
#define 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
#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. */
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) \
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. */
#define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X)
/* C4x specific pragmas. */
-#define REGISTER_TARGET_PRAGMAS(PFILE) do { \
- cpp_register_pragma (PFILE, 0, "CODE_SECTION", c4x_pr_CODE_SECTION); \
- cpp_register_pragma (PFILE, 0, "DATA_SECTION", c4x_pr_DATA_SECTION); \
- cpp_register_pragma (PFILE, 0, "FUNC_CANNOT_INLINE", c4x_pr_ignored); \
- cpp_register_pragma (PFILE, 0, "FUNC_EXT_CALLED", c4x_pr_ignored); \
- cpp_register_pragma (PFILE, 0, "FUNC_IS_PURE", c4x_pr_FUNC_IS_PURE); \
- cpp_register_pragma (PFILE, 0, "FUNC_IS_SYSTEM", c4x_pr_ignored); \
- cpp_register_pragma (PFILE, 0, "FUNC_NEVER_RETURNS", \
- c4x_pr_FUNC_NEVER_RETURNS); \
- cpp_register_pragma (PFILE, 0, "FUNC_NO_GLOBAL_ASG", c4x_pr_ignored); \
- cpp_register_pragma (PFILE, 0, "FUNC_NO_IND_ASG", c4x_pr_ignored); \
- cpp_register_pragma (PFILE, 0, "INTERRUPT", c4x_pr_INTERRUPT); \
- c4x_init_pragma (&c_lex); \
+#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)
-#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))
-
/* Assembler Commands for Alignment. */
#define ASM_OUTPUT_SKIP(FILE, SIZE) \
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)
"%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \
SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
-/* 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
{ \
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"); \
} \
}
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); \
} \
}
#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) \
{ \
{"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}}, \
C4X_BUILTIN_RCPF /* fast_invf (only C4x) */
};
-#define MD_INIT_BUILTINS do { \
- c4x_init_builtins (void_list_node); \
- } while (0)
-#define MD_EXPAND_BUILTIN(EXP, TARGET, SUBTARGET, MODE, IGNORE) \
- c4x_expand_builtin ((EXP), (TARGET), (SUBTARGET), (MODE), (IGNORE))
+/* Hack to overcome use of libgcc2.c using auto-host.h to determine
+ HAVE_GAS_HIDDEN. */
+#undef HAVE_GAS_HIDDEN