aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c84
1 files changed, 67 insertions, 17 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c66b51e..fc11cb1 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1,6 +1,6 @@
/* Output routines for GCC for ARM.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -460,6 +460,7 @@ static int thumb_call_reg_needed;
#define FL_FOR_ARCH6Z FL_FOR_ARCH6
#define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
#define FL_FOR_ARCH6T2 (FL_FOR_ARCH6 | FL_THUMB2)
+#define FL_FOR_ARCH6M (FL_FOR_ARCH6 & ~FL_NOTM)
#define FL_FOR_ARCH7 (FL_FOR_ARCH6T2 &~ FL_NOTM)
#define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM)
#define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV)
@@ -632,6 +633,7 @@ static const struct processors all_architectures[] =
{"armv6z", arm1176jzs, "6Z", FL_CO_PROC | FL_FOR_ARCH6Z, NULL},
{"armv6zk", arm1176jzs, "6ZK", FL_CO_PROC | FL_FOR_ARCH6ZK, NULL},
{"armv6t2", arm1156t2s, "6T2", FL_CO_PROC | FL_FOR_ARCH6T2, NULL},
+ {"armv6-m", cortexm1, "6M", FL_FOR_ARCH6M, NULL},
{"armv7", cortexa8, "7", FL_CO_PROC | FL_FOR_ARCH7, NULL},
{"armv7-a", cortexa8, "7A", FL_CO_PROC | FL_FOR_ARCH7A, NULL},
{"armv7-r", cortexr4, "7R", FL_CO_PROC | FL_FOR_ARCH7R, NULL},
@@ -17639,12 +17641,23 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
? 1 : 0);
if (mi_delta < 0)
mi_delta = - mi_delta;
- /* When generating 16-bit thumb code, thunks are entered in arm mode. */
+
if (TARGET_THUMB1)
{
int labelno = thunk_label++;
ASM_GENERATE_INTERNAL_LABEL (label, "LTHUMBFUNC", labelno);
- fputs ("\tldr\tr12, ", file);
+ /* Thunks are entered in arm mode when avaiable. */
+ if (TARGET_THUMB1_ONLY)
+ {
+ /* push r3 so we can use it as a temporary. */
+ /* TODO: Omit this save if r3 is not used. */
+ fputs ("\tpush {r3}\n", file);
+ fputs ("\tldr\tr3, ", file);
+ }
+ else
+ {
+ fputs ("\tldr\tr12, ", file);
+ }
assemble_name (file, label);
fputc ('\n', file);
if (flag_pic)
@@ -17658,29 +17671,63 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
Note that we have "+ 1" because some versions of GNU ld
don't set the low bit of the result for R_ARM_REL32
- relocations against thumb function symbols. */
+ relocations against thumb function symbols.
+ On ARMv6M this is +4, not +8. */
ASM_GENERATE_INTERNAL_LABEL (labelpc, "LTHUNKPC", labelno);
assemble_name (file, labelpc);
fputs (":\n", file);
- fputs ("\tadd\tr12, pc, r12\n", file);
+ if (TARGET_THUMB1_ONLY)
+ {
+ /* This is 2 insns after the start of the thunk, so we know it
+ is 4-byte aligned. */
+ fputs ("\tadd\tr3, pc, r3\n", file);
+ fputs ("\tmov r12, r3\n", file);
+ }
+ else
+ fputs ("\tadd\tr12, pc, r12\n", file);
}
+ else if (TARGET_THUMB1_ONLY)
+ fputs ("\tmov r12, r3\n", file);
}
- /* TODO: Use movw/movt for large constants when available. */
- while (mi_delta != 0)
+ if (TARGET_THUMB1_ONLY)
{
- if ((mi_delta & (3 << shift)) == 0)
- shift += 2;
- else
- {
- asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
- mi_op, this_regno, this_regno,
- mi_delta & (0xff << shift));
- mi_delta &= ~(0xff << shift);
- shift += 8;
- }
+ if (mi_delta > 255)
+ {
+ fputs ("\tldr\tr3, ", file);
+ assemble_name (file, label);
+ fputs ("+4\n", file);
+ asm_fprintf (file, "\t%s\t%r, %r, r3\n",
+ mi_op, this_regno, this_regno);
+ }
+ else if (mi_delta != 0)
+ {
+ asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
+ mi_op, this_regno, this_regno,
+ mi_delta);
+ }
+ }
+ else
+ {
+ /* TODO: Use movw/movt for large constants when available. */
+ while (mi_delta != 0)
+ {
+ if ((mi_delta & (3 << shift)) == 0)
+ shift += 2;
+ else
+ {
+ asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
+ mi_op, this_regno, this_regno,
+ mi_delta & (0xff << shift));
+ mi_delta &= ~(0xff << shift);
+ shift += 8;
+ }
+ }
}
if (TARGET_THUMB1)
{
+ if (TARGET_THUMB1_ONLY)
+ fputs ("\tpop\t{r3}\n", file);
+
fprintf (file, "\tbx\tr12\n");
ASM_OUTPUT_ALIGN (file, 2);
assemble_name (file, label);
@@ -17699,6 +17746,9 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
else
/* Output ".word .LTHUNKn". */
assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
+
+ if (TARGET_THUMB1_ONLY && mi_delta > 255)
+ assemble_integer (GEN_INT(mi_delta), 4, BITS_PER_WORD, 1);
}
else
{