aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/c4x/c4x.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/c4x/c4x.h')
-rw-r--r--gcc/config/c4x/c4x.h493
1 files changed, 330 insertions, 163 deletions
diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h
index cc92b2a12f9..a72d6dbc307 100644
--- a/gcc/config/c4x/c4x.h
+++ b/gcc/config/c4x/c4x.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
@@ -156,66 +156,109 @@
/* Run-time compilation parameters selecting different hardware subsets.
Macro to define tables used to set the flags.
- This is a list in braces of pairs in braces,
- each pair being { "NAME", VALUE }
+ This is a list in braces of triplets in braces,
+ each pair being { "NAME", VALUE, "DESCRIPTION" }
where VALUE is the bits to set or minus the bits to clear.
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
-{ { "small", SMALL_MEMORY_FLAG }, \
- { "big", -SMALL_MEMORY_FLAG }, \
- { "mpyi", MPYI_FLAG}, \
- { "no-mpyi", -MPYI_FLAG}, \
- { "fast-fix", FAST_FIX_FLAG}, \
- { "no-fast-fix", -FAST_FIX_FLAG}, \
- { "rpts", RPTS_FLAG}, \
- { "no-rpts", -RPTS_FLAG}, \
- { "rptb", RPTB_FLAG}, \
- { "no-rptb", -RPTB_FLAG}, \
- { "30", C30_FLAG}, \
- { "31", C31_FLAG}, \
- { "32", C32_FLAG}, \
- { "40", C40_FLAG}, \
- { "44", C44_FLAG}, \
- { "ti", TI_FLAG}, \
- { "no-ti", -TI_FLAG}, \
- { "paranoid", PARANOID_FLAG}, \
- { "no-paranoid", -PARANOID_FLAG}, \
- { "isr-dp-reload", PARANOID_FLAG}, \
- { "no-isr-dp-reload", -PARANOID_FLAG}, \
- { "memparm", MEMPARM_FLAG}, \
- { "regparm", -MEMPARM_FLAG}, \
- { "devel", DEVEL_FLAG}, \
- { "no-devel", -DEVEL_FLAG}, \
- { "bk", BK_FLAG}, \
- { "no-bk", -BK_FLAG}, \
- { "db", DB_FLAG}, \
- { "no-db", -DB_FLAG}, \
- { "debug", DEBUG_FLAG}, \
- { "no-debug", -DEBUG_FLAG}, \
- { "hoist", HOIST_FLAG}, \
- { "no-hoist", -HOIST_FLAG}, \
- { "no-force", -FORCE_FLAG}, \
- { "force", FORCE_FLAG}, \
- { "loop-unsigned", LOOP_UNSIGNED_FLAG}, \
- { "no-loop-unsigned", -LOOP_UNSIGNED_FLAG}, \
- { "preserve-float", PRESERVE_FLOAT_FLAG}, \
- { "no-preserve-float", -PRESERVE_FLOAT_FLAG}, \
- { "parallel-insns", PARALLEL_PACK_FLAG}, \
- { "no-parallel-mpy", -PARALLEL_MPY_FLAG}, \
- { "parallel-mpy", PARALLEL_MPY_FLAG}, \
- { "no-parallel-insns", -PARALLEL_PACK_FLAG}, \
- { "aliases", ALIASES_FLAG}, \
- { "no-aliases", -ALIASES_FLAG}, \
- { "", TARGET_DEFAULT} }
+{ { "small", SMALL_MEMORY_FLAG, \
+ "Small memory model" }, \
+ { "big", -SMALL_MEMORY_FLAG, \
+ "Big memory model" }, \
+ { "mpyi", MPYI_FLAG, \
+ "Use MPYI instruction for C3x" }, \
+ { "no-mpyi", -MPYI_FLAG, \
+ "Do not use MPYI instruction for C3x" }, \
+ { "fast-fix", FAST_FIX_FLAG, \
+ "Use fast but approximate float to integer conversion" }, \
+ { "no-fast-fix", -FAST_FIX_FLAG, \
+ "Use slow but accurate float to integer conversion" }, \
+ { "rpts", RPTS_FLAG, \
+ "Enable use of RTPS instruction" }, \
+ { "no-rpts", -RPTS_FLAG, \
+ "Disable use of RTPS instruction" }, \
+ { "rptb", RPTB_FLAG, \
+ "Enable use of RTPB instruction" }, \
+ { "no-rptb", -RPTB_FLAG, \
+ "Disable use of RTPB instruction" }, \
+ { "30", C30_FLAG, \
+ "Generate code for C30 CPU"}, \
+ { "31", C31_FLAG, \
+ "Generate code for C31 CPU"}, \
+ { "32", C32_FLAG, \
+ "Generate code for C32 CPU"}, \
+ { "40", C40_FLAG, \
+ "Generate code for C40 CPU"}, \
+ { "44", C44_FLAG, \
+ "Generate code for C44 CPU"}, \
+ { "ti", TI_FLAG, \
+ "Emit code compatible with TI tools"}, \
+ { "no-ti", -TI_FLAG, \
+ "Emit code to use GAS extensions"}, \
+ { "paranoid", PARANOID_FLAG, \
+ "Save DP across ISR in small memory model" }, \
+ { "no-paranoid", -PARANOID_FLAG, \
+ "Don't save DP across ISR in small memory model" }, \
+ { "isr-dp-reload", PARANOID_FLAG, \
+ "Save DP across ISR in small memory model" }, \
+ { "no-isr-dp-reload", -PARANOID_FLAG, \
+ "Don't save DP across ISR in small memory model" }, \
+ { "memparm", MEMPARM_FLAG, \
+ "Pass arguments on the stack" }, \
+ { "regparm", -MEMPARM_FLAG, \
+ "Pass arguments in registers" }, \
+ { "devel", DEVEL_FLAG, \
+ "Enable new features under development" }, \
+ { "no-devel", -DEVEL_FLAG, \
+ "Disable new features under development" }, \
+ { "bk", BK_FLAG, \
+ "Use the BK register as a general purpose register" }, \
+ { "no-bk", -BK_FLAG, \
+ "Do not allocate BK register" }, \
+ { "db", DB_FLAG, \
+ "Enable use of DB instruction" }, \
+ { "no-db", -DB_FLAG, \
+ "Disable use of DB instruction" }, \
+ { "debug", DEBUG_FLAG, \
+ "Enable debugging" }, \
+ { "no-debug", -DEBUG_FLAG, \
+ "Disable debugging" }, \
+ { "hoist", HOIST_FLAG, \
+ "Force constants into registers to improve hoisting" }, \
+ { "no-hoist", -HOIST_FLAG, \
+ "Don't force constants into registers" }, \
+ { "force", FORCE_FLAG, \
+ "Force RTL generation to emit valid 3 operand insns" }, \
+ { "no-force", -FORCE_FLAG, \
+ "Allow RTL generation to emit invalid 3 operand insns" }, \
+ { "loop-unsigned", LOOP_UNSIGNED_FLAG, \
+ "Allow unsigned interation counts for RPTB/DB" }, \
+ { "no-loop-unsigned", -LOOP_UNSIGNED_FLAG, \
+ "Disallow unsigned iteration counts for RPTB/DB" }, \
+ { "preserve-float", PRESERVE_FLOAT_FLAG, \
+ "Preserve all 40 bits of FP reg across call" }, \
+ { "no-preserve-float", -PRESERVE_FLOAT_FLAG, \
+ "Only preserve 32 bits of FP reg across call" }, \
+ { "parallel-insns", PARALLEL_PACK_FLAG, \
+ "Enable parallel instructions" }, \
+ { "no-parallel-mpy", -PARALLEL_MPY_FLAG, \
+ "Disable parallel instructions" }, \
+ { "parallel-mpy", PARALLEL_MPY_FLAG, \
+ "Enable MPY||ADD and MPY||SUB instructions" }, \
+ { "no-parallel-insns", -PARALLEL_PACK_FLAG, \
+ "Disable MPY||ADD and MPY||SUB instructions" }, \
+ { "aliases", ALIASES_FLAG, \
+ "Assume that pointers may be aliased" }, \
+ { "no-aliases", -ALIASES_FLAG, \
+ "Assume that pointers not aliased" }, \
+ { "", TARGET_DEFAULT, ""} }
/* Default target switches */
-/* Play safe, not the fastest code. Note that setting PARALLEL_MPY
-flag will set SMALL_REGISTER_CLASSES which can be a price to pay,
-especially when MPY||ADD instructions are only generated very
-infrequenctly. */
-#define TARGET_DEFAULT ALIASES_FLAG | RPTB_FLAG | PARALLEL_PACK_FLAG
+/* Play safe, not the fastest code. */
+#define TARGET_DEFAULT ALIASES_FLAG | PARALLEL_PACK_FLAG \
+ | PARALLEL_MPY_FLAG | RPTB_FLAG
/* Caveats:
Max iteration count for RPTB/RPTS is 2^31 + 1.
@@ -227,7 +270,7 @@ extern int target_flags;
#define TARGET_INLINE 1 /* Inline MPYI */
#define TARGET_PARALLEL 1 /* Enable parallel insns in MD */
-#define TARGET_SMALL_REG_CLASS 1
+#define TARGET_SMALL_REG_CLASS 0
#define TARGET_SMALL (target_flags & SMALL_MEMORY_FLAG)
#define TARGET_MPYI (!TARGET_C3X || (target_flags & MPYI_FLAG))
@@ -240,7 +283,7 @@ extern int target_flags;
#define TARGET_RPTB (target_flags & RPTB_FLAG \
&& optimize >= 2)
#define TARGET_BK (target_flags & BK_FLAG)
-#define TARGET_DB (!TARGET_C3X || (target_flags & DB_FLAG))
+#define TARGET_DB (! TARGET_C3X || (target_flags & DB_FLAG))
#define TARGET_DEBUG (target_flags & DEBUG_FLAG)
#define TARGET_HOIST (target_flags & HOIST_FLAG)
#define TARGET_LOOP_UNSIGNED (target_flags & LOOP_UNSIGNED_FLAG)
@@ -260,12 +303,16 @@ extern int target_flags;
#define TARGET_C40 (target_flags & C40_FLAG)
#define TARGET_C44 (target_flags & C44_FLAG)
+#define TARGET_LOAD_ADDRESS (1 || (! TARGET_C3X && ! TARGET_SMALL))
+
/* -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
@@ -288,8 +335,10 @@ extern int target_flags;
extern char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
#define TARGET_OPTIONS \
-{ {"rpts=", &c4x_rpts_cycles_string},\
- {"cpu=", &c4x_cpu_version_string} }
+{ {"rpts=", &c4x_rpts_cycles_string, \
+ "Specify maximum number of iterations for RPTS" }, \
+ {"cpu=", &c4x_cpu_version_string, \
+ "Select CPU to generate code for" } }
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -300,6 +349,9 @@ extern char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
extern void c4x_override_options ();
#define OVERRIDE_OPTIONS c4x_override_options ()
+/* Define this to change the optimizations performed by default. */
+extern void c4x_optimization_options ();
+#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) c4x_optimization_options(LEVEL,SIZE)
/* Run Time Target Specification */
@@ -335,6 +387,11 @@ extern void c4x_override_options ();
#define TARGET_FLOAT_FORMAT C4X_FLOAT_FORMAT
#define MAX_FIXED_MODE_SIZE 64 /* HImode */
+/* 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. */
@@ -417,7 +474,7 @@ extern void c4x_override_options ();
/* Extended precision registers (high set) */
-#define IS_EXT_HIGH_REG(r) (!TARGET_C3X \
+#define IS_EXT_HIGH_REG(r) (! TARGET_C3X \
&& ((r) >= R8_REGNO) && ((r) <= R11_REGNO))
/* Address registers */
@@ -431,6 +488,7 @@ extern void c4x_override_options ();
/* Misc registers */
#define IS_ST_REG(r) ((r) == ST_REGNO)
+#define IS_RC_REG(r) ((r) == RC_REGNO)
#define IS_REPEAT_REG(r) (((r) >= RS_REGNO) && ((r) <= RC_REGNO))
/* Composite register sets */
@@ -455,6 +513,7 @@ extern void c4x_override_options ();
#define IS_DP_OR_PSEUDO_REG(r) (IS_DP_REG(r) || IS_PSEUDO_REG(r))
#define IS_SP_OR_PSEUDO_REG(r) (IS_SP_REG(r) || IS_PSEUDO_REG(r))
#define IS_ST_OR_PSEUDO_REG(r) (IS_ST_REG(r) || IS_PSEUDO_REG(r))
+#define IS_RC_OR_PSEUDO_REG(r) (IS_RC_REG(r) || IS_PSEUDO_REG(r))
#define IS_PSEUDO_REGNO(op) (IS_PSEUDO_REG(REGNO(op)))
#define IS_ADDR_REGNO(op) (IS_ADDR_REG(REGNO(op)))
@@ -473,6 +532,7 @@ extern void c4x_override_options ();
#define IS_DP_OR_PSEUDO_REGNO(op) (IS_DP_OR_PSEUDO_REG(REGNO(op)))
#define IS_SP_OR_PSEUDO_REGNO(op) (IS_SP_OR_PSEUDO_REG(REGNO(op)))
#define IS_ST_OR_PSEUDO_REGNO(op) (IS_ST_OR_PSEUDO_REG(REGNO(op)))
+#define IS_RC_OR_PSEUDO_REGNO(op) (IS_RC_OR_PSEUDO_REG(REGNO(op)))
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
@@ -508,7 +568,7 @@ extern void c4x_override_options ();
#define CONDITIONAL_REGISTER_USAGE \
{ \
- if (!TARGET_BK) \
+ if (! TARGET_BK) \
{ \
fixed_regs[BK_REGNO] = 1; \
call_used_regs[BK_REGNO] = 1; \
@@ -528,6 +588,11 @@ extern void c4x_override_options ();
c4x_regclass_map[i] = NO_REGS; \
} \
} \
+ if (TARGET_PRESERVE_FLOAT) \
+ { \
+ c4x_caller_save_map[R6_REGNO] = HFmode; \
+ c4x_caller_save_map[R7_REGNO] = HFmode; \
+ } \
}
/* Order of Allocation of Registers */
@@ -573,11 +638,10 @@ extern void c4x_override_options ();
across a call in mode MODE. This does not have to include the call used
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) \
- && ((MODE) != QImode || (MODE) != HImode || (MODE) != Pmode)))
+#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)) \
+ && ! ((MODE) == QImode || (MODE) == HImode || (MODE) == Pmode)))
/* Specify the modes required to caller save a given hard regno. */
@@ -628,8 +692,10 @@ enum reg_class
EXT_REGS, /* 'f' */
ADDR_REGS, /* 'a' */
INDEX_REGS, /* 'x' */
- SP_REG, /* 'b' */
BK_REG, /* 'k' */
+ SP_REG, /* 'b' */
+ RC_REG, /* 'v' */
+ COUNTER_REGS, /* */
INT_REGS, /* 'c' */
GENERAL_REGS, /* 'r' */
DP_REG, /* 'z' */
@@ -649,36 +715,41 @@ enum reg_class
"EXT_REGS", \
"ADDR_REGS", \
"INDEX_REGS", \
- "SP_REG", \
"BK_REG", \
+ "SP_REG", \
+ "RC_REG", \
+ "COUNTER_REGS", \
"INT_REGS", \
"GENERAL_REGS", \
"DP_REG", \
"ST_REG", \
"ALL_REGS" \
-};
+}
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
- of length N_REG_CLASSES. */
-
+ of length N_REG_CLASSES. RC is not included in GENERAL_REGS
+ since the register allocator will often choose a general register
+ in preference to RC for the decrement_and_branch_on_count pattern. */
#define REG_CLASS_CONTENTS \
{ \
- 0x00000000, /* No registers */ \
- 0x00000003, /* 't' R0-R1 */ \
- 0x0000000c, /* 'u' R2-R3 */ \
- 0x000000ff, /* 'q' R0-R7 */ \
- 0xf00000ff, /* 'f' R0-R11 */ \
- 0x0000ff00, /* 'a' AR0-AR7 */ \
- 0x00060000, /* 'x' IR0-IR1 */ \
- 0x00100000, /* 'b' SP */ \
- 0x00080000, /* 'k' BK */ \
- 0x0e1eff00, /* 'c' AR0-AR7, IR0-IR1, RC, RS, RE, BK, SP */ \
- 0xfe1effff, /* 'r' R0-R11, AR0-AR7, IR0-IR1, RC, RS, RE, BK, SP */\
- 0x00010000, /* 'z' DP */ \
- 0x00200000, /* 'y' ST */ \
- 0xffffffff, /* All registers */ \
+ {0x00000000}, /* No registers */ \
+ {0x00000003}, /* 't' R0-R1 */ \
+ {0x0000000c}, /* 'u' R2-R3 */ \
+ {0x000000ff}, /* 'q' R0-R7 */ \
+ {0xf00000ff}, /* 'f' R0-R11 */ \
+ {0x0000ff00}, /* 'a' AR0-AR7 */ \
+ {0x00060000}, /* 'x' IR0-IR1 */ \
+ {0x00080000}, /* 'k' BK */ \
+ {0x00100000}, /* 'b' SP */ \
+ {0x08000000}, /* 'v' RC */ \
+ {0x0800ff00}, /* RC,AR0-AR7 */ \
+ {0x0e1eff00}, /* 'c' AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */ \
+ {0xfe1effff}, /* 'r' R0-R11, AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */\
+ {0x00010000}, /* 'z' DP */ \
+ {0x00200000}, /* 'y' ST */ \
+ {0xffffffff}, /* All registers */ \
}
/* The same information, inverted:
@@ -688,22 +759,18 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) (c4x_regclass_map[REGNO])
-/* When SMALL_REGISTER_CLASSES is defined, the compiler allows
-registers explicitly used in the rtl to be used as spill registers but
-prevents the compiler from extending the lifetime of these registers.
-Problems can occur if reload has to spill a register used explicitly
-in the RTL if it has a long lifetime. This is only likely to be a problem
-with a function having many variables and thus lots of spilling.
-
-We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY
-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
-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
-double arithmetic we need two additional registers that we can use as
-spill registers. */
+/* When SMALL_REGISTER_CLASSES is defined, the lifetime of registers
+ explicitly used in the rtl is kept as short as possible.
+
+ We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY
+ 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
+ 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
+ double arithmetic we need two additional registers that we can use as
+ spill registers. */
#define SMALL_REGISTER_CLASSES (TARGET_SMALL_REG_CLASS && TARGET_PARALLEL_MPY)
@@ -711,7 +778,7 @@ spill registers. */
#define INDEX_REG_CLASS INDEX_REGS
/*
- Constraints for the C4x
+ Register constraints for the C4x
a - address reg (ar0-ar7)
b - stack reg (sp)
@@ -723,10 +790,13 @@ spill registers. */
q - r0-r7
t - r0-r1
u - r2-r3
+ v - repeat count (rc)
x - index register (ir0-ir1)
y - status register (st)
z - dp reg (dp)
+ Memory/constant constraints for the C4x
+
G - short float 16-bit
I - signed 16-bit constant (sign extended)
J - signed 8-bit constant (sign extended) (C4x only)
@@ -756,6 +826,7 @@ spill registers. */
: ((CC) == 'q') ? EXT_LOW_REGS \
: ((CC) == 't') ? R0R1_REGS \
: ((CC) == 'u') ? R2R3_REGS \
+ : ((CC) == 'v') ? RC_REG \
: ((CC) == 'x') ? INDEX_REGS \
: ((CC) == 'y') ? ST_REG \
: ((CC) == 'z') ? DP_REG \
@@ -801,7 +872,7 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
#define IS_NOT_UINT16_CONST(VAL) IS_UINT16_CONST(~(VAL)) /* 'N' */
-#define IS_HIGH_CONST(VAL) (!TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O' */
+#define IS_HIGH_CONST(VAL) (! TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O' */
#define IS_DISP1_CONST(VAL) (((VAL) <= 1) && ((VAL) >= -1)) /* 'S' */
@@ -816,24 +887,25 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
#define CONST_OK_FOR_LETTER_P(VAL, C) \
( ((C) == 'I') ? (IS_INT16_CONST (VAL)) \
- : ((C) == 'J') ? (!TARGET_C3X && IS_INT8_CONST (VAL)) \
- : ((C) == 'K') ? (!TARGET_C3X && IS_INT5_CONST (VAL)) \
+ : ((C) == 'J') ? (! TARGET_C3X && IS_INT8_CONST (VAL)) \
+ : ((C) == 'K') ? (! TARGET_C3X && IS_INT5_CONST (VAL)) \
: ((C) == 'L') ? (IS_UINT16_CONST (VAL)) \
- : ((C) == 'M') ? (!TARGET_C3X && IS_UINT8_CONST (VAL)) \
+ : ((C) == 'M') ? (! TARGET_C3X && IS_UINT8_CONST (VAL)) \
: ((C) == 'N') ? (IS_NOT_UINT16_CONST (VAL)) \
: ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \
: 0 )
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL, C) \
- ( ((C) == 'G') ? (fp_zero_operand (VAL)) \
- : ((C) == 'H') ? (c4x_H_constant (VAL)) \
+#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \
+ ( ((C) == 'G') ? (fp_zero_operand (OP)) \
+ : ((C) == 'H') ? (c4x_H_constant (OP)) \
: 0 )
-#define EXTRA_CONSTRAINT(VAL, C) \
- ( ((C) == 'Q') ? (c4x_Q_constraint (VAL)) \
- : ((C) == 'R') ? (c4x_R_constraint (VAL)) \
- : ((C) == 'S') ? (c4x_S_constraint (VAL)) \
- : ((C) == 'T') ? (c4x_T_constraint (VAL)) \
+#define EXTRA_CONSTRAINT(OP, C) \
+ ( ((C) == 'Q') ? (c4x_Q_constraint (OP)) \
+ : ((C) == 'R') ? (c4x_R_constraint (OP)) \
+ : ((C) == 'S') ? (c4x_S_constraint (OP)) \
+ : ((C) == 'T') ? (c4x_T_constraint (OP)) \
+ : ((C) == 'U') ? (c4x_U_constraint (OP)) \
: 0 )
#define SMALL_CONST(VAL, insn) \
@@ -978,7 +1050,7 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
int regno; \
int offset = 0; \
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
offset += TARGET_PRESERVE_FLOAT \
&& ((regno == R6_REGNO) || (regno == R7_REGNO)) \
? 2 : 1; \
@@ -990,7 +1062,7 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
{{ FRAME_POINTER_REGNUM, FRAME_POINTER_REGNUM }}
#define CAN_ELIMINATE(FROM, TO) \
- (!(((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
+ (! (((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
|| ((FROM) == FRAME_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)))
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
@@ -998,7 +1070,7 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
int regno; \
int offset = 0; \
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
offset += TARGET_PRESERVE_FLOAT \
&& ((regno == R6_REGNO) || (regno == R7_REGNO)) \
? 2 : 1; \
@@ -1096,7 +1168,7 @@ extern struct rtx_def *c4x_function_arg();
MSBs of the address. This is not supported by the TI assembler. */
#define FUNCTION_PROFILER(FILE, LABELNO) \
- if (!TARGET_C3X) \
+ if (! TARGET_C3X) \
{ \
fprintf (FILE, "\tpush\tar2\n"); \
fprintf (FILE, "\tldhi\t^LP%d,ar2\n", (LABELNO)); \
@@ -1146,7 +1218,7 @@ extern struct rtx_def *c4x_function_arg();
#define FUNCTION_BLOCK_PROFILER(FILE, BLOCKNO) \
if (profile_block_flag == 2) \
{ \
- if (!TARGET_C3X) \
+ if (! TARGET_C3X) \
{ \
fprintf (FILE, "\tpush\tst\n"); \
fprintf (FILE, "\tpush\tar2\n"); \
@@ -1193,7 +1265,7 @@ extern struct rtx_def *c4x_function_arg();
} \
else \
{ \
- if (!TARGET_C3X) \
+ if (! TARGET_C3X) \
{ \
fprintf (FILE, "\tpush\tst\n"); \
fprintf (FILE, "\tpush\tar2\n"); \
@@ -1225,7 +1297,7 @@ extern struct rtx_def *c4x_function_arg();
#define BLOCK_PROFILER(FILE, BLOCKNO) \
if (profile_block_flag == 2) \
{ \
- if (!TARGET_C3X) \
+ if (! TARGET_C3X) \
{ \
fprintf (FILE, "\tpush\tst\n"); \
fprintf (FILE, "\tpush\tar2\n"); \
@@ -1281,7 +1353,7 @@ extern struct rtx_def *c4x_function_arg();
} \
else \
{ \
- if (!TARGET_C3X) \
+ if (! TARGET_C3X) \
{ \
fprintf (FILE, "\tpush\tar2\n"); \
fprintf (FILE, "\tpush\tar0\n"); \
@@ -1508,14 +1580,16 @@ extern struct rtx_def *c4x_gen_compare_reg ();
/* Addressing Modes */
-#define HAVE_POST_INCREMENT
-#define HAVE_PRE_INCREMENT
-#define HAVE_POST_DECREMENT
-#define HAVE_PRE_DECREMENT
-#define HAVE_PRE_MODIFY_REG
-#define HAVE_POST_MODIFY_REG
-#define HAVE_PRE_MODIFY_DISP
-#define HAVE_POST_MODIFY_DISP
+#define HAVE_POST_INCREMENT 1
+#define HAVE_PRE_INCREMENT 1
+#define HAVE_POST_DECREMENT 1
+#define HAVE_PRE_DECREMENT 1
+#define HAVE_PRE_MODIFY_REG 1
+#define HAVE_POST_MODIFY_REG 1
+#define HAVE_PRE_MODIFY_DISP 1
+#define HAVE_POST_MODIFY_DISP 1
+
+#define HAVE_MULTIPLE_PACK 2
/* What about LABEL_REF? */
#define CONSTANT_ADDRESS_P(X) (GET_CODE (X) == SYMBOL_REF)
@@ -1599,17 +1673,44 @@ extern struct rtx_def *c4x_legitimize_address ();
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
- The C4x can only load 16-bit immediate values, so we only allow
- a restricted subset of CONST_INT and CONST_DOUBLE and reject
- LABEL_REF, SYMBOL_REF, CONST, and HIGH codes. */
+ The C4x can only load 16-bit immediate values, so we only allow a
+ restricted subset of CONST_INT and CONST_DOUBLE. Disallow
+ LABEL_REF and SYMBOL_REF (except on the C40 with the big memory
+ model) so that the symbols will be forced into the constant pool.
+ On second thoughts, lets do this with the move expanders.
+*/
#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X) \
- || GET_CODE (X) == CONST_INT && c4x_I_constant (X))
-
+ ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \
+ || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)) \
+ || (GET_CODE (X) == SYMBOL_REF) \
+ || (GET_CODE (X) == LABEL_REF) \
+ || (GET_CODE (X) == CONST) \
+ || (GET_CODE (X) == HIGH && ! TARGET_C3X) \
+ || (GET_CODE (X) == LO_SUM && ! TARGET_C3X))
#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. */
+
+extern void c4x_encode_section_info ();
+#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
@@ -1625,10 +1726,22 @@ extern struct rtx_def *c4x_legitimize_address ();
#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: \
+ case DIV: \
+ case UDIV: \
+ case MOD: \
+ case UMOD: \
return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \
? 15 : 50);
@@ -1699,11 +1812,10 @@ if (REG_P (OP1) && ! REG_P (OP0)) \
#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \
|| INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG)
-/* Make the Rx register a little easier to use so they are used for
- calculations and the ARx registers are used for addressing. */
+/* Compute extra cost of moving data between one register class
+ and another. */
-#define REGISTER_MOVE_COST(FROM, TO) \
-(EXPENSIVE_CLASS_P(TO) ? 5 : EXPENSIVE_CLASS_P(FROM) ? 4 : 3)
+#define REGISTER_MOVE_COST(FROM, TO) 2
/* Memory move cost is same as fast register move. Maybe this should
be bumped up? */
@@ -1774,7 +1886,7 @@ do { \
} while (0)
/* The TI tooling uses atexit. */
-#define ON_EXIT(FUNC,ARG) atexit (FUNC)
+#define HAVE_ATEXIT
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors
@@ -1816,7 +1928,7 @@ void \
const_section () \
{ \
extern void text_section(); \
- if (!USE_CONST_SECTION) \
+ if (! USE_CONST_SECTION) \
text_section(); \
else if (in_section != in_const) \
{ \
@@ -1896,10 +2008,10 @@ dtors_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) \
+ || ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
+ || ! DECL_INITIAL (DECL) \
|| (DECL_INITIAL (DECL) != error_mark_node \
- && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
+ && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \
data_section (); \
else \
const_section (); \
@@ -1951,7 +2063,7 @@ dtors_section () \
may have quietly changed this register on the sly. */
#define ASM_IDENTIFY_GCC(FILE) \
- if (!TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \
+ if (! TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \
fputs ("\t.data\ndata_sec:\n", FILE);
#define ASM_COMMENT_START ";"
@@ -1965,7 +2077,7 @@ dtors_section () \
{ long l; \
char str[30]; \
REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%20f", str); \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \
if (sizeof (int) == sizeof (long)) \
fprintf (FILE, "\t.word\t0%08xh\t; %s\n", l, str);\
else \
@@ -1984,7 +2096,7 @@ dtors_section () \
{ long l[2]; \
char str[30]; \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%20f", str); \
+ 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", \
@@ -2427,8 +2539,6 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \
#define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS)
-#define MACHINE_DEPENDENT_COMBINE(INSNS) c4x_combine_parallel(INSNS)
-
#define DBR_OUTPUT_SEQEND(FILE) \
if (final_sequence != NULL_RTX) \
{ \
@@ -2447,11 +2557,6 @@ if (final_sequence != NULL_RTX) \
#define NO_FUNCTION_CSE
-/* Repeat block stuff (hook into strength_reduce() in loop.c). */
-
-extern void c4x_rptb_process ();
-#define REPEAT_BLOCK_PROCESS(START, END) c4x_rptb_process(START, END)
-
/* We don't want a leading tab. */
#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING)
@@ -2475,7 +2580,8 @@ extern void c4x_rptb_process ();
{"dp_reg_operand", {REG}}, \
{"sp_reg_operand", {REG}}, \
{"st_reg_operand", {REG}}, \
- {"call_operand", {REG, SYMBOL_REF}}, \
+ {"rc_reg_operand", {REG}}, \
+ {"call_address_operand", {REG, SYMBOL_REF, LABEL_REF, CONST}}, \
{"src_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
{"src_hi_operand", {SUBREG, REG, MEM, CONST_DOUBLE}}, \
{"lsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
@@ -2483,7 +2589,8 @@ extern void c4x_rptb_process ();
{"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
{"par_ind_operand", {MEM}}, \
{"parallel_operand", {SUBREG, REG, MEM}}, \
- {"mem_operand", {MEM}}, \
+ {"symbolic_address_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
+ {"mem_operand", {MEM}},
/* Variables in c4x.c */
@@ -2535,6 +2642,10 @@ extern int stik_const_operand ();
extern int not_const_operand ();
+extern int parallel_operand ();
+
+extern int reg_or_const_operand ();
+
extern int reg_operand ();
extern int reg_imm_operand ();
@@ -2551,6 +2662,8 @@ extern int std_reg_operand ();
extern int src_operand ();
+extern int src_hi_operand ();
+
extern int lsrc_operand ();
extern int tsrc_operand ();
@@ -2563,12 +2676,66 @@ extern int dp_reg_operand ();
extern int sp_reg_operand ();
+extern int rc_reg_operand ();
+
extern int st_reg_operand ();
-extern int call_operand ();
+extern int symbolic_address_operand ();
+
+extern int ar0_reg_operand ();
+
+extern int ar0_mem_operand ();
+
+extern int ar1_reg_operand ();
+
+extern int ar1_mem_operand ();
+
+extern int ar2_reg_operand ();
+
+extern int ar2_mem_operand ();
+
+extern int ar3_reg_operand ();
+
+extern int ar3_mem_operand ();
+
+extern int ar4_reg_operand ();
+
+extern int ar4_mem_operand ();
+
+extern int ar5_reg_operand ();
+
+extern int ar5_mem_operand ();
+
+extern int ar6_reg_operand ();
+
+extern int ar6_mem_operand ();
+
+extern int ar7_reg_operand ();
+
+extern int ar7_mem_operand ();
+
+extern int ir0_reg_operand ();
+
+extern int ir0_mem_operand ();
+
+extern int ir1_reg_operand ();
+
+extern int ir1_mem_operand ();
+
+extern int group1_reg_operand ();
+
+extern int group1_mem_operand ();
+
+extern int arx_reg_operand ();
+
+extern int call_address_operand ();
extern int par_ind_operand ();
+extern int not_rc_reg ();
+
+extern int not_modify_reg ();
+
extern int c4x_H_constant ();
extern int c4x_I_constant ();
@@ -2585,22 +2752,22 @@ extern int c4x_S_constraint ();
extern int c4x_T_constraint ();
+extern int c4x_U_constraint ();
+
extern void c4x_emit_libcall ();
extern void c4x_emit_libcall3 ();
extern void c4x_emit_libcall_mulhi ();
-extern int c4x_group1_reg_operand ();
-
-extern int c4x_group1_mem_operand ();
-
-extern int c4x_arx_reg_operand ();
+extern int c4x_emit_move_sequence ();
extern int legitimize_operands ();
extern int valid_operands ();
+extern int valid_parallel_load_store ();
+
extern int valid_parallel_operands_4 ();
extern int valid_parallel_operands_5 ();