diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2014-09-09 21:35:03 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2014-09-09 21:38:05 +0200 |
commit | fe3ec0b2af8d02c1d5f198c119b80a335d89eb0f (patch) | |
tree | ba38555cad08c89745638d6b8becaff6cd83b390 /toolchain/gcc | |
parent | 3b9f9fc8e3468e0930fe1ab952cbae3894c256f0 (diff) |
add toolchain support for avr32
Diffstat (limited to 'toolchain/gcc')
-rw-r--r-- | toolchain/gcc/Makefile | 2 | ||||
-rw-r--r-- | toolchain/gcc/Makefile.inc | 8 | ||||
-rw-r--r-- | toolchain/gcc/patches/4.4.7/930-avr32_support.patch | 22706 | ||||
-rw-r--r-- | toolchain/gcc/patches/4.4.7/931-avr32_disable_shifted_data_opt.patch | 32 | ||||
-rw-r--r-- | toolchain/gcc/patches/4.4.7/933-avr32_bug_7435.patch | 32 | ||||
-rw-r--r-- | toolchain/gcc/patches/4.4.7/934-avr32_bug_9675.patch | 21 | ||||
-rw-r--r-- | toolchain/gcc/patches/4.4.7/cflags.patch | 257 |
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 |