summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/arm
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
committerobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
commitc8f5fc7032940ad6633f932ac40cade82ec4d0cc (patch)
tree29a0f0a6c79a69ecc64f612947a0fe5904311713 /contrib/gcc/config/arm
parentc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (diff)
downloadFreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.zip
FreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.tar.gz
Gcc 3.1.0 pre-release from the FSF anoncvs repo on 9-May-2002 15:57:15 EDT.
Diffstat (limited to 'contrib/gcc/config/arm')
-rw-r--r--contrib/gcc/config/arm/aof.h13
-rw-r--r--contrib/gcc/config/arm/aout.h12
-rw-r--r--contrib/gcc/config/arm/arm.c323
-rw-r--r--contrib/gcc/config/arm/arm.h23
-rw-r--r--contrib/gcc/config/arm/arm.md71
-rw-r--r--contrib/gcc/config/arm/coff.h4
-rw-r--r--contrib/gcc/config/arm/elf.h4
-rw-r--r--contrib/gcc/config/arm/linux-elf.h8
-rw-r--r--contrib/gcc/config/arm/netbsd.h11
-rw-r--r--contrib/gcc/config/arm/rtems-elf.h13
10 files changed, 260 insertions, 222 deletions
diff --git a/contrib/gcc/config/arm/aof.h b/contrib/gcc/config/arm/aof.h
index 750bc08..f110ea2 100644
--- a/contrib/gcc/config/arm/aof.h
+++ b/contrib/gcc/config/arm/aof.h
@@ -120,6 +120,10 @@ do { \
(*ptr++) (); \
} while (0)
+/* We really want to put Thumb tables in a read-only data section, but
+ switching to another section during function output is not
+ possible. We could however do what the SPARC does and defer the
+ whole table generation until the end of the function. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
#ifndef ARM_OS_NAME
@@ -322,8 +326,13 @@ do { \
/* Output of Dispatch Tables */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE))
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
+ do { \
+ if (TARGET_ARM) \
+ fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE)); \
+ else \
+ fprintf ((STREAM), "\tDCD\t|L..%d| - |L..%d|\n", (VALUE), (REL)); \
+ } while (0)
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
fprintf ((STREAM), "\tDCD\t|L..%d|\n", (VALUE))
diff --git a/contrib/gcc/config/arm/aout.h b/contrib/gcc/config/arm/aout.h
index 64ca8b7..868eee0 100644
--- a/contrib/gcc/config/arm/aout.h
+++ b/contrib/gcc/config/arm/aout.h
@@ -181,8 +181,16 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
asm_fprintf (STREAM, "\t.word\t%LL%d\n", VALUE)
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
- asm_fprintf (STREAM, "\tb\t%LL%d\n", VALUE)
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+ do \
+ { \
+ if (TARGET_ARM) \
+ asm_fprintf (STREAM, "\tb\t%LL%d\n", VALUE); \
+ else \
+ asm_fprintf (STREAM, "\t.word\t%LL%d-%LL%d\n", VALUE, REL); \
+ } \
+ while (0)
+
#undef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \
diff --git a/contrib/gcc/config/arm/arm.c b/contrib/gcc/config/arm/arm.c
index dd823a2..4ef7279 100644
--- a/contrib/gcc/config/arm/arm.c
+++ b/contrib/gcc/config/arm/arm.c
@@ -266,12 +266,9 @@ int thumb_code = 0;
PRINT_OPERAND_ADDRESS. */
enum machine_mode output_memory_reference_mode;
-/* Nonzero if the prologue must setup `fp'. */
-int current_function_anonymous_args;
-
/* The register number to be used for the PIC offset register. */
const char * arm_pic_register_string = NULL;
-int arm_pic_register = 9;
+int arm_pic_register = INVALID_REGNUM;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
@@ -654,8 +651,8 @@ arm_override_options ()
/* If stack checking is disabled, we can use r10 as the PIC register,
which keeps r9 available. */
- if (flag_pic && !TARGET_APCS_STACK)
- arm_pic_register = 10;
+ if (flag_pic)
+ arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
if (TARGET_APCS_FLOAT)
warning ("passing floating point arguments in fp regs not yet supported");
@@ -716,18 +713,16 @@ arm_override_options ()
if (arm_pic_register_string != NULL)
{
- int pic_register;
-
+ int pic_register = decode_reg_name (arm_pic_register_string);
+
if (!flag_pic)
warning ("-mpic-register= is useless without -fpic");
- pic_register = decode_reg_name (arm_pic_register_string);
-
/* Prevent the user from choosing an obviously stupid PIC register. */
- if (pic_register < 0 || call_used_regs[pic_register]
- || pic_register == HARD_FRAME_POINTER_REGNUM
- || pic_register == STACK_POINTER_REGNUM
- || pic_register >= PC_REGNUM)
+ else if (pic_register < 0 || call_used_regs[pic_register]
+ || pic_register == HARD_FRAME_POINTER_REGNUM
+ || pic_register == STACK_POINTER_REGNUM
+ || pic_register >= PC_REGNUM)
error ("unable to use '%s' for PIC register", arm_pic_register_string);
else
arm_pic_register = pic_register;
@@ -902,14 +897,14 @@ use_return_insn (iscond)
func_type = arm_current_func_type ();
- /* Naked functions, volatile functiond and interrupt
- functions all need special consideration. */
- if (func_type & (ARM_FT_INTERRUPT | ARM_FT_VOLATILE | ARM_FT_NAKED))
+ /* Naked functions and volatile functions need special
+ consideration. */
+ if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))
return 0;
/* As do variadic functions. */
if (current_function_pretend_args_size
- || current_function_anonymous_args
+ || cfun->machine->uses_anonymous_args
/* Of if the function calls __builtin_eh_return () */
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
/* Or if there is no frame pointer and there is a stack adjustment. */
@@ -2102,9 +2097,6 @@ arm_encode_call_attribute (decl, flag)
int len = strlen (str);
char * newstr;
- if (TREE_CODE (decl) != FUNCTION_DECL)
- return;
-
/* Do not allow weak functions to be treated as short call. */
if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
return;
@@ -2318,7 +2310,10 @@ legitimize_pic_address (orig, mode, reg)
else
emit_insn (gen_pic_load_addr_thumb (address, orig));
- if (GET_CODE (orig) == LABEL_REF && NEED_GOT_RELOC)
+ if ((GET_CODE (orig) == LABEL_REF
+ || (GET_CODE (orig) == SYMBOL_REF &&
+ ENCODED_SHORT_CALL_ATTR_P (XSTR (orig, 0))))
+ && NEED_GOT_RELOC)
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
else
{
@@ -5334,14 +5329,29 @@ is_jump_table (insn)
return NULL_RTX;
}
+#ifndef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 0
+#endif
+
static HOST_WIDE_INT
get_jump_table_size (insn)
rtx insn;
{
- rtx body = PATTERN (insn);
- int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
+ /* ADDR_VECs only take room if read-only data does into the text
+ section. */
+ if (JUMP_TABLES_IN_TEXT_SECTION
+#if !defined(READONLY_DATA_SECTION)
+ || 1
+#endif
+ )
+ {
+ rtx body = PATTERN (insn);
+ int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
+
+ return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
+ }
- return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
+ return 0;
}
/* Move a minipool fix MP from its current location to before MAX_MP.
@@ -7139,17 +7149,16 @@ arm_compute_save_reg_mask ()
/* Decide if we need to save the link register.
Interrupt routines have their own banked link register,
so they never need to save it.
- Otheriwse if we do not use the link register we do not need to save
+ Otherwise if we do not use the link register we do not need to save
it. If we are pushing other registers onto the stack however, we
can save an instruction in the epilogue by pushing the link register
now and then popping it back into the PC. This incurs extra memory
accesses though, so we only do it when optimising for size, and only
if we know that we will not need a fancy return sequence. */
- if (! IS_INTERRUPT (func_type)
- && (regs_ever_live [LR_REGNUM]
+ if (regs_ever_live [LR_REGNUM]
|| (save_reg_mask
&& optimize_size
- && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL)))
+ && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL))
save_reg_mask |= 1 << LR_REGNUM;
if (cfun->machine->lr_save_eliminated)
@@ -7207,21 +7216,19 @@ output_return_instruction (operand, really_return, reverse)
live_regs_mask = arm_compute_save_reg_mask ();
- /* On some ARM architectures it is faster to use LDR rather than LDM to
- load a single register. On other architectures, the cost is the same.
- In 26 bit mode we have to use LDM in order to be able to restore the CPSR. */
- if ((live_regs_mask == (1 << LR_REGNUM))
- && ! TARGET_INTERWORK
- && ! IS_INTERRUPT (func_type)
- && (! really_return || TARGET_APCS_32))
+ if (live_regs_mask)
{
- if (! really_return)
- sprintf (instr, "ldr%s\t%%|lr, [%%|sp], #4", conditional);
+ const char * return_reg;
+
+ /* If we do not have any special requirements for function exit
+ (eg interworking, or ISR) then we can load the return address
+ directly into the PC. Otherwise we must load it into LR. */
+ if (really_return
+ && ! TARGET_INTERWORK)
+ return_reg = reg_names[PC_REGNUM];
else
- sprintf (instr, "ldr%s\t%%|pc, [%%|sp], #4", conditional);
- }
- else if (live_regs_mask)
- {
+ return_reg = reg_names[LR_REGNUM];
+
if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM))
/* There are two possible reasons for the IP register being saved.
Either a stack frame was created, in which case IP contains the
@@ -7233,96 +7240,91 @@ output_return_instruction (operand, really_return, reverse)
live_regs_mask |= (1 << SP_REGNUM);
}
- /* Generate the load multiple instruction to restore the registers. */
- if (frame_pointer_needed)
- sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
- else
- sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
-
- for (reg = 0; reg <= SP_REGNUM; reg++)
- if (live_regs_mask & (1 << reg))
- {
- strcat (instr, "%|");
- strcat (instr, reg_names[reg]);
- strcat (instr, ", ");
- }
-
- if ((live_regs_mask & (1 << LR_REGNUM)) == 0)
+ /* On some ARM architectures it is faster to use LDR rather than
+ LDM to load a single register. On other architectures, the
+ cost is the same. In 26 bit mode, or for exception handlers,
+ we have to use LDM to load the PC so that the CPSR is also
+ restored. */
+ for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
{
- /* If we are not restoring the LR register then we will
- have added one too many commas to the list above.
- Replace it with a closing brace. */
- instr [strlen (instr) - 2] = '}';
+ if (live_regs_mask == (unsigned int)(1 << reg))
+ break;
}
- else
+ if (reg <= LAST_ARM_REGNUM
+ && (reg != LR_REGNUM
+ || ! really_return
+ || (TARGET_APCS_32 && ! IS_INTERRUPT (func_type))))
{
- strcat (instr, "%|");
-
- /* At this point there should only be one or two registers left in
- live_regs_mask: always LR, and possibly PC if we created a stack
- frame. LR contains the return address. If we do not have any
- special requirements for function exit (eg interworking, or ISR)
- then we can load this value directly into the PC and save an
- instruction. */
- if (! TARGET_INTERWORK
- && ! IS_INTERRUPT (func_type)
- && really_return)
- strcat (instr, reg_names [PC_REGNUM]);
- else
- strcat (instr, reg_names [LR_REGNUM]);
-
- strcat (instr, (TARGET_APCS_32 || !really_return) ? "}" : "}^");
+ sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional,
+ (reg == LR_REGNUM) ? return_reg : reg_names[reg]);
}
-
- if (really_return)
+ else
{
- /* See if we need to generate an extra instruction to
- perform the actual function return. */
- switch ((int) ARM_FUNC_TYPE (func_type))
- {
- case ARM_FT_ISR:
- case ARM_FT_FIQ:
- output_asm_insn (instr, & operand);
+ char *p;
+ int first = 1;
- strcpy (instr, "sub");
- strcat (instr, conditional);
- strcat (instr, "s\t%|pc, %|lr, #4");
- break;
+ /* Generate the load multiple instruction to restore the registers. */
+ if (frame_pointer_needed)
+ sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
+ else
+ sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
- case ARM_FT_EXCEPTION:
- output_asm_insn (instr, & operand);
+ p = instr + strlen (instr);
- strcpy (instr, "mov");
- strcat (instr, conditional);
- strcat (instr, "s\t%|pc, %|lr");
- break;
+ for (reg = 0; reg <= SP_REGNUM; reg++)
+ if (live_regs_mask & (1 << reg))
+ {
+ int l = strlen (reg_names[reg]);
- case ARM_FT_INTERWORKED:
- output_asm_insn (instr, & operand);
+ if (first)
+ first = 0;
+ else
+ {
+ memcpy (p, ", ", 2);
+ p += 2;
+ }
- strcpy (instr, "bx");
- strcat (instr, conditional);
- strcat (instr, "\t%|lr");
- break;
+ memcpy (p, "%|", 2);
+ memcpy (p + 2, reg_names[reg], l);
+ p += l + 2;
+ }
+
+ if (live_regs_mask & (1 << LR_REGNUM))
+ {
+ int l = strlen (return_reg);
- default:
- /* The return has already been handled
- by loading the LR into the PC. */
- if ((live_regs_mask & (1 << LR_REGNUM)) == 0)
+ if (! first)
{
- output_asm_insn (instr, & operand);
-
- strcpy (instr, "mov");
- strcat (instr, conditional);
- if (! TARGET_APCS_32)
- strcat (instr, "s");
- strcat (instr, "\t%|pc, %|lr");
+ memcpy (p, ", ", 2);
+ p += 2;
}
- break;
+
+ memcpy (p, "%|", 2);
+ memcpy (p + 2, return_reg, l);
+ strcpy (p + 2 + l, ((TARGET_APCS_32
+ && !IS_INTERRUPT (func_type))
+ || !really_return)
+ ? "}" : "}^");
}
+ else
+ strcpy (p, "}");
+ }
+
+ output_asm_insn (instr, & operand);
+
+ /* See if we need to generate an extra instruction to
+ perform the actual function return. */
+ if (really_return
+ && func_type != ARM_FT_INTERWORKED
+ && (live_regs_mask & (1 << LR_REGNUM)) != 0)
+ {
+ /* The return has already been handled
+ by loading the LR into the PC. */
+ really_return = 0;
}
}
- else if (really_return)
+
+ if (really_return)
{
switch ((int) ARM_FUNC_TYPE (func_type))
{
@@ -7340,18 +7342,19 @@ output_return_instruction (operand, really_return, reverse)
break;
default:
- sprintf (instr, "mov%s%s\t%%|pc, %%|lr",
- conditional, TARGET_APCS_32 ? "" : "s");
+ /* ARMv5 implementations always provide BX, so interworking
+ is the default unless APCS-26 is in use. */
+ if ((insn_flags & FL_ARCH5) != 0 && TARGET_APCS_32)
+ sprintf (instr, "bx%s\t%%|lr", conditional);
+ else
+ sprintf (instr, "mov%s%s\t%%|pc, %%|lr",
+ conditional, TARGET_APCS_32 ? "" : "s");
break;
}
+
+ output_asm_insn (instr, & operand);
}
- else
- /* Nothing to load off the stack, and
- no return instruction to generate. */
- return "";
- output_asm_insn (instr, & operand);
-
return "";
}
@@ -7457,9 +7460,9 @@ arm_output_function_prologue (f, frame_size)
current_function_args_size,
current_function_pretend_args_size, frame_size);
- asm_fprintf (f, "\t%@ frame_needed = %d, current_function_anonymous_args = %d\n",
+ asm_fprintf (f, "\t%@ frame_needed = %d, uses_anonymous_args = %d\n",
frame_pointer_needed,
- current_function_anonymous_args);
+ cfun->machine->uses_anonymous_args);
if (cfun->machine->lr_save_eliminated)
asm_fprintf (f, "\t%@ link register save eliminated.\n");
@@ -7479,8 +7482,9 @@ arm_output_epilogue (really_return)
int reg;
unsigned long saved_regs_mask;
unsigned long func_type;
- /* If we need this, then it will always be at least this much. */
- int floats_offset = 12;
+ /* Floats_offset is the offset from the "virtual" frame. In an APCS
+ frame that is $fp + 4 for a non-variadic function. */
+ int floats_offset = 0;
rtx operands[3];
int frame_size = get_frame_size ();
FILE * f = asm_out_file;
@@ -7517,6 +7521,9 @@ arm_output_epilogue (really_return)
saved_regs_mask = arm_compute_save_reg_mask ();
+ /* XXX We should adjust floats_offset for any anonymous args, and then
+ re-adjust vfp_offset below to compensate. */
+
/* Compute how far away the floats will be. */
for (reg = 0; reg <= LAST_ARM_REGNUM; reg ++)
if (saved_regs_mask & (1 << reg))
@@ -7524,6 +7531,8 @@ arm_output_epilogue (really_return)
if (frame_pointer_needed)
{
+ int vfp_offset = 4;
+
if (arm_fpu_arch == FP_SOFT2)
{
for (reg = LAST_ARM_FP_REGNUM; reg >= FIRST_ARM_FP_REGNUM; reg--)
@@ -7531,7 +7540,7 @@ arm_output_epilogue (really_return)
{
floats_offset += 12;
asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n",
- reg, FP_REGNUM, floats_offset);
+ reg, FP_REGNUM, floats_offset - vfp_offset);
}
}
else
@@ -7548,7 +7557,7 @@ arm_output_epilogue (really_return)
if (start_reg - reg == 3)
{
asm_fprintf (f, "\tlfm\t%r, 4, [%r, #-%d]\n",
- reg, FP_REGNUM, floats_offset);
+ reg, FP_REGNUM, floats_offset - vfp_offset);
start_reg = reg - 1;
}
}
@@ -7557,7 +7566,7 @@ arm_output_epilogue (really_return)
if (reg != start_reg)
asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
reg + 1, start_reg - reg,
- FP_REGNUM, floats_offset);
+ FP_REGNUM, floats_offset - vfp_offset);
start_reg = reg - 1;
}
}
@@ -7566,7 +7575,7 @@ arm_output_epilogue (really_return)
if (reg != start_reg)
asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n",
reg + 1, start_reg - reg,
- FP_REGNUM, floats_offset);
+ FP_REGNUM, floats_offset - vfp_offset);
}
/* saved_regs_mask should contain the IP, which at the time of stack
@@ -7660,7 +7669,7 @@ arm_output_epilogue (really_return)
to load use the LDR instruction - it is faster. */
if (saved_regs_mask == (1 << LR_REGNUM))
{
- /* The excpetion handler ignores the LR, so we do
+ /* The exception handler ignores the LR, so we do
not really need to load it off the stack. */
if (eh_ofs)
asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
@@ -7686,7 +7695,10 @@ arm_output_epilogue (really_return)
REGNO (eh_ofs));
#endif
- if (! really_return)
+ if (! really_return
+ || (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
+ && current_function_pretend_args_size == 0
+ && saved_regs_mask & (1 << PC_REGNUM)))
return "";
/* Generate the return instruction. */
@@ -7754,7 +7766,6 @@ arm_output_function_epilogue (file, frame_size)
abort ();
/* Reset the ARM-specific per-function variables. */
- current_function_anonymous_args = 0;
after_arm_reorg = 0;
}
}
@@ -8068,7 +8079,7 @@ arm_compute_initial_elimination_offset (from, to)
/* FIXME: Not sure about this. Maybe we should always return 0 ? */
return (frame_pointer_needed
&& current_function_needs_context
- && ! current_function_anonymous_args) ? 4 : 0;
+ && ! cfun->machine->uses_anonymous_args) ? 4 : 0;
case STACK_POINTER_REGNUM:
/* If nothing has been pushed on the stack at all
@@ -8209,7 +8220,7 @@ arm_expand_prologue ()
else
{
/* Store the args on the stack. */
- if (current_function_anonymous_args)
+ if (cfun->machine->uses_anonymous_args)
insn = emit_multi_reg_push
((0xf0 >> (args_to_push / 4)) & 0xf);
else
@@ -8245,7 +8256,7 @@ arm_expand_prologue ()
if (args_to_push)
{
/* Push the argument registers, or reserve space for them. */
- if (current_function_anonymous_args)
+ if (cfun->machine->uses_anonymous_args)
insn = emit_multi_reg_push
((0xf0 >> (args_to_push / 4)) & 0xf);
else
@@ -8255,6 +8266,19 @@ arm_expand_prologue ()
RTX_FRAME_RELATED_P (insn) = 1;
}
+ /* If this is an interrupt service routine, and the link register is
+ going to be pushed, subtracting four now will mean that the
+ function return can be done with a single instruction. */
+ if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
+ && (live_regs_mask & (1 << LR_REGNUM)) != 0)
+ {
+ emit_insn (gen_rtx_SET (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ gen_rtx_PLUS (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ GEN_INT (-4))));
+ }
+
if (live_regs_mask)
{
insn = emit_multi_reg_push (live_regs_mask);
@@ -8609,7 +8633,9 @@ arm_assemble_integer (x, size, aligned_p)
if (NEED_GOT_RELOC && flag_pic && making_const_table &&
(GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
{
- if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ if (GET_CODE (x) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (x)
+ || ENCODED_SHORT_CALL_ATTR_P (XSTR (x, 0))))
fputs ("(GOTOFF)", asm_out_file);
else if (GET_CODE (x) == LABEL_REF)
fputs ("(GOTOFF)", asm_out_file);
@@ -9139,20 +9165,8 @@ arm_hard_regno_mode_ok (regno, mode)
return (NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
if (regno <= LAST_ARM_REGNUM)
- /* We allow an SImode or smaller value to be stored in any
- general purpose register. This does not mean, for example
- that GCC will choose to store a variable in the stack pointer
- since it is a fixed register. But it is important to allow
- access to these special registers, so that they can be
- referenced from C code via the asm assembler alias, eg:
-
- register char * stack_ptr asm ("sp");
-
- For any mode requiring more than one register to hold the
- value we restrict the choice so that r13, r14, and r15
- cannot be part of the register set. */
- return (NUM_REGS (mode) <= 1)
- || (regno < (SP_REGNUM - (unsigned) NUM_REGS (mode)));
+ /* We allow any value to be stored in the general regisetrs. */
+ return 1;
if ( regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM)
@@ -10187,7 +10201,6 @@ thumb_expand_prologue ()
if (regno > LAST_LO_REGNUM) /* Very unlikely */
{
rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
- rtx insn;
/* Choose an arbitary, non-argument low register. */
reg = gen_rtx (REG, SImode, LAST_LO_REGNUM);
@@ -10312,7 +10325,7 @@ thumb_output_function_prologue (f, size)
if (current_function_pretend_args_size)
{
- if (current_function_anonymous_args)
+ if (cfun->machine->uses_anonymous_args)
{
int num_pushes;
diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h
index 46f938e..5e8b5d9 100644
--- a/contrib/gcc/config/arm/arm.h
+++ b/contrib/gcc/config/arm/arm.h
@@ -81,8 +81,6 @@ extern struct rtx_def * pool_vector_label;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
extern int return_used_this_function;
-/* Nonzero if the prologue must setup `fp'. */
-extern int current_function_anonymous_args;
/* Just in case configure has failed to define anything. */
#ifndef TARGET_CPU_DEFAULT
@@ -855,7 +853,7 @@ extern const char * structure_size_string;
regno <= LAST_ARM_FP_REGNUM; ++regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
} \
- if (flag_pic) \
+ if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \
{ \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
@@ -1029,6 +1027,13 @@ extern const char * structure_size_string;
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26 \
}
+
+/* Interrupt functions can only use registers that have already been
+ saved by the prologue, even if they would normally be
+ call-clobbered. */
+#define HARD_REGNO_RENAME_OK(SRC, DST) \
+ (! IS_INTERRUPT (cfun->machine->func_type) || \
+ regs_ever_live[DST])
/* Register and constant classes. */
@@ -1454,6 +1459,8 @@ typedef struct machine_function
int lr_save_eliminated;
/* Records the type of the current function. */
unsigned long func_type;
+ /* Record if the function has a variable argument list. */
+ int uses_anonymous_args;
}
machine_function;
@@ -1536,8 +1543,7 @@ typedef struct
that way. */
#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PRETEND_SIZE, NO_RTL) \
{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
+ cfun->machine->uses_anonymous_args = 1; \
if ((CUM).nregs < NUM_ARG_REGS) \
(PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
}
@@ -1844,7 +1850,8 @@ typedef struct
#define THUMB_LEGITIMATE_CONSTANT_P(X) \
( GET_CODE (X) == CONST_INT \
|| GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
+ || CONSTANT_ADDRESS_P (X) \
+ || flag_pic)
#define LEGITIMATE_CONSTANT_P(X) \
(TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) : THUMB_LEGITIMATE_CONSTANT_P (X))
@@ -1892,9 +1899,9 @@ typedef struct
or known to be defined in this file then encode a short call flag.
This macro is used inside the ENCODE_SECTION macro. */
#define ARM_ENCODE_CALL_TYPE(decl) \
- if (TREE_CODE (decl) == FUNCTION_DECL) \
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') \
{ \
- if (DECL_WEAK (decl)) \
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) \
arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
else if (! TREE_PUBLIC (decl)) \
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md
index 3646fe5..91bbf61 100644
--- a/contrib/gcc/config/arm/arm.md
+++ b/contrib/gcc/config/arm/arm.md
@@ -135,8 +135,12 @@
(define_attr "neg_pool_range" "" (const_int 0))
; An assembler sequence may clobber the condition codes without us knowing.
+; If such an insn references the pool, then we have no way of knowing how,
+; so use the most conservative value for pool_range.
(define_asm_attributes
- [(set_attr "conds" "clob")])
+ [(set_attr "conds" "clob")
+ (set_attr "length" "4")
+ (set_attr "pool_range" "250")])
; TYPE attribute is used to detect floating point instructions which, if
; running on a co-processor can run in parallel with other, basic instructions
@@ -3959,7 +3963,7 @@
[(set_attr "length" "8")
(set_attr "type" "*,load,store2")
(set_attr "pool_range" "*,1020,*")
- (set_attr "neg_pool_range" "*,1012,*")]
+ (set_attr "neg_pool_range" "*,1008,*")]
)
;;; ??? This should have alternatives for constants.
@@ -4132,27 +4136,6 @@
}"
)
-(define_expand "movaddr"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operand:DI 1 "address_operand" ""))]
- "TARGET_ARM"
- ""
-)
-
-(define_insn "*movaddr_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operand:DI 1 "address_operand" "p"))]
- "TARGET_ARM
- && reload_completed
- && (GET_CODE (operands[1]) == LABEL_REF
- || (GET_CODE (operands[1]) == CONST
- && GET_CODE (XEXP (operands[1], 0)) == PLUS
- && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
- "adr%?\\t%0, %a1"
- [(set_attr "predicable" "yes")]
-)
-
;; When generating pic, we need to load the symbol offset into a register.
;; So that the optimizer does not confuse this with a normal symbol load
;; we use an unspec. The offset will be loaded from a constant pool entry,
@@ -5110,8 +5093,8 @@
(set_attr "predicable" "yes")
(set_attr "type"
"load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
- (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
- (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
+ (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
+ (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
)
;; Software floating point version. This is essentially the same as movdi.
@@ -5126,8 +5109,8 @@
"* return output_move_double (operands);"
[(set_attr "length" "8,8,8")
(set_attr "type" "*,load,store2")
- (set_attr "pool_range" "252")
- (set_attr "neg_pool_range" "244")]
+ (set_attr "pool_range" "1020")
+ (set_attr "neg_pool_range" "1008")]
)
;;; ??? This should have alternatives for constants.
@@ -5201,7 +5184,7 @@
(set_attr "predicable" "yes")
(set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
(set_attr "pool_range" "*,*,1024,*,*,*,*")
- (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
+ (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
)
@@ -6655,7 +6638,8 @@
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB
- && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
"bl\\t%a0"
[(set_attr "length" "4")
(set_attr "type" "call")]
@@ -6668,7 +6652,8 @@
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB
- && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
"bl\\t%a1"
[(set_attr "length" "4")
(set_attr "type" "call")]
@@ -8297,6 +8282,7 @@
"TARGET_ARM
&& !BYTES_BIG_ENDIAN
&& !TARGET_MMU_TRAPS
+ && !arm_arch4
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& (GET_CODE (operands[2]) != REG
@@ -8315,6 +8301,7 @@
"TARGET_ARM
&& !BYTES_BIG_ENDIAN
&& !TARGET_MMU_TRAPS
+ && !arm_arch4
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& (GET_CODE (operands[2]) != REG
@@ -8479,6 +8466,7 @@
"TARGET_ARM
&& !BYTES_BIG_ENDIAN
&& !TARGET_MMU_TRAPS
+ && !arm_arch4
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& REGNO (operands[3]) != FRAME_POINTER_REGNUM"
@@ -8499,6 +8487,7 @@
"TARGET_ARM
&& !BYTES_BIG_ENDIAN
&& !TARGET_MMU_TRAPS
+ && !arm_arch4
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& REGNO (operands[3]) != FRAME_POINTER_REGNUM"
@@ -8562,6 +8551,7 @@
"TARGET_ARM
&& !BYTES_BIG_ENDIAN
&& !TARGET_MMU_TRAPS
+ && !arm_arch4
&& REGNO (operands[0]) != REGNO(operands[1])
&& (GET_CODE (operands[2]) != REG
|| REGNO(operands[0]) != REGNO (operands[2]))"
@@ -9136,11 +9126,28 @@
;; Miscellaneous Thumb patterns
-(define_insn "tablejump"
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
+ (use (label_ref (match_operand 1 "" "")))])]
+ "TARGET_THUMB"
+ "
+ if (flag_pic)
+ {
+ /* Hopefully, CSE will eliminate this copy. */
+ rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
+ rtx reg2 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_addsi3 (reg2, operands[0], reg1));
+ operands[0] = reg2;
+ }
+ "
+)
+
+(define_insn "*thumb_tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_THUMB"
- "mov pc, %0"
+ "mov\\t%|pc, %0"
[(set_attr "length" "2")]
)
diff --git a/contrib/gcc/config/arm/coff.h b/contrib/gcc/config/arm/coff.h
index f53dace..c9f0d92 100644
--- a/contrib/gcc/config/arm/coff.h
+++ b/contrib/gcc/config/arm/coff.h
@@ -72,7 +72,9 @@ Boston, MA 02111-1307, USA. */
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used. */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+/* We put ARM jump tables in the text section, because it makes the code
+ more efficient, but for Thumb it's better to put them out of band. */
+#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
#undef READONLY_DATA_SECTION
#define READONLY_DATA_SECTION rdata_section
diff --git a/contrib/gcc/config/arm/elf.h b/contrib/gcc/config/arm/elf.h
index c27daca..1cab2c4 100644
--- a/contrib/gcc/config/arm/elf.h
+++ b/contrib/gcc/config/arm/elf.h
@@ -103,7 +103,9 @@ Boston, MA 02111-1307, USA. */
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used. */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+/* We put ARM jump tables in the text section, because it makes the code
+ more efficient, but for Thumb it's better to put them out of band. */
+#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
#ifndef LINK_SPEC
#define LINK_SPEC "%{mbig-endian:-EB} -X"
diff --git a/contrib/gcc/config/arm/linux-elf.h b/contrib/gcc/config/arm/linux-elf.h
index 74f7e7e..f1c86d2 100644
--- a/contrib/gcc/config/arm/linux-elf.h
+++ b/contrib/gcc/config/arm/linux-elf.h
@@ -1,5 +1,5 @@
/* Definitions for ARM running Linux-based GNU systems using ELF
- Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001
+ Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
@@ -42,6 +42,10 @@ Boston, MA 02111-1307, USA. */
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
/* Now we define the strings used to build the spec file. */
#define LIB_SPEC \
"%{shared: -lc} \
@@ -87,7 +91,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
-"-Dunix -Dlinux -D__ELF__ \
+"-Dunix -D__gnu_linux__ -Dlinux -D__ELF__ \
-Asystem=unix -Asystem=posix"
/* Allow #sccs in preprocessor. */
diff --git a/contrib/gcc/config/arm/netbsd.h b/contrib/gcc/config/arm/netbsd.h
index 74f32e8..2be49d8 100644
--- a/contrib/gcc/config/arm/netbsd.h
+++ b/contrib/gcc/config/arm/netbsd.h
@@ -1,4 +1,4 @@
-/* NetBSD/arm (RiscBSD) version.
+/* NetBSD/arm a.out version.
Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
@@ -77,15 +77,6 @@ Boston, MA 02111-1307, USA. */
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
#define HANDLE_SYSV_PRAGMA
/* We don't have any limit on the length as out debugger is GDB. */
diff --git a/contrib/gcc/config/arm/rtems-elf.h b/contrib/gcc/config/arm/rtems-elf.h
index 954f72b..312c96f 100644
--- a/contrib/gcc/config/arm/rtems-elf.h
+++ b/contrib/gcc/config/arm/rtems-elf.h
@@ -1,5 +1,5 @@
/* Definitions for RTEMS based ARM systems using ELF
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,15 +19,10 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Run-time Target Specification. */
-#undef TARGET_VERSION
+#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/ELF RTEMS)", stderr);
#define HAS_INIT_SECTION
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Darm -Darm_elf -Drtems -D__rtems__ -D__ELF__ \
- -Asystem(rtems) -Acpu(arm) -Amachine(arm)"
-
-/*#undef INVOKE_main*/
-
-
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__rtems__ -D__ELF__ -Asystem=rtems"
OpenPOWER on IntegriCloud