summaryrefslogtreecommitdiff
path: root/toolchain/gcc
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2014-09-09 21:35:03 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2014-09-09 21:38:05 +0200
commitfe3ec0b2af8d02c1d5f198c119b80a335d89eb0f (patch)
treeba38555cad08c89745638d6b8becaff6cd83b390 /toolchain/gcc
parent3b9f9fc8e3468e0930fe1ab952cbae3894c256f0 (diff)
add toolchain support for avr32
Diffstat (limited to 'toolchain/gcc')
-rw-r--r--toolchain/gcc/Makefile2
-rw-r--r--toolchain/gcc/Makefile.inc8
-rw-r--r--toolchain/gcc/patches/4.4.7/930-avr32_support.patch22706
-rw-r--r--toolchain/gcc/patches/4.4.7/931-avr32_disable_shifted_data_opt.patch32
-rw-r--r--toolchain/gcc/patches/4.4.7/933-avr32_bug_7435.patch32
-rw-r--r--toolchain/gcc/patches/4.4.7/934-avr32_bug_9675.patch21
-rw-r--r--toolchain/gcc/patches/4.4.7/cflags.patch257
7 files changed, 23057 insertions, 1 deletions
diff --git a/toolchain/gcc/Makefile b/toolchain/gcc/Makefile
index 17ade4d04..68f64e2ff 100644
--- a/toolchain/gcc/Makefile
+++ b/toolchain/gcc/Makefile
@@ -44,7 +44,7 @@ else
GCC_CONFOPTS+= --disable-tls --disable-threads --disable-libatomic
endif
-ifneq ($(ADK_LINUX_AARCH64)$(ADK_LINUX_ALPHA)$(ADK_LINUX_ARC)$(ADK_LINUX_BFIN)$(ADK_LINUX_XTENSA)$(ADK_LINUX_M68K),y)
+ifneq ($(ADK_LINUX_AARCH64)$(ADK_LINUX_ALPHA)$(ADK_LINUX_ARC)$(ADK_LINUX_AVR32)$(ADK_LINUX_BFIN)$(ADK_LINUX_XTENSA)$(ADK_LINUX_M68K),y)
GCC_FINAL_CONFOPTS+= --enable-cxx-flags='$(TARGET_CXXFLAGS)'
endif
diff --git a/toolchain/gcc/Makefile.inc b/toolchain/gcc/Makefile.inc
index 5acfced94..7849939cf 100644
--- a/toolchain/gcc/Makefile.inc
+++ b/toolchain/gcc/Makefile.inc
@@ -33,3 +33,11 @@ PKG_RELEASE:= 1
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 19
endif
+ifeq ($(ADK_TOOLCHAIN_GCC_4_4_7),y)
+PKG_VERSION:= 4.4.7
+PKG_MD5SUM:= e2c60f5ef918be2db08df96c7d97d0c4
+PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
+PKG_RELEASE:= 1
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+LIBSTDCXXVER:= 19
+endif
diff --git a/toolchain/gcc/patches/4.4.7/930-avr32_support.patch b/toolchain/gcc/patches/4.4.7/930-avr32_support.patch
new file mode 100644
index 000000000..334d2cd13
--- /dev/null
+++ b/toolchain/gcc/patches/4.4.7/930-avr32_support.patch
@@ -0,0 +1,22706 @@
+--- a/gcc/builtins.c
++++ b/gcc/builtins.c
+@@ -11108,7 +11108,7 @@ validate_gimple_arglist (const_gimple ca
+
+ do
+ {
+- code = va_arg (ap, enum tree_code);
++ code = va_arg (ap, int);
+ switch (code)
+ {
+ case 0:
+--- a/gcc/calls.c
++++ b/gcc/calls.c
+@@ -3447,7 +3447,7 @@ emit_library_call_value_1 (int retval, r
+ for (; count < nargs; count++)
+ {
+ rtx val = va_arg (p, rtx);
+- enum machine_mode mode = va_arg (p, enum machine_mode);
++ enum machine_mode mode = va_arg (p, int);
+
+ /* We cannot convert the arg value to the mode the library wants here;
+ must do it earlier where we know the signedness of the arg. */
+--- /dev/null
++++ b/gcc/config/avr32/avr32.c
+@@ -0,0 +1,8060 @@
++/*
++ Target hooks and helper functions for AVR32.
++ Copyright 2003,2004,2005,2006,2007,2008,2009,2010 Atmel Corporation.
++
++ This file is part of GCC.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "tree.h"
++#include "obstack.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "output.h"
++#include "insn-attr.h"
++#include "flags.h"
++#include "reload.h"
++#include "function.h"
++#include "expr.h"
++#include "optabs.h"
++#include "toplev.h"
++#include "recog.h"
++#include "ggc.h"
++#include "except.h"
++#include "c-pragma.h"
++#include "integrate.h"
++#include "tm_p.h"
++#include "langhooks.h"
++#include "hooks.h"
++#include "df.h"
++
++#include "target.h"
++#include "target-def.h"
++
++#include <ctype.h>
++
++
++
++/* Global variables. */
++typedef struct minipool_node Mnode;
++typedef struct minipool_fixup Mfix;
++
++/* Obstack for minipool constant handling. */
++static struct obstack minipool_obstack;
++static char *minipool_startobj;
++static rtx minipool_vector_label;
++
++/* True if we are currently building a constant table. */
++int making_const_table;
++
++tree fndecl_attribute_args = NULL_TREE;
++
++
++/* Function prototypes. */
++static unsigned long avr32_isr_value (tree);
++static unsigned long avr32_compute_func_type (void);
++static tree avr32_handle_isr_attribute (tree *, tree, tree, int, bool *);
++static tree avr32_handle_acall_attribute (tree *, tree, tree, int, bool *);
++static tree avr32_handle_fndecl_attribute (tree * node, tree name, tree args,
++ int flags, bool * no_add_attrs);
++static void avr32_reorg (void);
++bool avr32_return_in_msb (tree type);
++bool avr32_vector_mode_supported (enum machine_mode mode);
++static void avr32_init_libfuncs (void);
++static void avr32_file_end (void);
++static void flashvault_decl_list_add (unsigned int vector_num, const char *name);
++
++
++
++static void
++avr32_add_gc_roots (void)
++{
++ gcc_obstack_init (&minipool_obstack);
++ minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
++}
++
++
++/* List of all known AVR32 parts */
++static const struct part_type_s avr32_part_types[] = {
++ /* name, part_type, architecture type, macro */
++ {"none", PART_TYPE_AVR32_NONE, ARCH_TYPE_AVR32_AP, "__AVR32__"},
++ {"ap7000", PART_TYPE_AVR32_AP7000, ARCH_TYPE_AVR32_AP, "__AVR32_AP7000__"},
++ {"ap7001", PART_TYPE_AVR32_AP7001, ARCH_TYPE_AVR32_AP, "__AVR32_AP7001__"},
++ {"ap7002", PART_TYPE_AVR32_AP7002, ARCH_TYPE_AVR32_AP, "__AVR32_AP7002__"},
++ {"ap7200", PART_TYPE_AVR32_AP7200, ARCH_TYPE_AVR32_AP, "__AVR32_AP7200__"},
++ {"uc3a0128", PART_TYPE_AVR32_UC3A0128, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A0128__"},
++ {"uc3a0256", PART_TYPE_AVR32_UC3A0256, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A0256__"},
++ {"uc3a0512", PART_TYPE_AVR32_UC3A0512, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A0512__"},
++ {"uc3a0512es", PART_TYPE_AVR32_UC3A0512ES, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3A0512ES__"},
++ {"uc3a1128", PART_TYPE_AVR32_UC3A1128, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A1128__"},
++ {"uc3a1256", PART_TYPE_AVR32_UC3A1256, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A1256__"},
++ {"uc3a1512", PART_TYPE_AVR32_UC3A1512, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A1512__"},
++ {"uc3a1512es", PART_TYPE_AVR32_UC3A1512ES, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3A1512ES__"},
++ {"uc3a3revd", PART_TYPE_AVR32_UC3A3REVD, ARCH_TYPE_AVR32_UCR2NOMUL, "__AVR32_UC3A3256S__"},
++ {"uc3a364", PART_TYPE_AVR32_UC3A364, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A364__"},
++ {"uc3a364s", PART_TYPE_AVR32_UC3A364S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A364S__"},
++ {"uc3a3128", PART_TYPE_AVR32_UC3A3128, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A3128__"},
++ {"uc3a3128s", PART_TYPE_AVR32_UC3A3128S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A3128S__"},
++ {"uc3a3256", PART_TYPE_AVR32_UC3A3256, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A3256__"},
++ {"uc3a3256s", PART_TYPE_AVR32_UC3A3256S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A3256S__"},
++ {"uc3a464", PART_TYPE_AVR32_UC3A464, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A464__"},
++ {"uc3a464s", PART_TYPE_AVR32_UC3A464S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A464S__"},
++ {"uc3a4128", PART_TYPE_AVR32_UC3A4128, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A4128__"},
++ {"uc3a4128s", PART_TYPE_AVR32_UC3A4128S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A4128S__"},
++ {"uc3a4256", PART_TYPE_AVR32_UC3A4256, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A4256__"},
++ {"uc3a4256s", PART_TYPE_AVR32_UC3A4256S, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3A4256S__"},
++ {"uc3b064", PART_TYPE_AVR32_UC3B064, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B064__"},
++ {"uc3b0128", PART_TYPE_AVR32_UC3B0128, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B0128__"},
++ {"uc3b0256", PART_TYPE_AVR32_UC3B0256, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B0256__"},
++ {"uc3b0256es", PART_TYPE_AVR32_UC3B0256ES, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B0256ES__"},
++ {"uc3b0512", PART_TYPE_AVR32_UC3B0512, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3B0512__"},
++ {"uc3b0512revc", PART_TYPE_AVR32_UC3B0512REVC, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3B0512REVC__"},
++ {"uc3b164", PART_TYPE_AVR32_UC3B164, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B164__"},
++ {"uc3b1128", PART_TYPE_AVR32_UC3B1128, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B1128__"},
++ {"uc3b1256", PART_TYPE_AVR32_UC3B1256, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B1256__"},
++ {"uc3b1256es", PART_TYPE_AVR32_UC3B1256ES, ARCH_TYPE_AVR32_UCR1, "__AVR32_UC3B1256ES__"},
++ {"uc3b1512", PART_TYPE_AVR32_UC3B1512, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3B1512__"},
++ {"uc3b1512revc", PART_TYPE_AVR32_UC3B1512REVC, ARCH_TYPE_AVR32_UCR2, "__AVR32_UC3B1512REVC__"},
++ {"uc64d3", PART_TYPE_AVR32_UC64D3, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC64D3__"},
++ {"uc128d3", PART_TYPE_AVR32_UC128D3, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC128D3__"},
++ {"uc64d4", PART_TYPE_AVR32_UC64D4, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC64D4__"},
++ {"uc128d4", PART_TYPE_AVR32_UC128D4, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC128D4__"},
++ {"uc3c0512crevc", PART_TYPE_AVR32_UC3C0512CREVC, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3C0512CREVC__"},
++ {"uc3c1512crevc", PART_TYPE_AVR32_UC3C1512CREVC, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3C1512CREVC__"},
++ {"uc3c2512crevc", PART_TYPE_AVR32_UC3C2512CREVC, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3C2512CREVC__"},
++ {"uc3l0256", PART_TYPE_AVR32_UC3L0256, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L0256__"},
++ {"uc3l0128", PART_TYPE_AVR32_UC3L0128, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L0128__"},
++ {"uc3l064", PART_TYPE_AVR32_UC3L064, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L064__"},
++ {"uc3l032", PART_TYPE_AVR32_UC3L032, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L032__"},
++ {"uc3l016", PART_TYPE_AVR32_UC3L016, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L016__"},
++ {"uc3l064revb", PART_TYPE_AVR32_UC3L064REVB, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC3L064REVB__"},
++ {"uc64l3u", PART_TYPE_AVR32_UC64L3U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC64L3U__"},
++ {"uc128l3u", PART_TYPE_AVR32_UC128L3U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC128L3U__"},
++ {"uc256l3u", PART_TYPE_AVR32_UC256L3U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC256L3U__"},
++ {"uc64l4u", PART_TYPE_AVR32_UC64L4U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC64L4U__"},
++ {"uc128l4u", PART_TYPE_AVR32_UC128L4U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC128L4U__"},
++ {"uc256l4u", PART_TYPE_AVR32_UC256L4U, ARCH_TYPE_AVR32_UCR3, "__AVR32_UC256L4U__"},
++ {"uc3c064c", PART_TYPE_AVR32_UC3C064C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C064C__"},
++ {"uc3c0128c", PART_TYPE_AVR32_UC3C0128C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C0128C__"},
++ {"uc3c0256c", PART_TYPE_AVR32_UC3C0256C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C0256C__"},
++ {"uc3c0512c", PART_TYPE_AVR32_UC3C0512C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C0512C__"},
++ {"uc3c164c", PART_TYPE_AVR32_UC3C164C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C164C__"},
++ {"uc3c1128c", PART_TYPE_AVR32_UC3C1128C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C1128C__"},
++ {"uc3c1256c", PART_TYPE_AVR32_UC3C1256C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C1256C__"},
++ {"uc3c1512c", PART_TYPE_AVR32_UC3C1512C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C1512C__"},
++ {"uc3c264c", PART_TYPE_AVR32_UC3C264C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C264C__"},
++ {"uc3c2128c", PART_TYPE_AVR32_UC3C2128C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C2128C__"},
++ {"uc3c2256c", PART_TYPE_AVR32_UC3C2256C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C2256C__"},
++ {"uc3c2512c", PART_TYPE_AVR32_UC3C2512C, ARCH_TYPE_AVR32_UCR3FP, "__AVR32_UC3C2512C__"},
++ {"mxt768e", PART_TYPE_AVR32_MXT768E, ARCH_TYPE_AVR32_UCR3, "__AVR32_MXT768E__"},
++ {NULL, 0, 0, NULL}
++};
++
++/* List of all known AVR32 architectures */
++static const struct arch_type_s avr32_arch_types[] = {
++ /* name, architecture type, microarchitecture type, feature flags, macro */
++ {"ap", ARCH_TYPE_AVR32_AP, UARCH_TYPE_AVR32B,
++ (FLAG_AVR32_HAS_DSP
++ | FLAG_AVR32_HAS_SIMD
++ | FLAG_AVR32_HAS_UNALIGNED_WORD
++ | FLAG_AVR32_HAS_BRANCH_PRED | FLAG_AVR32_HAS_RETURN_STACK
++ | FLAG_AVR32_HAS_CACHES),
++ "__AVR32_AP__"},
++ {"ucr1", ARCH_TYPE_AVR32_UCR1, UARCH_TYPE_AVR32A,
++ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW),
++ "__AVR32_UC__=1"},
++ {"ucr2", ARCH_TYPE_AVR32_UCR2, UARCH_TYPE_AVR32A,
++ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
++ | FLAG_AVR32_HAS_V2_INSNS),
++ "__AVR32_UC__=2"},
++ {"ucr2nomul", ARCH_TYPE_AVR32_UCR2NOMUL, UARCH_TYPE_AVR32A,
++ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
++ | FLAG_AVR32_HAS_V2_INSNS | FLAG_AVR32_HAS_NO_MUL_INSNS),
++ "__AVR32_UC__=2"},
++ {"ucr3", ARCH_TYPE_AVR32_UCR3, UARCH_TYPE_AVR32A,
++ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
++ | FLAG_AVR32_HAS_V2_INSNS),
++ "__AVR32_UC__=3"},
++ {"ucr3fp", ARCH_TYPE_AVR32_UCR3FP, UARCH_TYPE_AVR32A,
++ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW | FLAG_AVR32_HAS_FPU
++ | FLAG_AVR32_HAS_V2_INSNS),
++ "__AVR32_UC__=3"},
++ {NULL, 0, 0, 0, NULL}
++};
++
++/* Default arch name */
++const char *avr32_arch_name = "none";
++const char *avr32_part_name = "none";
++
++const struct part_type_s *avr32_part;
++const struct arch_type_s *avr32_arch;
++
++
++/* FIXME: needs to use GC. */
++struct flashvault_decl_list
++{
++ struct flashvault_decl_list *next;
++ unsigned int vector_num;
++ const char *name;
++};
++
++static struct flashvault_decl_list *flashvault_decl_list_head = NULL;
++
++
++/* Set default target_flags. */
++#undef TARGET_DEFAULT_TARGET_FLAGS
++#define TARGET_DEFAULT_TARGET_FLAGS \
++ (MASK_HAS_ASM_ADDR_PSEUDOS | MASK_MD_REORG_OPTIMIZATION | MASK_COND_EXEC_BEFORE_RELOAD)
++
++void
++avr32_optimization_options (int level, int size)
++{
++ if (AVR32_ALWAYS_PIC)
++ flag_pic = 1;
++
++ /* Enable section anchors if optimization is enabled. */
++ if (level > 0 || size)
++ flag_section_anchors = 2;
++}
++
++
++/* Override command line options */
++void
++avr32_override_options (void)
++{
++ const struct part_type_s *part;
++ const struct arch_type_s *arch;
++
++ /*Add backward compability*/
++ if (strcmp ("uc", avr32_arch_name)== 0)
++ {
++ fprintf (stderr, "Warning: Deprecated arch `%s' specified. "
++ "Please use '-march=ucr1' instead. "
++ "Converting to arch 'ucr1'\n",
++ avr32_arch_name);
++ avr32_arch_name="ucr1";
++ }
++
++ /* Check if arch type is set. */
++ for (arch = avr32_arch_types; arch->name; arch++)
++ {
++ if (strcmp (arch->name, avr32_arch_name) == 0)
++ break;
++ }
++ avr32_arch = arch;
++
++ if (!arch->name && strcmp("none", avr32_arch_name) != 0)
++ {
++ fprintf (stderr, "Unknown arch `%s' specified\n"
++ "Known arch names:\n"
++ "\tuc (deprecated)\n",
++ avr32_arch_name);
++ for (arch = avr32_arch_types; arch->name; arch++)
++ fprintf (stderr, "\t%s\n", arch->name);
++ avr32_arch = &avr32_arch_types[ARCH_TYPE_AVR32_AP];
++ }
++
++ /* Check if part type is set. */
++ for (part = avr32_part_types; part->name; part++)
++ if (strcmp (part->name, avr32_part_name) == 0)
++ break;
++
++ avr32_part = part;
++ if (!part->name)
++ {
++ fprintf (stderr, "Unknown part `%s' specified\nKnown part names:\n",
++ avr32_part_name);
++ for (part = avr32_part_types; part->name; part++)
++ {
++ if (strcmp("none", part->name) != 0)
++ fprintf (stderr, "\t%s\n", part->name);
++ }
++ /* Set default to NONE*/
++ avr32_part = &avr32_part_types[PART_TYPE_AVR32_NONE];
++ }
++
++ /* NB! option -march= overrides option -mpart
++ * if both are used at the same time */
++ if (!arch->name)
++ avr32_arch = &avr32_arch_types[avr32_part->arch_type];
++
++ /* If optimization level is two or greater, then align start of loops to a
++ word boundary since this will allow folding the first insn of the loop.
++ Do this only for targets supporting branch prediction. */
++ if (optimize >= 2 && TARGET_BRANCH_PRED)
++ align_loops = 2;
++
++
++ /* Enable fast-float library if unsafe math optimizations
++ are used. */
++ if (flag_unsafe_math_optimizations)
++ target_flags |= MASK_FAST_FLOAT;
++
++ /* Check if we should set avr32_imm_in_const_pool
++ based on if caches are present or not. */
++ if ( avr32_imm_in_const_pool == -1 )
++ {
++ if ( TARGET_CACHES )
++ avr32_imm_in_const_pool = 1;
++ else
++ avr32_imm_in_const_pool = 0;
++ }
++
++ if (TARGET_NO_PIC)
++ flag_pic = 0;
++ avr32_add_gc_roots ();
++}
++
++
++/*
++If defined, a function that outputs the assembler code for entry to a
++function. The prologue is responsible for setting up the stack frame,
++initializing the frame pointer register, saving registers that must be
++saved, and allocating size additional bytes of storage for the
++local variables. size is an integer. file is a stdio
++stream to which the assembler code should be output.
++
++The label for the beginning of the function need not be output by this
++macro. That has already been done when the macro is run.
++
++To determine which registers to save, the macro can refer to the array
++regs_ever_live: element r is nonzero if hard register
++r is used anywhere within the function. This implies the function
++prologue should save register r, provided it is not one of the
++call-used registers. (TARGET_ASM_FUNCTION_EPILOGUE must likewise use
++regs_ever_live.)
++
++On machines that have ``register windows'', the function entry code does
++not save on the stack the registers that are in the windows, even if
++they are supposed to be preserved by function calls; instead it takes
++appropriate steps to ``push'' the register stack, if any non-call-used
++registers are used in the function.
++
++On machines where functions may or may not have frame-pointers, the
++function entry code must vary accordingly; it must set up the frame
++pointer if one is wanted, and not otherwise. To determine whether a
++frame pointer is in wanted, the macro can refer to the variable
++frame_pointer_needed. The variable's value will be 1 at run
++time in a function that needs a frame pointer. (see Elimination).
++
++The function entry code is responsible for allocating any stack space
++required for the function. This stack space consists of the regions
++listed below. In most cases, these regions are allocated in the
++order listed, with the last listed region closest to the top of the
++stack (the lowest address if STACK_GROWS_DOWNWARD is defined, and
++the highest address if it is not defined). You can use a different order
++for a machine if doing so is more convenient or required for
++compatibility reasons. Except in cases where required by standard
++or by a debugger, there is no reason why the stack layout used by GCC
++need agree with that used by other compilers for a machine.
++*/
++
++#undef TARGET_ASM_FUNCTION_PROLOGUE
++#define TARGET_ASM_FUNCTION_PROLOGUE avr32_target_asm_function_prologue
++
++#undef TARGET_ASM_FILE_END
++#define TARGET_ASM_FILE_END avr32_file_end
++
++#undef TARGET_DEFAULT_SHORT_ENUMS
++#define TARGET_DEFAULT_SHORT_ENUMS hook_bool_void_false
++
++#undef TARGET_PROMOTE_FUNCTION_ARGS
++#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
++
++#undef TARGET_PROMOTE_FUNCTION_RETURN
++#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
++
++#undef TARGET_PROMOTE_PROTOTYPES
++#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
++
++#undef TARGET_MUST_PASS_IN_STACK
++#define TARGET_MUST_PASS_IN_STACK avr32_must_pass_in_stack
++
++#undef TARGET_PASS_BY_REFERENCE
++#define TARGET_PASS_BY_REFERENCE avr32_pass_by_reference
++
++#undef TARGET_STRICT_ARGUMENT_NAMING
++#define TARGET_STRICT_ARGUMENT_NAMING avr32_strict_argument_naming
++
++#undef TARGET_VECTOR_MODE_SUPPORTED_P
++#define TARGET_VECTOR_MODE_SUPPORTED_P avr32_vector_mode_supported
++
++#undef TARGET_RETURN_IN_MEMORY
++#define TARGET_RETURN_IN_MEMORY avr32_return_in_memory
++
++#undef TARGET_RETURN_IN_MSB
++#define TARGET_RETURN_IN_MSB avr32_return_in_msb
++
++#undef TARGET_ENCODE_SECTION_INFO
++#define TARGET_ENCODE_SECTION_INFO avr32_encode_section_info
++
++#undef TARGET_ARG_PARTIAL_BYTES
++#define TARGET_ARG_PARTIAL_BYTES avr32_arg_partial_bytes
++
++#undef TARGET_STRIP_NAME_ENCODING
++#define TARGET_STRIP_NAME_ENCODING avr32_strip_name_encoding
++
++#define streq(string1, string2) (strcmp (string1, string2) == 0)
++
++#undef TARGET_NARROW_VOLATILE_BITFIELD
++#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
++
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE avr32_attribute_table
++
++#undef TARGET_COMP_TYPE_ATTRIBUTES
++#define TARGET_COMP_TYPE_ATTRIBUTES avr32_comp_type_attributes
++
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS avr32_rtx_costs
++
++#undef TARGET_CANNOT_FORCE_CONST_MEM
++#define TARGET_CANNOT_FORCE_CONST_MEM avr32_cannot_force_const_mem
++
++#undef TARGET_ASM_INTEGER
++#define TARGET_ASM_INTEGER avr32_assemble_integer
++
++#undef TARGET_FUNCTION_VALUE
++#define TARGET_FUNCTION_VALUE avr32_function_value
++
++#undef TARGET_MIN_ANCHOR_OFFSET
++#define TARGET_MIN_ANCHOR_OFFSET (0)
++
++#undef TARGET_MAX_ANCHOR_OFFSET
++#define TARGET_MAX_ANCHOR_OFFSET ((1 << 15) - 1)
++#undef TARGET_SECONDARY_RELOAD
++#define TARGET_SECONDARY_RELOAD avr32_secondary_reload
++
++
++/*
++ * Defining the option, -mlist-devices to list the devices supported by gcc.
++ * This option should be used while printing target-help to list all the
++ * supported devices.
++ */
++#undef TARGET_HELP
++#define TARGET_HELP avr32_target_help
++
++void avr32_target_help ()
++{
++ if (avr32_list_supported_parts)
++ {
++ const struct part_type_s *list;
++ fprintf (stdout, "List of parts supported by avr32-gcc:\n");
++ for (list = avr32_part_types; list->name; list++)
++ {
++ if (strcmp("none", list->name) != 0)
++ fprintf (stdout, "%-20s%s\n", list->name, list->macro);
++ }
++ fprintf (stdout, "\n\n");
++ }
++}
++
++enum reg_class
++avr32_secondary_reload (bool in_p, rtx x, enum reg_class class,
++ enum machine_mode mode, secondary_reload_info *sri)
++{
++
++ if ( avr32_rmw_memory_operand (x, mode) )
++ {
++ if (!in_p)
++ sri->icode = CODE_FOR_reload_out_rmw_memory_operand;
++ else
++ sri->icode = CODE_FOR_reload_in_rmw_memory_operand;
++ }
++ return NO_REGS;
++
++}
++/*
++ * Switches to the appropriate section for output of constant pool
++ * entry x in mode. You can assume that x is some kind of constant in
++ * RTL. The argument mode is redundant except in the case of a
++ * const_int rtx. Select the section by calling readonly_data_ section
++ * or one of the alternatives for other sections. align is the
++ * constant alignment in bits.
++ *
++ * The default version of this function takes care of putting symbolic
++ * constants in flag_ pic mode in data_section and everything else in
++ * readonly_data_section.
++ */
++//#undef TARGET_ASM_SELECT_RTX_SECTION
++//#define TARGET_ASM_SELECT_RTX_SECTION avr32_select_rtx_section
++
++
++/*
++ * If non-null, this hook performs a target-specific pass over the
++ * instruction stream. The compiler will run it at all optimization
++ * levels, just before the point at which it normally does
++ * delayed-branch scheduling.
++ *
++ * The exact purpose of the hook varies from target to target. Some
++ * use it to do transformations that are necessary for correctness,
++ * such as laying out in-function constant pools or avoiding hardware
++ * hazards. Others use it as an opportunity to do some
++ * machine-dependent optimizations.
++ *
++ * You need not implement the hook if it has nothing to do. The
++ * default definition is null.
++ */
++#undef TARGET_MACHINE_DEPENDENT_REORG
++#define TARGET_MACHINE_DEPENDENT_REORG avr32_reorg
++
++/* Target hook for assembling integer objects.
++ Need to handle integer vectors */
++static bool
++avr32_assemble_integer (rtx x, unsigned int size, int aligned_p)
++{
++ if (avr32_vector_mode_supported (GET_MODE (x)))
++ {
++ int i, units;
++
++ if (GET_CODE (x) != CONST_VECTOR)
++ abort ();
++
++ units = CONST_VECTOR_NUNITS (x);
++
++ switch (GET_MODE (x))
++ {
++ case V2HImode:
++ size = 2;
++ break;
++ case V4QImode:
++ size = 1;
++ break;
++ default:
++ abort ();
++ }
++
++ for (i = 0; i < units; i++)
++ {
++ rtx elt;
++
++ elt = CONST_VECTOR_ELT (x, i);
++ assemble_integer (elt, size, i == 0 ? 32 : size * BITS_PER_UNIT, 1);
++ }
++
++ return true;
++ }
++
++ return default_assemble_integer (x, size, aligned_p);
++}
++
++
++/*
++ * This target hook describes the relative costs of RTL expressions.
++ *
++ * The cost may depend on the precise form of the expression, which is
++ * available for examination in x, and the rtx code of the expression
++ * in which it is contained, found in outer_code. code is the
++ * expression code--redundant, since it can be obtained with GET_CODE
++ * (x).
++ *
++ * In implementing this hook, you can use the construct COSTS_N_INSNS
++ * (n) to specify a cost equal to n fast instructions.
++ *
++ * On entry to the hook, *total contains a default estimate for the
++ * cost of the expression. The hook should modify this value as
++ * necessary. Traditionally, the default costs are COSTS_N_INSNS (5)
++ * for multiplications, COSTS_N_INSNS (7) for division and modulus
++ * operations, and COSTS_N_INSNS (1) for all other operations.
++ *
++ * When optimizing for code size, i.e. when optimize_size is non-zero,
++ * this target hook should be used to estimate the relative size cost
++ * of an expression, again relative to COSTS_N_INSNS.
++ *
++ * The hook returns true when all subexpressions of x have been
++ * processed, and false when rtx_cost should recurse.
++ */
++
++/* Worker routine for avr32_rtx_costs. */
++static inline int
++avr32_rtx_costs_1 (rtx x, enum rtx_code code ATTRIBUTE_UNUSED,
++ enum rtx_code outer ATTRIBUTE_UNUSED)
++{
++ enum machine_mode mode = GET_MODE (x);
++
++ switch (GET_CODE (x))
++ {
++ case MEM:
++ /* Using pre decrement / post increment memory operations on the
++ avr32_uc architecture means that two writebacks must be performed
++ and hence two cycles are needed. */
++ if (!optimize_size
++ && GET_MODE_SIZE (mode) <= 2 * UNITS_PER_WORD
++ && TARGET_ARCH_UC
++ && (GET_CODE (XEXP (x, 0)) == PRE_DEC
++ || GET_CODE (XEXP (x, 0)) == POST_INC))
++ return COSTS_N_INSNS (5);
++
++ /* Memory costs quite a lot for the first word, but subsequent words
++ load at the equivalent of a single insn each. */
++ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
++ return COSTS_N_INSNS (3 + (GET_MODE_SIZE (mode) / UNITS_PER_WORD));
++
++ return COSTS_N_INSNS (4);
++ case SYMBOL_REF:
++ case CONST:
++ /* These are valid for the pseudo insns: lda.w and call which operates
++ on direct addresses. We assume that the cost of a lda.w is the same
++ as the cost of a ld.w insn. */
++ return (outer == SET) ? COSTS_N_INSNS (4) : COSTS_N_INSNS (1);
++ case DIV:
++ case MOD:
++ case UDIV:
++ case UMOD:
++ return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
++
++ case ROTATE:
++ case ROTATERT:
++ if (mode == TImode)
++ return COSTS_N_INSNS (100);
++
++ if (mode == DImode)
++ return COSTS_N_INSNS (10);
++ return COSTS_N_INSNS (4);
++ case ASHIFT:
++ case LSHIFTRT:
++ case ASHIFTRT:
++ case NOT:
++ if (mode == TImode)
++ return COSTS_N_INSNS (10);
++
++ if (mode == DImode)
++ return COSTS_N_INSNS (4);
++ return COSTS_N_INSNS (1);
++ case PLUS:
++ case MINUS:
++ case NEG:
++ case COMPARE:
++ case ABS:
++ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
++ return COSTS_N_INSNS (100);
++
++ if (mode == TImode)
++ return COSTS_N_INSNS (50);
++
++ if (mode == DImode)
++ return COSTS_N_INSNS (2);
++ return COSTS_N_INSNS (1);
++
++ case MULT:
++ {
++ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
++ return COSTS_N_INSNS (300);
++
++ if (mode == TImode)
++ return COSTS_N_INSNS (16);
++
++ if (mode == DImode)
++ return COSTS_N_INSNS (4);
++
++ if (mode == HImode)
++ return COSTS_N_INSNS (2);
++
++ return COSTS_N_INSNS (3);
++ }
++ case IF_THEN_ELSE:
++ if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
++ return COSTS_N_INSNS (4);
++ return COSTS_N_INSNS (1);
++ case SIGN_EXTEND:
++ case ZERO_EXTEND:
++ /* Sign/Zero extensions of registers cost quite much since these
++ instrcutions only take one register operand which means that gcc
++ often must insert some move instrcutions */
++ if (mode == QImode || mode == HImode)
++ return (COSTS_N_INSNS (GET_CODE (XEXP (x, 0)) == MEM ? 0 : 1));
++ return COSTS_N_INSNS (4);
++ case UNSPEC:
++ /* divmod operations */
++ if (XINT (x, 1) == UNSPEC_UDIVMODSI4_INTERNAL
++ || XINT (x, 1) == UNSPEC_DIVMODSI4_INTERNAL)
++ {
++ return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
++ }
++ /* Fallthrough */
++ default:
++ return COSTS_N_INSNS (1);
++ }
++}
++
++
++static bool
++avr32_rtx_costs (rtx x, int code, int outer_code, int *total)
++{
++ *total = avr32_rtx_costs_1 (x, code, outer_code);
++ return true;
++}
++
++
++bool
++avr32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
++{
++ /* Do not want symbols in the constant pool when compiling pic or if using
++ address pseudo instructions. */
++ return ((flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS)
++ && avr32_find_symbol (x) != NULL_RTX);
++}
++
++
++/* Table of machine attributes. */
++const struct attribute_spec avr32_attribute_table[] = {
++ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++ /* Interrupt Service Routines have special prologue and epilogue
++ requirements. */
++ {"isr", 0, 1, false, false, false, avr32_handle_isr_attribute},
++ {"interrupt", 0, 1, false, false, false, avr32_handle_isr_attribute},
++ {"acall", 0, 1, false, true, true, avr32_handle_acall_attribute},
++ {"naked", 0, 0, true, false, false, avr32_handle_fndecl_attribute},
++ {"rmw_addressable", 0, 0, true, false, false, NULL},
++ {"flashvault", 0, 1, true, false, false, avr32_handle_fndecl_attribute},
++ {"flashvault_impl", 0, 1, true, false, false, avr32_handle_fndecl_attribute},
++ {NULL, 0, 0, false, false, false, NULL}
++};
++
++
++typedef struct
++{
++ const char *const arg;
++ const unsigned long return_value;
++}
++isr_attribute_arg;
++
++
++static const isr_attribute_arg isr_attribute_args[] = {
++ {"FULL", AVR32_FT_ISR_FULL},
++ {"full", AVR32_FT_ISR_FULL},
++ {"HALF", AVR32_FT_ISR_HALF},
++ {"half", AVR32_FT_ISR_HALF},
++ {"NONE", AVR32_FT_ISR_NONE},
++ {"none", AVR32_FT_ISR_NONE},
++ {"UNDEF", AVR32_FT_ISR_NONE},
++ {"undef", AVR32_FT_ISR_NONE},
++ {"SWI", AVR32_FT_ISR_NONE},
++ {"swi", AVR32_FT_ISR_NONE},
++ {NULL, AVR32_FT_ISR_NONE}
++};
++
++
++/* Returns the (interrupt) function type of the current
++ function, or AVR32_FT_UNKNOWN if the type cannot be determined. */
++static unsigned long
++avr32_isr_value (tree argument)
++{
++ const isr_attribute_arg *ptr;
++ const char *arg;
++
++ /* No argument - default to ISR_NONE. */
++ if (argument == NULL_TREE)
++ return AVR32_FT_ISR_NONE;
++
++ /* Get the value of the argument. */
++ if (TREE_VALUE (argument) == NULL_TREE
++ || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
++ return AVR32_FT_UNKNOWN;
++
++ arg = TREE_STRING_POINTER (TREE_VALUE (argument));
++
++ /* Check it against the list of known arguments. */
++ for (ptr = isr_attribute_args; ptr->arg != NULL; ptr++)
++ if (streq (arg, ptr->arg))
++ return ptr->return_value;
++
++ /* An unrecognized interrupt type. */
++ return AVR32_FT_UNKNOWN;
++}
++
++
++/*
++These hooks specify assembly directives for creating certain kinds
++of integer object. The TARGET_ASM_BYTE_OP directive creates a
++byte-sized object, the TARGET_ASM_ALIGNED_HI_OP one creates an
++aligned two-byte object, and so on. Any of the hooks may be
++NULL, indicating that no suitable directive is available.
++
++The compiler will print these strings at the start of a new line,
++followed immediately by the object's initial value. In most cases,
++the string should contain a tab, a pseudo-op, and then another tab.
++*/
++#undef TARGET_ASM_BYTE_OP
++#define TARGET_ASM_BYTE_OP "\t.byte\t"
++#undef TARGET_ASM_ALIGNED_HI_OP
++#define TARGET_ASM_ALIGNED_HI_OP "\t.align 1\n\t.short\t"
++#undef TARGET_ASM_ALIGNED_SI_OP
++#define TARGET_ASM_ALIGNED_SI_OP "\t.align 2\n\t.int\t"
++#undef TARGET_ASM_ALIGNED_DI_OP
++#define TARGET_ASM_ALIGNED_DI_OP NULL
++#undef TARGET_ASM_ALIGNED_TI_OP
++#define TARGET_ASM_ALIGNED_TI_OP NULL
++#undef TARGET_ASM_UNALIGNED_HI_OP
++#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
++#undef TARGET_ASM_UNALIGNED_SI_OP
++#define TARGET_ASM_UNALIGNED_SI_OP "\t.int\t"
++#undef TARGET_ASM_UNALIGNED_DI_OP
++#define TARGET_ASM_UNALIGNED_DI_OP NULL
++#undef TARGET_ASM_UNALIGNED_TI_OP
++#define TARGET_ASM_UNALIGNED_TI_OP NULL
++
++#undef TARGET_ASM_OUTPUT_MI_THUNK
++#define TARGET_ASM_OUTPUT_MI_THUNK avr32_output_mi_thunk
++
++#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
++#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
++
++
++static void
++avr32_output_mi_thunk (FILE * file,
++ tree thunk ATTRIBUTE_UNUSED,
++ HOST_WIDE_INT delta,
++ HOST_WIDE_INT vcall_offset, tree function)
++ {
++ int mi_delta = delta;
++ int this_regno =
++ (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ?
++ INTERNAL_REGNUM (11) : INTERNAL_REGNUM (12));
++
++
++ if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21")
++ || vcall_offset)
++ {
++ fputs ("\tpushm\tlr\n", file);
++ }
++
++
++ if (mi_delta != 0)
++ {
++ if (avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21"))
++ {
++ fprintf (file, "\tsub\t%s, %d\n", reg_names[this_regno], -mi_delta);
++ }
++ else
++ {
++ /* Immediate is larger than k21 we must make us a temp register by
++ pushing a register to the stack. */
++ fprintf (file, "\tmov\tlr, lo(%d)\n", mi_delta);
++ fprintf (file, "\torh\tlr, hi(%d)\n", mi_delta);
++ fprintf (file, "\tadd\t%s, lr\n", reg_names[th