aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@cygnus.com>1999-07-05 08:44:36 +0000
committerNick Clifton <nickc@gcc.gnu.org>1999-07-05 08:44:36 +0000
commit62b10bbc331241e7ceebffb7ef9bfc80884f53d5 (patch)
treee23b7de44adbdbdef1adab420a4cb75426a26a14
parent32bebc4399ed6f3e721b0e81c29ef0f424aa138e (diff)
downloadgcc-62b10bbc331241e7ceebffb7ef9bfc80884f53d5.zip
gcc-62b10bbc331241e7ceebffb7ef9bfc80884f53d5.tar.gz
gcc-62b10bbc331241e7ceebffb7ef9bfc80884f53d5.tar.bz2
Add preliminary support for arm v5 architectures.
From-SVN: r27944
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/config/arm/arm.c284
-rw-r--r--gcc/config/arm/arm.h319
-rw-r--r--gcc/config/arm/coff.h74
-rw-r--r--gcc/config/arm/elf.h204
-rw-r--r--gcc/invoke.texi44
6 files changed, 531 insertions, 416 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 94194a4..ca5086d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,25 @@
+Fri Jul 2 18:49:51 1999 Nick Clifton <nickc@cygnus.com>
+
+ Add framework to support armv5 architecture when it becomes
+ available:
+
+ * config/arm/arm.c (FL_ARCH5): New processor capability flag.
+ (arm_arch5): New variable.
+ (all_architectures): Add armv5 line.
+ * config/arm/arm.h (CPP_CPU_ARCH_SPEC): Define __ARM_ARCH_5__ if
+ -march=armv5 is specified on the command line.
+ (arm_arch5): Export this variable.
+ * invoke.texi: Document new string accepted by -march= switch for
+ ARM ports.
+
+ * config/arm/arm.h: Replace use of constant 12 as a register
+ number with IP_REGNUM. Similarly 14 and LR_REGNUM.
+ * config/arm/arm.c: Replace use of constant 12 as a register
+ number with IP_REGNUM. Similarly 14 and LR_REGNUM.
+
+ * config/arm/elf.h: Tidy up.
+ * config/arm/coff.h: Tidy up.
+
Thu Jul 1 19:08:13 1999 Mark P. Mitchell <mark@codesourcery.com>
* gcc/configure.in (mips-sgi-irix6*): Handle --with-gnu-ld.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d2c037c..be1fa62 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -94,14 +94,15 @@ const char * structure_size_string = NULL;
int arm_structure_size_boundary = 32; /* Used to be 8 */
/* Bit values used to identify processor capabilities. */
-#define FL_CO_PROC 0x01 /* Has external co-processor bus */
-#define FL_FAST_MULT 0x02 /* Fast multiply */
-#define FL_MODE26 0x04 /* 26-bit mode support */
-#define FL_MODE32 0x08 /* 32-bit mode support */
-#define FL_ARCH4 0x10 /* Architecture rel 4 */
-#define FL_THUMB 0x20 /* Thumb aware */
-#define FL_LDSCHED 0x40 /* Load scheduling necessary */
-#define FL_STRONG 0x80 /* StrongARM */
+#define FL_CO_PROC (1 << 0) /* Has external co-processor bus */
+#define FL_FAST_MULT (1 << 1) /* Fast multiply */
+#define FL_MODE26 (1 << 2) /* 26-bit mode support */
+#define FL_MODE32 (1 << 3) /* 32-bit mode support */
+#define FL_ARCH4 (1 << 4) /* Architecture rel 4 */
+#define FL_ARCH5 (1 << 5) /* Architecture rel 5 */
+#define FL_THUMB (1 << 6) /* Thumb aware */
+#define FL_LDSCHED (1 << 7) /* Load scheduling necessary */
+#define FL_STRONG (1 << 8) /* StrongARM */
/* The bits in this mask specify which instructions we are allowed to generate. */
static int insn_flags = 0;
@@ -120,6 +121,9 @@ int arm_fast_multiply = 0;
/* Nonzero if this chip supports the ARM Architecture 4 extensions */
int arm_arch4 = 0;
+/* Nonzero if this chip supports the ARM Architecture 5 extensions */
+int arm_arch5 = 0;
+
/* Nonzero if this chip can benefit from load scheduling. */
int arm_ld_sched = 0;
@@ -229,15 +233,16 @@ static struct processors all_architectures[] =
{
/* ARM Architectures */
- {"armv2", FL_CO_PROC | FL_MODE26 },
- {"armv2a", FL_CO_PROC | FL_MODE26 },
- {"armv3", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"armv3m", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
- {"armv4", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 },
+ { "armv2", FL_CO_PROC | FL_MODE26 },
+ { "armv2a", FL_CO_PROC | FL_MODE26 },
+ { "armv3", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
+ { "armv3m", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
+ { "armv4", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 },
/* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
implementations that support it, so we will leave it out for now. */
- {"armv4t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- {NULL, 0}
+ { "armv4t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
+ { "armv5", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
+ { NULL, 0 }
};
/* This is a magic stucture. The 'string' field is magically filled in
@@ -494,6 +499,7 @@ arm_override_options ()
/* Initialise boolean versions of the flags, for use in the arm.md file. */
arm_fast_multiply = insn_flags & FL_FAST_MULT;
arm_arch4 = insn_flags & FL_ARCH4;
+ arm_arch5 = insn_flags & FL_ARCH5;
arm_ld_sched = tune_flags & FL_LDSCHED;
arm_is_strong = tune_flags & FL_STRONG;
@@ -1279,7 +1285,7 @@ arm_gen_constant (code, mode, val, target, source, subtargets, generate)
enum rtx_code
arm_canonicalize_comparison (code, op1)
enum rtx_code code;
- rtx *op1;
+ rtx * op1;
{
unsigned HOST_WIDE_INT i = INTVAL (*op1);
@@ -1538,7 +1544,7 @@ legitimize_pic_address (orig, mode, reg)
static rtx pic_rtx;
int
-is_pic(x)
+is_pic (x)
rtx x;
{
if (x == pic_rtx)
@@ -1876,7 +1882,8 @@ arm_adjust_cost (insn, link, dep, cost)
static int fpa_consts_inited = 0;
-char *strings_fpa[8] = {
+char * strings_fpa[8] =
+{
"0", "1", "2", "3",
"4", "5", "0.5", "10"
};
@@ -2401,7 +2408,7 @@ int
symbol_mentioned_p (x)
rtx x;
{
- register char *fmt;
+ register char * fmt;
register int i;
if (GET_CODE (x) == SYMBOL_REF)
@@ -2430,7 +2437,7 @@ int
label_mentioned_p (x)
rtx x;
{
- register char *fmt;
+ register char * fmt;
register int i;
if (GET_CODE (x) == LABEL_REF)
@@ -2647,11 +2654,11 @@ store_multiple_operation (op, mode)
int
load_multiple_sequence (operands, nops, regs, base, load_offset)
- rtx *operands;
+ rtx * operands;
int nops;
- int *regs;
- int *base;
- HOST_WIDE_INT *load_offset;
+ int * regs;
+ int * base;
+ HOST_WIDE_INT * load_offset;
{
int unsorted_regs[4];
HOST_WIDE_INT unsorted_offsets[4];
@@ -2820,7 +2827,7 @@ load_multiple_sequence (operands, nops, regs, base, load_offset)
char *
emit_ldm_seq (operands, nops)
- rtx *operands;
+ rtx * operands;
int nops;
{
int regs[4];
@@ -2880,11 +2887,11 @@ emit_ldm_seq (operands, nops)
int
store_multiple_sequence (operands, nops, regs, base, load_offset)
- rtx *operands;
+ rtx * operands;
int nops;
- int *regs;
- int *base;
- HOST_WIDE_INT *load_offset;
+ int * regs;
+ int * base;
+ HOST_WIDE_INT * load_offset;
{
int unsorted_regs[4];
HOST_WIDE_INT unsorted_offsets[4];
@@ -2933,7 +2940,7 @@ store_multiple_sequence (operands, nops, regs, base, load_offset)
{
if (i == 0)
{
- base_reg = REGNO(reg);
+ base_reg = REGNO (reg);
unsorted_regs[0] = (GET_CODE (operands[i]) == REG
? REGNO (operands[i])
: REGNO (SUBREG_REG (operands[i])));
@@ -3017,7 +3024,7 @@ store_multiple_sequence (operands, nops, regs, base, load_offset)
char *
emit_stm_seq (operands, nops)
- rtx *operands;
+ rtx * operands;
int nops;
{
int regs[4];
@@ -3209,7 +3216,7 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
int
arm_gen_movstrqi (operands)
- rtx *operands;
+ rtx * operands;
{
HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
int i;
@@ -3291,27 +3298,27 @@ arm_gen_movstrqi (operands)
/* OUT_WORDS_TO_GO will be zero here if there are byte stores to do. */
if (out_words_to_go)
- {
- rtx sreg;
-
- mem = gen_rtx_MEM (SImode, src);
- RTX_UNCHANGING_P (mem) = src_unchanging_p;
- MEM_IN_STRUCT_P (mem) = src_in_struct_p;
- MEM_SCALAR_P (mem) = src_scalar_p;
- emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
- emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
-
- mem = gen_rtx_MEM (SImode, dst);
- RTX_UNCHANGING_P (mem) = dst_unchanging_p;
- MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
- MEM_SCALAR_P (mem) = dst_scalar_p;
- emit_move_insn (mem, sreg);
- emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
- in_words_to_go--;
-
- if (in_words_to_go) /* Sanity check */
- abort ();
- }
+ {
+ rtx sreg;
+
+ mem = gen_rtx_MEM (SImode, src);
+ RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ MEM_SCALAR_P (mem) = src_scalar_p;
+ emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
+ emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
+
+ mem = gen_rtx_MEM (SImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ MEM_SCALAR_P (mem) = dst_scalar_p;
+ emit_move_insn (mem, sreg);
+ emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
+ in_words_to_go--;
+
+ if (in_words_to_go) /* Sanity check */
+ abort ();
+ }
if (in_words_to_go)
{
@@ -3344,6 +3351,7 @@ arm_gen_movstrqi (operands)
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, gen_rtx_SUBREG (QImode, part_bytes_reg, 0));
+
if (--last_bytes)
{
tmp = gen_reg_rtx (SImode);
@@ -3365,6 +3373,7 @@ arm_gen_movstrqi (operands)
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, gen_rtx_SUBREG (QImode, part_bytes_reg, 0));
+
if (--last_bytes)
{
rtx tmp = gen_reg_rtx (SImode);
@@ -3613,7 +3622,7 @@ gen_compare_reg (code, x, y)
void
arm_reload_in_hi (operands)
- rtx *operands;
+ rtx * operands;
{
rtx ref = operands[1];
rtx base, scratch;
@@ -3729,7 +3738,7 @@ arm_reload_in_hi (operands)
two scratch registers for some corner cases). */
void
arm_reload_out_hi (operands)
- rtx *operands;
+ rtx * operands;
{
rtx ref = operands[0];
rtx outval = operands[1];
@@ -4047,7 +4056,7 @@ dump_table (scan)
for (i = 0; i < pool_size; i++)
{
- pool_node *p = pool_vector + i;
+ pool_node * p = pool_vector + i;
switch (GET_MODE_SIZE (p->mode))
{
@@ -4362,7 +4371,7 @@ fp_immediate_constant (x)
/* As for fp_immediate_constant, but value is passed directly, not in rtx. */
static char *
fp_const_from_val (r)
- REAL_VALUE_TYPE *r;
+ REAL_VALUE_TYPE * r;
{
int i;
@@ -4383,8 +4392,8 @@ fp_const_from_val (r)
void
print_multi_reg (stream, instr, mask, hat)
- FILE *stream;
- char *instr;
+ FILE * stream;
+ char * instr;
int mask, hat;
{
int i;
@@ -4393,11 +4402,13 @@ print_multi_reg (stream, instr, mask, hat)
fputc ('\t', stream);
fprintf (stream, instr, REGISTER_PREFIX);
fputs (", {", stream);
+
for (i = 0; i < 16; i++)
if (mask & (1 << i))
{
if (not_first)
fprintf (stream, ", ");
+
fprintf (stream, "%s%s", REGISTER_PREFIX, reg_names[i]);
not_first = TRUE;
}
@@ -4409,15 +4420,16 @@ print_multi_reg (stream, instr, mask, hat)
char *
output_call (operands)
- rtx *operands;
+ rtx * operands;
{
/* Handle calls to lr using ip (which may be clobbered in subr anyway). */
- if (REGNO (operands[0]) == 14)
+ if (REGNO (operands[0]) == LR_REGNUM)
{
- operands[0] = gen_rtx_REG (SImode, 12);
+ operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
output_asm_insn ("mov%?\t%0, %|lr", operands);
}
+
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
if (TARGET_THUMB_INTERWORK)
@@ -4430,32 +4442,34 @@ output_call (operands)
static int
eliminate_lr2ip (x)
- rtx *x;
+ rtx * x;
{
int something_changed = 0;
- rtx x0 = *x;
+ rtx x0 = * x;
int code = GET_CODE (x0);
register int i, j;
- register char *fmt;
+ register char * fmt;
switch (code)
{
case REG:
- if (REGNO (x0) == 14)
+ if (REGNO (x0) == LR_REGNUM)
{
- *x = gen_rtx_REG (SImode, 12);
+ *x = gen_rtx_REG (SImode, IP_REGNUM);
return 1;
}
return 0;
default:
/* Scan through the sub-elements and change any references there */
fmt = GET_RTX_FORMAT (code);
+
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
something_changed |= eliminate_lr2ip (&XEXP (x0, i));
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x0, i); j++)
something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
+
return something_changed;
}
}
@@ -4464,7 +4478,7 @@ eliminate_lr2ip (x)
char *
output_call_mem (operands)
- rtx *operands;
+ rtx * operands;
{
operands[0] = copy_rtx (operands[0]); /* Be ultra careful */
/* Handle calls using lr by using ip (which may be clobbered in subr anyway).
@@ -4494,13 +4508,13 @@ output_call_mem (operands)
char *
output_mov_long_double_fpu_from_arm (operands)
- rtx *operands;
+ rtx * operands;
{
int arm_reg0 = REGNO (operands[1]);
rtx ops[3];
- if (arm_reg0 == 12)
- abort();
+ if (arm_reg0 == IP_REGNUM)
+ abort ();
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
@@ -4508,6 +4522,7 @@ output_mov_long_double_fpu_from_arm (operands)
output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);
output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);
+
return "";
}
@@ -4517,13 +4532,13 @@ output_mov_long_double_fpu_from_arm (operands)
char *
output_mov_long_double_arm_from_fpu (operands)
- rtx *operands;
+ rtx * operands;
{
int arm_reg0 = REGNO (operands[0]);
rtx ops[3];
- if (arm_reg0 == 12)
- abort();
+ if (arm_reg0 == IP_REGNUM)
+ abort ();
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
@@ -4539,7 +4554,7 @@ output_mov_long_double_arm_from_fpu (operands)
OPERANDS[1] is the source. */
char *
output_mov_long_double_arm_from_arm (operands)
- rtx *operands;
+ rtx * operands;
{
/* We have to be careful here because the two might overlap */
int dest_start = REGNO (operands[0]);
@@ -4576,13 +4591,14 @@ output_mov_long_double_arm_from_arm (operands)
char *
output_mov_double_fpu_from_arm (operands)
- rtx *operands;
+ rtx * operands;
{
int arm_reg0 = REGNO (operands[1]);
rtx ops[2];
- if (arm_reg0 == 12)
- abort();
+ if (arm_reg0 == IP_REGNUM)
+ abort ();
+
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);
@@ -4596,13 +4612,13 @@ output_mov_double_fpu_from_arm (operands)
char *
output_mov_double_arm_from_fpu (operands)
- rtx *operands;
+ rtx * operands;
{
int arm_reg0 = REGNO (operands[0]);
rtx ops[2];
- if (arm_reg0 == 12)
- abort();
+ if (arm_reg0 == IP_REGNUM)
+ abort ();
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
@@ -4632,8 +4648,8 @@ output_move_double (operands)
if (code1 == REG)
{
int reg1 = REGNO (operands[1]);
- if (reg1 == 12)
- abort();
+ if (reg1 == IP_REGNUM)
+ abort ();
/* Ensure the second source is not overwritten */
if (reg1 == reg0 + (WORDS_BIG_ENDIAN ? -1 : 1))
@@ -4783,12 +4799,12 @@ output_move_double (operands)
}
}
else
- abort(); /* Constraints should prevent this */
+ abort (); /* Constraints should prevent this */
}
else if (code0 == MEM && code1 == REG)
{
- if (REGNO (operands[1]) == 12)
- abort();
+ if (REGNO (operands[1]) == IP_REGNUM)
+ abort ();
switch (GET_CODE (XEXP (operands[0], 0)))
{
@@ -4840,7 +4856,7 @@ output_move_double (operands)
}
}
else
- abort(); /* Constraints should prevent this */
+ abort (); /* Constraints should prevent this */
return "";
}
@@ -4851,7 +4867,7 @@ output_move_double (operands)
char *
output_mov_immediate (operands)
- rtx *operands;
+ rtx * operands;
{
HOST_WIDE_INT n = INTVAL (operands[1]);
int n_ones = 0;
@@ -4894,7 +4910,7 @@ output_mov_immediate (operands)
char *
output_add_immediate (operands)
- rtx *operands;
+ rtx * operands;
{
HOST_WIDE_INT n = INTVAL (operands[2]);
@@ -4922,8 +4938,8 @@ output_add_immediate (operands)
static char *
output_multi_immediate (operands, instr1, instr2, immed_op, n)
- rtx *operands;
- char *instr1, *instr2;
+ rtx * operands;
+ char * instr1, * instr2;
int immed_op;
HOST_WIDE_INT n;
{
@@ -5001,7 +5017,7 @@ shift_op (op, amountp)
rtx op;
HOST_WIDE_INT *amountp;
{
- char *mnem;
+ char * mnem;
enum rtx_code code = GET_CODE (op);
if (GET_CODE (XEXP (op, 1)) == REG || GET_CODE (XEXP (op, 1)) == SUBREG)
@@ -5092,8 +5108,8 @@ int_log2 (power)
void
output_ascii_pseudo_op (stream, p, len)
- FILE *stream;
- unsigned char *p;
+ FILE * stream;
+ unsigned char * p;
int len;
{
int i;
@@ -5157,11 +5173,11 @@ pattern_really_clobbers_lr (x)
switch (GET_CODE (SET_DEST (x)))
{
case REG:
- return REGNO (SET_DEST (x)) == 14;
+ return REGNO (SET_DEST (x)) == LR_REGNUM;
case SUBREG:
if (GET_CODE (XEXP (SET_DEST (x), 0)) == REG)
- return REGNO (XEXP (SET_DEST (x), 0)) == 14;
+ return REGNO (XEXP (SET_DEST (x), 0)) == LR_REGNUM;
if (GET_CODE (XEXP (SET_DEST (x), 0)) == MEM)
return 0;
@@ -5181,11 +5197,11 @@ pattern_really_clobbers_lr (x)
switch (GET_CODE (XEXP (x, 0)))
{
case REG:
- return REGNO (XEXP (x, 0)) == 14;
+ return REGNO (XEXP (x, 0)) == LR_REGNUM;
case SUBREG:
if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG)
- return REGNO (XEXP (XEXP (x, 0), 0)) == 14;
+ return REGNO (XEXP (XEXP (x, 0), 0)) == LR_REGNUM;
abort ();
default:
@@ -5295,7 +5311,7 @@ output_return_instruction (operand, really_return, reverse)
return_used_this_function = 1;
- if (volatile_func)
+ if (TARGET_ABORT_NORETURN && volatile_func)
{
rtx ops[2];
/* If this function was declared non-returning, and we have found a tail
@@ -5313,7 +5329,7 @@ output_return_instruction (operand, really_return, reverse)
}
if (current_function_calls_alloca && ! really_return)
- abort();
+ abort ();
for (reg = 0; reg <= 10; reg++)
if (regs_ever_live[reg] && ! call_used_regs[reg])
@@ -5322,7 +5338,7 @@ output_return_instruction (operand, really_return, reverse)
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
live_regs++;
- if (live_regs || (regs_ever_live[14] && ! lr_save_eliminated))
+ if (live_regs || (regs_ever_live[LR_REGNUM] && ! lr_save_eliminated))
live_regs++;
if (frame_pointer_needed)
@@ -5330,7 +5346,7 @@ output_return_instruction (operand, really_return, reverse)
if (live_regs)
{
- if (lr_save_eliminated || ! regs_ever_live[14])
+ if (lr_save_eliminated || ! regs_ever_live[LR_REGNUM])
live_regs++;
if (frame_pointer_needed)
@@ -5341,7 +5357,7 @@ output_return_instruction (operand, really_return, reverse)
reverse ? "ldm%?%D0fd\t%|sp!, {" : "ldm%?%d0fd\t%|sp!, {");
for (reg = 0; reg <= 10; reg++)
- if (regs_ever_live[reg]
+ if (regs_ever_live[reg]
&& (! call_used_regs[reg]
|| (flag_pic && reg == PIC_OFFSET_TABLE_REGNUM)))
{
@@ -5361,15 +5377,15 @@ output_return_instruction (operand, really_return, reverse)
strcat (instr, ", ");
strcat (instr, "%|");
strcat (instr, TARGET_THUMB_INTERWORK || (! really_return)
- ? reg_names[14] : reg_names[15] );
+ ? reg_names[LR_REGNUM] : reg_names[PC_REGNUM] );
}
else
{
strcat (instr, "%|");
if (TARGET_THUMB_INTERWORK && really_return)
- strcat (instr, reg_names[12]);
+ strcat (instr, reg_names[IP_REGNUM]);
else
- strcat (instr, really_return ? reg_names[15] : reg_names[14]);
+ strcat (instr, really_return ? reg_names[PC_REGNUM] : reg_names[LR_REGNUM]);
}
strcat (instr, (TARGET_APCS_32 || !really_return) ? "}" : "}^");
output_asm_insn (instr, &operand);
@@ -5508,13 +5524,13 @@ output_func_prologue (f, frame_size)
if (frame_pointer_needed)
live_regs_mask |= 0xD800;
- else if (regs_ever_live[14])
+ else if (regs_ever_live[LR_REGNUM])
{
if (! current_function_args_size
&& ! function_really_clobbers_lr (get_insns ()))
lr_save_eliminated = 1;
else
- live_regs_mask |= 0x4000;
+ live_regs_mask |= 1 << LR_REGNUM;
}
if (live_regs_mask)
@@ -5524,7 +5540,7 @@ output_func_prologue (f, frame_size)
doing so, in this case we need to push lr as well, or we
will fail to get a proper return. */
- live_regs_mask |= 0x4000;
+ live_regs_mask |= 1 << LR_REGNUM;
lr_save_eliminated = 0;
}
@@ -5543,7 +5559,7 @@ output_func_prologue (f, frame_size)
void
output_func_epilogue (f, frame_size)
- FILE *f;
+ FILE * f;
int frame_size;
{
int reg, live_regs_mask = 0;
@@ -5701,12 +5717,12 @@ output_func_epilogue (f, frame_size)
reg - start_reg, REGISTER_PREFIX);
}
- if (current_function_pretend_args_size == 0 && regs_ever_live[14])
+ if (current_function_pretend_args_size == 0 && regs_ever_live[LR_REGNUM])
{
if (TARGET_THUMB_INTERWORK)
{
if (! lr_save_eliminated)
- live_regs_mask |= 0x4000;
+ live_regs_mask |= 1 << LR_REGNUM;
if (live_regs_mask != 0)
print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE);
@@ -5723,11 +5739,11 @@ output_func_epilogue (f, frame_size)
}
else
{
- if (live_regs_mask || regs_ever_live[14])
+ if (live_regs_mask || regs_ever_live[LR_REGNUM])
{
/* Restore the integer regs, and the return address into lr */
if (! lr_save_eliminated)
- live_regs_mask |= 0x4000;
+ live_regs_mask |= 1 << LR_REGNUM;
if (live_regs_mask != 0)
print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE);
@@ -5856,14 +5872,14 @@ arm_expand_prologue ()
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
live_regs_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
- if (regs_ever_live[14])
- live_regs_mask |= 0x4000;
+ if (regs_ever_live[LR_REGNUM])
+ live_regs_mask |= 1 << LR_REGNUM;
}
if (frame_pointer_needed)
{
live_regs_mask |= 0xD800;
- emit_insn (gen_movsi (gen_rtx_REG (SImode, 12),
+ emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM),
stack_pointer_rtx));
}
@@ -5881,7 +5897,7 @@ arm_expand_prologue ()
{
/* If we have to push any regs, then we must push lr as well, or
we won't get a proper return. */
- live_regs_mask |= 0x4000;
+ live_regs_mask |= 1 << LR_REGNUM;
emit_multi_reg_push (live_regs_mask);
}
@@ -5928,7 +5944,7 @@ arm_expand_prologue ()
}
if (frame_pointer_needed)
- emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, 12),
+ emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, IP_REGNUM),
(GEN_INT
(-(4 + current_function_pretend_args_size)))));
@@ -5963,7 +5979,7 @@ arm_expand_prologue ()
void
arm_print_operand (stream, x, code)
- FILE *stream;
+ FILE * stream;
rtx x;
int code;
{
@@ -6586,17 +6602,17 @@ arm_final_prescan_insn (insn)
rtx aof_pic_label = NULL_RTX;
struct pic_chain
{
- struct pic_chain *next;
- char *symname;
+ struct pic_chain * next;
+ char * symname;
};
-static struct pic_chain *aof_pic_chain = NULL;
+static struct pic_chain * aof_pic_chain = NULL;
rtx
aof_pic_entry (x)
rtx x;
{
- struct pic_chain **chainp;
+ struct pic_chain ** chainp;
int offset;
if (aof_pic_label == NULL_RTX)
@@ -6620,9 +6636,9 @@ aof_pic_entry (x)
void
aof_dump_pic_table (f)
- FILE *f;
+ FILE * f;
{
- struct pic_chain *chain;
+ struct pic_chain * chain;
if (aof_pic_chain == NULL)
return;
@@ -6675,17 +6691,17 @@ aof_data_section ()
struct import
{
- struct import *next;
- char *name;
+ struct import * next;
+ char * name;
};
-static struct import *imports_list = NULL;
+static struct import * imports_list = NULL;
void
aof_add_import (name)
- char *name;
+ char * name;
{
- struct import *new;
+ struct import * new;
for (new = imports_list; new; new = new->next)
if (new->name == name)
@@ -6699,9 +6715,9 @@ aof_add_import (name)
void
aof_delete_import (name)
- char *name;
+ char * name;
{
- struct import **old;
+ struct import ** old;
for (old = &imports_list; *old; old = & (*old)->next)
{
@@ -6717,7 +6733,7 @@ int arm_main_function = 0;
void
aof_dump_imports (f)
- FILE *f;
+ FILE * f;
{
/* The AOF assembler needs this to cause the startup code to be extracted
from the library. Brining in __main causes the whole thing to work
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 629f04a..1fd9207 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -65,7 +65,7 @@ enum arm_cond_code
ARM_HI, ARM_LS, ARM_GE, ARM_LT, ARM_GT, ARM_LE, ARM_AL, ARM_NV
};
extern enum arm_cond_code arm_current_cc;
-extern char *arm_condition_codes[];
+extern char * arm_condition_codes[];
#define ARM_INVERSE_CONDITION_CODE(X) ((enum arm_cond_code) (((int)X) ^ 1))
@@ -153,6 +153,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{march=armv3m:-D__ARM_ARCH_3M__} \
%{march=armv4:-D__ARM_ARCH_4__} \
%{march=armv4t:-D__ARM_ARCH_4T__} \
+%{march=armv5:-D__ARM_ARCH_5__} \
%{!march=*: \
%{mcpu=arm2:-D__ARM_ARCH_2__} \
%{mcpu=arm250:-D__ARM_ARCH_2__} \
@@ -459,6 +460,9 @@ extern int arm_fast_multiply;
/* Nonzero if this chip supports the ARM Architecture 4 extensions */
extern int arm_arch4;
+/* Nonzero if this chip supports the ARM Architecture 5 extensions */
+extern int arm_arch5;
+
/* Nonzero if this chip can benefit from load scheduling. */
extern int arm_ld_sched;
@@ -785,6 +789,12 @@ extern const char * structure_size_string;
should point to a special register that we will make sure is eliminated. */
#define HARD_FRAME_POINTER_REGNUM 11
+/* Register which holds return address from a subroutine call. */
+#define LR_REGNUM 14
+
+/* Scratch register - used in all kinds of places, eg trampolines. */
+#define IP_REGNUM 12
+
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may be accessed
via the stack pointer) in functions that seem suitable.
@@ -944,51 +954,53 @@ enum reg_class
For the ARM, we wish to handle large displacements off a base
register by splitting the addend across a MOV and the mem insn.
This can cut the number of reloads needed. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-do { \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
- && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
- HOST_WIDE_INT low, high; \
- \
- if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \
- low = ((val & 0xf) ^ 0x8) - 0x8; \
- else if (MODE == SImode || MODE == QImode \
- || (MODE == SFmode && TARGET_SOFT_FLOAT) \
- || (MODE == HImode && ! arm_arch4)) \
- /* Need to be careful, -4096 is not a valid offset */ \
- low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff); \
- else if (MODE == HImode && arm_arch4) \
- /* Need to be careful, -256 is not a valid offset */ \
- low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
- else if (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && TARGET_HARD_FLOAT) \
- /* Need to be careful, -1024 is not a valid offset */ \
- low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff); \
- else \
- break; \
- \
- high = ((((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000); \
- /* Check for overflow or zero */ \
- if (low == 0 || high == 0 || (high + low != val)) \
- break; \
- \
- /* Reload the high part into a base reg; leave the low part \
- in the mem. */ \
- X = gen_rtx_PLUS (GET_MODE (X), \
- gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
- GEN_INT (high)), \
- GEN_INT (low)); \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
-} while (0)
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
+ do \
+ { \
+ if (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
+ && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ { \
+ HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
+ HOST_WIDE_INT low, high; \
+ \
+ if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \
+ low = ((val & 0xf) ^ 0x8) - 0x8; \
+ else if (MODE == SImode || MODE == QImode \
+ || (MODE == SFmode && TARGET_SOFT_FLOAT) \
+ || (MODE == HImode && ! arm_arch4)) \
+ /* Need to be careful, -4096 is not a valid offset */ \
+ low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff); \
+ else if (MODE == HImode && arm_arch4) \
+ /* Need to be careful, -256 is not a valid offset */ \
+ low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
+ else if (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ && TARGET_HARD_FLOAT) \
+ /* Need to be careful, -1024 is not a valid offset */ \
+ low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff); \
+ else \
+ break; \
+ \
+ high = ((((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000); \
+ /* Check for overflow or zero */ \
+ if (low == 0 || high == 0 || (high + low != val)) \
+ break; \
+ \
+ /* Reload the high part into a base reg; leave the low part \
+ in the mem. */ \
+ X = gen_rtx_PLUS (GET_MODE (X), \
+ gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
+ GEN_INT (high)), \
+ GEN_INT (low)); \
+ push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
+ BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
+ OPNUM, TYPE); \
+ goto WIN; \
+ } \
+ } \
+ while (0)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
@@ -1189,8 +1201,8 @@ do { \
rtx sym; \
\
fprintf ((STREAM), "\tmov\t%s%s, %s%s\n\tbl\t", \
- REGISTER_PREFIX, reg_names[12] /* ip */, \
- REGISTER_PREFIX, reg_names[14] /* lr */); \
+ REGISTER_PREFIX, reg_names[IP_REGNUM] /* ip */, \
+ REGISTER_PREFIX, reg_names[LR_REGNUM] /* lr */); \
assemble_name ((STREAM), ARM_MCOUNT_NAME); \
fputc ('\n', (STREAM)); \
ASM_GENERATE_INTERNAL_LABEL (temp, "LP", (LABELNO)); \
@@ -1280,7 +1292,7 @@ do { \
if (! frame_pointer_needed) \
offset -= 16; \
if (! volatile_func \
- && (regs_ever_live[14] || saved_hard_reg)) \
+ && (regs_ever_live[LR_REGNUM] || saved_hard_reg)) \
offset += 4; \
offset += current_function_outgoing_args_size; \
(OFFSET) = ((get_frame_size () + 3) & ~3) + offset; \
@@ -1458,54 +1470,55 @@ do { \
/* A C statement (sans semicolon) to jump to LABEL for legitimate index RTXs
used by the macro GO_IF_LEGITIMATE_ADDRESS. Floating point indices can
only be small constants. */
-#define GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL) \
-do \
-{ \
- HOST_WIDE_INT range; \
- enum rtx_code code = GET_CODE (INDEX); \
- \
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
- { \
- if (code == CONST_INT && INTVAL (INDEX) < 1024 \
- && INTVAL (INDEX) > -1024 \
- && (INTVAL (INDEX) & 3) == 0) \
- goto LABEL; \
- } \
- else \
- { \
- if (INDEX_REGISTER_RTX_P (INDEX) && GET_MODE_SIZE (MODE) <= 4) \
- goto LABEL; \
- if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \
- && (! arm_arch4 || (MODE) != HImode)) \
- { \
- rtx xiop0 = XEXP (INDEX, 0); \
- rtx xiop1 = XEXP (INDEX, 1); \
- if (INDEX_REGISTER_RTX_P (xiop0) \
- && power_of_two_operand (xiop1, SImode)) \
- goto LABEL; \
- if (INDEX_REGISTER_RTX_P (xiop1) \
- && power_of_two_operand (xiop0, SImode)) \
- goto LABEL; \
- } \
- if (GET_MODE_SIZE (MODE) <= 4 \
- && (code == LSHIFTRT || code == ASHIFTRT \
- || code == ASHIFT || code == ROTATERT) \
- && (! arm_arch4 || (MODE) != HImode)) \
- { \
- rtx op = XEXP (INDEX, 1); \
- if (INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \
- && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 \
- && INTVAL (op) <= 31) \
- goto LABEL; \
- } \
- /* NASTY: Since this limits the addressing of unsigned byte loads */ \
- range = ((MODE) == HImode || (MODE) == QImode) \
- ? (arm_arch4 ? 256 : 4095) : 4096; \
- if (code == CONST_INT && INTVAL (INDEX) < range \
- && INTVAL (INDEX) > -range) \
- goto LABEL; \
- } \
-} while (0)
+#define GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL) \
+ do \
+ { \
+ HOST_WIDE_INT range; \
+ enum rtx_code code = GET_CODE (INDEX); \
+ \
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ { \
+ if (code == CONST_INT && INTVAL (INDEX) < 1024 \
+ && INTVAL (INDEX) > -1024 \
+ && (INTVAL (INDEX) & 3) == 0) \
+ goto LABEL; \
+ } \
+ else \
+ { \
+ if (INDEX_REGISTER_RTX_P (INDEX) && GET_MODE_SIZE (MODE) <= 4) \
+ goto LABEL; \
+ if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \
+ && (! arm_arch4 || (MODE) != HImode)) \
+ { \
+ rtx xiop0 = XEXP (INDEX, 0); \
+ rtx xiop1 = XEXP (INDEX, 1); \
+ if (INDEX_REGISTER_RTX_P (xiop0) \
+ && power_of_two_operand (xiop1, SImode)) \
+ goto LABEL; \
+ if (INDEX_REGISTER_RTX_P (xiop1) \
+ && power_of_two_operand (xiop0, SImode)) \
+ goto LABEL; \
+ } \
+ if (GET_MODE_SIZE (MODE) <= 4 \
+ && (code == LSHIFTRT || code == ASHIFTRT \
+ || code == ASHIFT || code == ROTATERT) \
+ && (! arm_arch4 || (MODE) != HImode)) \
+ { \
+ rtx op = XEXP (INDEX, 1); \
+ if (INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \
+ && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 \
+ && INTVAL (op) <= 31) \
+ goto LABEL; \
+ } \
+ /* NASTY: Since this limits the addressing of unsigned byte loads */ \
+ range = ((MODE) == HImode || (MODE) == QImode) \
+ ? (arm_arch4 ? 256 : 4095) : 4096; \
+ if (code == CONST_INT && INTVAL (INDEX) < range \
+ && INTVAL (INDEX) > -range) \
+ goto LABEL; \
+ } \
+ } \
+ while (0)
/* Jump to LABEL if X is a valid address RTX. This must also take
REG_OK_STRICT into account when deciding about valid registers, but it uses
@@ -1588,7 +1601,6 @@ do \
On the ARM, try to convert [REG, #BIGCONST]
into ADD BASE, REG, #UPPERCONST and [BASE, #VALIDCONST],
where VALIDCONST == 0 in case of TImode. */
-extern struct rtx_def *legitimize_pic_address ();
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
{ \
if (GET_CODE (X) == PLUS) \
@@ -1767,7 +1779,7 @@ extern struct rtx_def *legitimize_pic_address ();
((X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
|| (X) == arg_pointer_rtx)
-#define DEFAULT_RTX_COSTS(X,CODE,OUTER_CODE) \
+#define DEFAULT_RTX_COSTS(X, CODE, OUTER_CODE) \
return arm_rtx_costs (X, CODE);
/* Moves to and from memory are quite expensive */
@@ -1851,18 +1863,19 @@ extern int making_const_table;
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
-#define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
-do \
-{ \
- if (GET_CODE (OP1) == CONST_INT \
- && ! (const_ok_for_arm (INTVAL (OP1)) \
- || (const_ok_for_arm (- INTVAL (OP1))))) \
- { \
- rtx const_op = OP1; \
- CODE = arm_canonicalize_comparison ((CODE), &const_op); \
- OP1 = const_op; \
- } \
-} while (0)
+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+ do \
+ { \
+ if (GET_CODE (OP1) == CONST_INT \
+ && ! (const_ok_for_arm (INTVAL (OP1)) \
+ || (const_ok_for_arm (- INTVAL (OP1))))) \
+ { \
+ rtx const_op = OP1; \
+ CODE = arm_canonicalize_comparison ((CODE), &const_op); \
+ OP1 = const_op; \
+ } \
+ } \
+ while (0)
#define STORE_FLAG_VALUE 1
@@ -1870,7 +1883,8 @@ do \
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
-extern struct rtx_def *arm_compare_op0, *arm_compare_op1;
+extern struct rtx_def * arm_compare_op0;
+extern struct rtx_def * arm_compare_op1;
/* Define the codes that are matched by predicates in arm.c */
#define PREDICATE_CODES \
@@ -1914,22 +1928,23 @@ extern struct rtx_def *arm_compare_op0, *arm_compare_op1;
/* Output an internal label definition. */
#ifndef ASM_OUTPUT_INTERNAL_LABEL
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
- do \
- { \
+#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
+ do \
+ { \
char * s = (char *) alloca (40 + strlen (PREFIX)); \
- extern int arm_target_label, arm_ccfsm_state; \
+ extern int arm_target_label, arm_ccfsm_state; \
extern rtx arm_target_insn; \
- \
- if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
- && !strcmp (PREFIX, "L")) \
+ \
+ if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
+ && !strcmp (PREFIX, "L")) \
{ \
- arm_ccfsm_state = 0; \
+ arm_ccfsm_state = 0; \
arm_target_insn = NULL; \
} \
- ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
- ASM_OUTPUT_LABEL (STREAM, s); \
- } while (0)
+ ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
+ ASM_OUTPUT_LABEL (STREAM, s); \
+ } \
+ while (0)
#endif
/* Output a push or a pop instruction (only used when profiling). */
@@ -2076,34 +2091,36 @@ extern struct rtx_def *arm_compare_op0, *arm_compare_op1;
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance. */
-#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
-do { \
- int mi_delta = (DELTA); \
- char *mi_op = mi_delta < 0 ? "sub" : "add"; \
- int shift = 0; \
- int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION)))\
- ? 1 : 0); \
- if (mi_delta < 0) mi_delta = -mi_delta; \
- while (mi_delta != 0) \
- { \
- if (mi_delta & (3 << shift) == 0) \
- shift += 2; \
- else \
- { \
- fprintf (FILE, "\t%s\t%s%s, %s%s, #%d\n", \
- mi_op, REGISTER_PREFIX, reg_names[this_regno], \
- REGISTER_PREFIX, reg_names[this_regno], \
- mi_delta & (0xff << shift)); \
- mi_delta &= ~(0xff << shift); \
- shift += 8; \
- } \
- } \
- fputs ("\tb\t", FILE); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- if (NEED_PLT_GOT) \
- fputs ("(PLT)", FILE); \
- fputc ('\n', FILE); \
-} while (0)
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+ do \
+ { \
+ int mi_delta = (DELTA); \
+ char * mi_op = mi_delta < 0 ? "sub" : "add"; \
+ int shift = 0; \
+ int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) \
+ ? 1 : 0); \
+ if (mi_delta < 0) mi_delta = -mi_delta; \
+ while (mi_delta != 0) \
+ { \
+ if (mi_delta & (3 << shift) == 0) \
+ shift += 2; \
+ else \
+ { \
+ fprintf (FILE, "\t%s\t%s%s, %s%s, #%d\n", \
+ mi_op, REGISTER_PREFIX, reg_names[this_regno], \
+ REGISTER_PREFIX, reg_names[this_regno], \
+ mi_delta & (0xff << shift)); \
+ mi_delta &= ~(0xff << shift); \
+ shift += 8; \
+ } \
+ } \
+ fputs ("\tb\t", FILE); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ if (NEED_PLT_GOT) \
+ fputs ("(PLT)", FILE); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame. */
diff --git a/gcc/config/arm/coff.h b/gcc/config/arm/coff.h
index ed4511a..478ae62 100644
--- a/gcc/config/arm/coff.h
+++ b/gcc/config/arm/coff.h
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32)
-#define MULTILIB_DEFAULTS { "mlittle-endian", "msoft-float", "mapcs-32" }
+#define MULTILIB_DEFAULTS { "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
/* Setting this to 32 produces more efficient code, but the value set in previous
versions of this toolchain was 8, which produces more compact structures. The
@@ -50,7 +50,7 @@ extern int arm_structure_size_boundary;
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
+ arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
/* This is COFF, but prefer stabs. */
#define SDB_DEBUGGING_INFO
@@ -68,31 +68,35 @@ arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
ordinary symbol, or gdb won't see it. The stabs entry must be
before the N_SO in order for gdb to find it. */
#define ASM_IDENTIFY_GCC(STREAM) \
- fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
+ fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#undef ASM_FILE_START
-#define ASM_FILE_START(STREAM) \
-do { \
- extern char *version_string; \
- fprintf (STREAM, "%s Generated by gcc %s for ARM/coff\n", \
- ASM_COMMENT_START, version_string); \
-} while (0)
+#define ASM_FILE_START(STREAM) \
+ do \
+ { \
+ extern char * version_string; \
+ fprintf (STREAM, "%s Generated by gcc %s for ARM/coff\n", \
+ ASM_COMMENT_START, version_string); \
+ } \
+ while (0)
/* A C statement to output something to the assembler file to switch to section
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
-#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
-do { \
- if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
- fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \
- else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
- fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \
- else \
- fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \
-} while (0)
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+ do \
+ { \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
+ fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \
+ else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
+ fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \
+ else \
+ fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \
+ } \
+ while (0)
/* Support the ctors/dtors and other sections. */
@@ -171,24 +175,28 @@ dtors_section () \
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#undef ASM_OUTPUT_CONSTRUCTOR
-#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
-do { \
- ctors_section (); \
- fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
- assemble_name (STREAM, NAME); \
- fprintf (STREAM, "\n"); \
-} while (0)
+#define ASM_OUTPUT_CONSTRUCTOR(STREAM, NAME) \
+ do \
+ { \
+ ctors_section (); \
+ fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+ } \
+ while (0)
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
#undef ASM_OUTPUT_DESTRUCTOR
-#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
-do { \
- dtors_section (); \
- fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
- assemble_name (STREAM, NAME); \
- fprintf (STREAM, "\n"); \
-} while (0)
+#define ASM_OUTPUT_DESTRUCTOR(STREAM, NAME) \
+ do \
+ { \
+ dtors_section (); \
+ fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+ } \
+ while (0)
/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */
#define CTOR_LISTS_DEFINED_EXTERNALLY
@@ -205,5 +213,5 @@ do { \
#define HAVE_ATEXIT
/* The ARM development system defines __main. */
-#define NAME__MAIN "__gccmain"
+#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h
index 63ec125..0b39e0d 100644
--- a/gcc/config/arm/elf.h
+++ b/gcc/config/arm/elf.h
@@ -76,69 +76,75 @@ Boston, MA 02111-1307, USA. */
while (0)
/* Write the extra assembler code needed to declare an object properly. */
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do { \
- fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } while (0)
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ putc (',', FILE); \
+ fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
+ putc ('\n', FILE); \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ putc (',', FILE); \
+ fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
+ int_size_in_bytes (TREE_TYPE (DECL))); \
+ fputc ('\n', FILE); \
+ } \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } \
+ while (0)
/* Output the size directive for a decl in rest_of_decl_compilation
in the case where we did not do so before the initializer.
Once we find the error_mark_node, we know that the value of
size_directive_output was set
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
-#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
-do { \
- char * name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
- && ! AT_END && TOP_LEVEL \
- && DECL_INITIAL (DECL) == error_mark_node \
- && !size_directive_output) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
- } \
- } while (0)
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
+ do \
+ { \
+ char * name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, name); \
+ putc (',', FILE); \
+ fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
+ int_size_in_bytes (TREE_TYPE (DECL))); \
+ fputc ('\n', FILE); \
+ } \
+ } \
+ while (0)
/* This is how to declare the size of a function. */
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do { \
- if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno ++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
- } while (0)
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ char label[256]; \
+ static int labelno; \
+ labelno ++; \
+ ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, (FNAME)); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, label); \
+ fprintf (FILE, "-"); \
+ assemble_name (FILE, (FNAME)); \
+ putc ('\n', FILE); \
+ } \
+ } \
+ while (0)
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
@@ -180,7 +186,7 @@ extern int arm_structure_size_boundary;
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
+ arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
/* A C statement to output assembler commands which will identify the
@@ -193,39 +199,42 @@ arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
before the N_SO in order for gdb to find it. */
#ifndef ASM_IDENTIFY_GCC
#define ASM_IDENTIFY_GCC(STREAM) \
- fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
+ fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
#endif
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#ifndef ASM_FILE_START
-#define ASM_FILE_START(STREAM) \
-do { \
- extern char * version_string; \
- fprintf (STREAM, "%s Generated by gcc %s for ARM/elf\n", \
- ASM_COMMENT_START, version_string); \
- output_file_directive ((STREAM), main_input_filename); \
-} while (0)
+#define ASM_FILE_START(STREAM) \
+ do \
+ { \
+ extern char * version_string; \
+ fprintf (STREAM, "%s Generated by gcc %s for ARM/elf\n", \
+ ASM_COMMENT_START, version_string); \
+ output_file_directive ((STREAM), main_input_filename); \
+ } \
+ while (0)
#endif
-
+
/* Output an internal label definition. */
#ifndef ASM_OUTPUT_INTERNAL_LABEL
#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
- do \
- { \
+ do \
+ { \
char * s = (char *) alloca (40 + strlen (PREFIX)); \
- extern int arm_target_label, arm_ccfsm_state; \
+ extern int arm_target_label, arm_ccfsm_state; \
extern rtx arm_target_insn; \
- \
- if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
+ \
+ if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
&& !strcmp (PREFIX, "L")) \
{ \
- arm_ccfsm_state = 0; \
+ arm_ccfsm_state = 0; \
arm_target_insn = NULL; \
} \
- ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
- ASM_OUTPUT_LABEL (STREAM, s); \
- } while (0)
+ ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
+ arm_asm_output_label (STREAM, s); \
+ } \
+ while (0)
#endif
/* Support the ctors/dtors and other sections. */
@@ -308,32 +317,41 @@ dtors_section () \
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#ifndef ASM_OUTPUT_CONSTRUCTOR
-#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
-do { \
- ctors_section (); \
- fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
- assemble_name (STREAM, NAME); \
- fprintf (STREAM, "\n"); \
-} while (0)
+#define ASM_OUTPUT_CONSTRUCTOR(STREAM, NAME) \
+ do \
+ { \
+ ctors_section (); \
+ fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+ } \
+ while (0)
#endif
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
#ifndef ASM_OUTPUT_DESTRUCTOR
-#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
-do { \
- dtors_section (); \
- fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
- assemble_name (STREAM, NAME); \
- fprintf (STREAM, "\n"); \
-} while (0)
+#define ASM_OUTPUT_DESTRUCTOR(STREAM, NAME) \
+ do \
+ { \
+ dtors_section (); \
+ fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+ } \
+ while (0)
#endif
/* This is how we tell the assembler that a symbol is weak. */
-#define ASM_WEAKEN_LABEL(FILE,NAME) \
- do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); } while (0)
+#define ASM_WEAKEN_LABEL(FILE, NAME) \
+ do \
+ { \
+ fputs ("\t.weak\t", FILE); \
+ assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
/* For PIC code we need to explicitly specify (PLT) and (GOT) relocs. */
#define NEED_PLT_GOT flag_pic
@@ -345,10 +363,10 @@ do { \
machine. Use this macro to limit the alignment which can be
specified using the `__attribute__ ((aligned (N)))' construct. If
not defined, the default value is `BIGGEST_ALIGNMENT'. */
-#define MAX_OFILE_ALIGNMENT (32768*8)
+#define MAX_OFILE_ALIGNMENT (32768 * 8)
/* Align output to a power of two. */
#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- fprintf (STREAM, "\t.align\t%d\n", POWER)
+ fprintf (STREAM, "\t.align\t%d\n", POWER)
#include "arm/aout.h"
diff --git a/gcc/invoke.texi b/gcc/invoke.texi
index 655a156..1902c2a 100644
--- a/gcc/invoke.texi
+++ b/gcc/invoke.texi
@@ -263,6 +263,7 @@ in the following sections.
-mbsd -mxopen -mno-symrename
-mabort-on-noreturn
-mno-sched-prolog
+-mnop-fun-dllimport -mno-nop-fun-dllimport
@emph{Thumb Options}
-mtpcs-frame -mno-tpcs-frame
@@ -270,6 +271,9 @@ in the following sections.
-mlittle-endian -mbig-endian
-mthumb-interwork -mno-thumb-interwork
-mstructure-size-boundary=
+-mnop-fun-dllimport -mno-nop-fun-dllimport
+-mcallee-super-interworking -mno-callee-super-interworking
+-mcaller-super-interworking -mno-caller-super-interworking
@emph{MN10200 Options}
-mrelax
@@ -3853,17 +3857,25 @@ suppresses this pass. The post-processor is never run when the
compiler is built for cross-compilation.
@item -mcpu=<name>
-@itemx -mtune=<name>
@kindex -mcpu=
-@kindex -mtune=
This specifies the name of the target ARM processor. GCC uses this name
to determine what kind of instructions it can use when generating
assembly code. Permissable names are: arm2, arm250, arm3, arm6, arm60,
arm600, arm610, arm620, arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi,
arm70, arm700, arm700i, arm710, arm710c, arm7100, arm7500, arm7500fe,
arm7tdmi, arm8, strongarm, strongarm110, strongarm1100, arm8, arm810,
-arm9, arm9tdmi. @samp{-mtune=} is a synonym for @samp{-mcpue=} to
-support older versions of GCC.
+arm9, arm920, arm920t, arm9tdmi.
+
+@itemx -mtune=<name>
+@kindex -mtune=
+This option is very similar to the @samp{-mcpu=} option, except that
+instead of specifying the actual target processor type, and hence
+restricting which instructions can be used, it specifies that GCC should
+tune the performance of the code as if the target were of the type
+specified in this option, but still choosing the instructions that it
+will generate based on the cpu specified by a @samp{-mcpu=} option.
+For some arm implementations better performance can be obtained by using
+this option.
@item -march=<name>
@kindex -march=
@@ -3871,7 +3883,7 @@ This specifies the name of the target ARM architecture. GCC uses this
name to determine what kind of instructions it can use when generating
assembly code. This option can be used in conjunction with or instead
of the @samp{-mcpu=} option. Permissable names are: armv2, armv2a,
-armv3, armv3m, armv4, armv4t
+armv3, armv3m, armv4, armv4t, armv5.
@item -mfpe=<number>
@itemx -mfp=<number>
@@ -3900,6 +3912,10 @@ value as future versions of the toolchain may default to this value.
Generate a call to the function abort at the end of a noreturn function.
It will be executed if the function tries to return.
+@item -mnop-fun-dllimport
+@kindex -mnop-fun-dllimport
+Disable the support for the @emph{dllimport} attribute.
+
@end table
@node Thumb Options
@@ -3953,6 +3969,24 @@ libraries compiled with the other value, if they exchange information
using structures or unions. Programmers are encouraged to use the 32
value as future versions of the toolchain may default to this value.
+@item -mnop-fun-dllimport
+@kindex -mnop-fun-dllimport
+Disable the support for the @emph{dllimport} attribute.
+
+@item -mcallee-super-interworking
+@kindex -mcallee-super-interworking
+Gives all externally visible functions in the file being compiled an ARM
+instruction set header which switches to Thumb mode before executing the
+rest of the function. This allows these functions to be called from
+non-interworking code.
+
+@item -mcaller-super-interworking
+@kindex -mcaller-super-interworking
+Allows calls via function pointers (including virtual functions) to
+execute correctly regardless of whether the target code has been
+compiled for interworking or not. There is a small overhead in the cost
+of executing a funciton pointer if this option is enabled.
+
@end table
@node MN10200 Options