diff -Nur gcc-4.4.6.orig/gcc/builtins.c gcc-4.4.6/gcc/builtins.c --- gcc-4.4.6.orig/gcc/builtins.c 2010-12-07 19:56:56.000000000 +0100 +++ gcc-4.4.6/gcc/builtins.c 2011-10-22 19:23:08.512581300 +0200 @@ -11108,7 +11108,7 @@ do { - code = va_arg (ap, enum tree_code); + code = va_arg (ap, int); switch (code) { case 0: diff -Nur gcc-4.4.6.orig/gcc/calls.c gcc-4.4.6/gcc/calls.c --- gcc-4.4.6.orig/gcc/calls.c 2010-09-24 17:07:36.000000000 +0200 +++ gcc-4.4.6/gcc/calls.c 2011-10-22 19:23:08.512581300 +0200 @@ -3447,7 +3447,7 @@ 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. */ diff -Nur gcc-4.4.6.orig/gcc/config/avr32/avr32-elf.h gcc-4.4.6/gcc/config/avr32/avr32-elf.h --- gcc-4.4.6.orig/gcc/config/avr32/avr32-elf.h 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.4.6/gcc/config/avr32/avr32-elf.h 2011-10-22 19:23:08.516581300 +0200 @@ -0,0 +1,91 @@ +/* + Elf specific definitions. + Copyright 2003,2004,2005,2006,2007,2008,2009 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. */ + + +/***************************************************************************** + * Controlling the Compiler Driver, 'gcc' + *****************************************************************************/ + +/* Run-time Target Specification. */ +#undef TARGET_VERSION +#define TARGET_VERSION fputs (" (AVR32 GNU with ELF)", stderr); + +/* +Another C string constant used much like LINK_SPEC. The +difference between the two is that STARTFILE_SPEC is used at +the very beginning of the command given to the linker. + +If this macro is not defined, a default is provided that loads the +standard C startup file from the usual place. See gcc.c. +*/ +#if 0 +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0%O%s crti%O%s crtbegin%O%s" +#endif +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{mflashvault: crtfv.o%s} %{!mflashvault: crt0.o%s} \ + crti.o%s crtbegin.o%s" + +#undef LINK_SPEC +#define LINK_SPEC "%{muse-oscall:--defsym __do_not_use_oscall_coproc__=0} %{mrelax|O*:%{mno-relax|O0|O1: ;:--relax}} %{mpart=uc3a3revd:-mavr32elf_uc3a3256s;:%{mpart=*:-mavr32elf_%*}} %{mcpu=*:-mavr32elf_%*}" + + +/* +Another C string constant used much like LINK_SPEC. The +difference between the two is that ENDFILE_SPEC is used at +the very end of the command given to the linker. + +Do not define this macro if it does not need to do anything. +*/ +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend%O%s crtn%O%s" + + +/* Target CPU builtins. */ +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__avr32__"); \ + builtin_define ("__AVR32__"); \ + builtin_define ("__AVR32_ELF__"); \ + builtin_define (avr32_part->macro); \ + builtin_define (avr32_arch->macro); \ + if (avr32_arch->uarch_type == UARCH_TYPE_AVR32A) \ + builtin_define ("__AVR32_AVR32A__"); \ + else \ + builtin_define ("__AVR32_AVR32B__"); \ + if (TARGET_UNALIGNED_WORD) \ + builtin_define ("__AVR32_HAS_UNALIGNED_WORD__"); \ + if (TARGET_SIMD) \ + builtin_define ("__AVR32_HAS_SIMD__"); \ + if (TARGET_DSP) \ + builtin_define ("__AVR32_HAS_DSP__"); \ + if (TARGET_RMW) \ + builtin_define ("__AVR32_HAS_RMW__"); \ + if (TARGET_BRANCH_PRED) \ + builtin_define ("__AVR32_HAS_BRANCH_PRED__"); \ + if (TARGET_FAST_FLOAT) \ + builtin_define ("__AVR32_FAST_FLOAT__"); \ + if (TARGET_FLASHVAULT) \ + builtin_define ("__AVR32_FLASHVAULT__"); \ + if (TARGET_NO_MUL_INSNS) \ + builtin_define ("__AVR32_NO_MUL__"); \ + } \ + while (0) diff -Nur gcc-4.4.6.orig/gcc/config/avr32/avr32-modes.def gcc-4.4.6/gcc/config/avr32/avr32-modes.def --- gcc-4.4.6.orig/gcc/config/avr32/avr32-modes.def 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.4.6/gcc/config/avr32/avr32-modes.def 2011-10-22 19:23:08.524581303 +0200 @@ -0,0 +1 @@ +VECTOR_MODES (INT, 4); /* V4QI V2HI */ diff -Nur gcc-4.4.6.orig/gcc/config/avr32/avr32-protos.h gcc-4.4.6/gcc/config/avr32/avr32-protos.h --- gcc-4.4.6.orig/gcc/config/avr32/avr32-protos.h 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.4.6/gcc/config/avr32/avr32-protos.h 2011-10-22 19:23:08.524581303 +0200 @@ -0,0 +1,196 @@ +/* + Prototypes for exported functions defined in avr32.c + Copyright 2003,2004,2005,2006,2007,2008,2009 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. */ + + +#ifndef AVR32_PROTOS_H +#define AVR32_PROTOS_H + +extern const int swap_reg[]; + +extern int avr32_valid_macmac_bypass (rtx, rtx); +extern int avr32_valid_mulmac_bypass (rtx, rtx); + +extern int avr32_decode_lcomm_symbol_offset (rtx, int *); +extern void avr32_encode_lcomm_symbol_offset (tree, char *, int); + +extern const char *avr32_strip_name_encoding (const char *); + +extern rtx avr32_get_note_reg_equiv (rtx insn); + +extern int avr32_use_return_insn (int iscond); + +extern void avr32_make_reglist16 (int reglist16_vect, char *reglist16_string); + +extern void avr32_make_reglist8 (int reglist8_vect, char *reglist8_string); +extern void avr32_make_fp_reglist_w (int reglist_mask, char *reglist_string); +extern void avr32_make_fp_reglist_d (int reglist_mask, char *reglist_string); + +extern void avr32_output_return_instruction (int single_ret_inst, + int iscond, rtx cond, + rtx r12_imm); +extern void avr32_expand_prologue (void); +extern void avr32_set_return_address (rtx source, rtx scratch); + +extern int avr32_hard_regno_mode_ok (int regno, enum machine_mode mode); +extern int avr32_extra_constraint_s (rtx value, const int strict); +extern int avr32_eh_return_data_regno (const int n); +extern int avr32_initial_elimination_offset (const int from, const int to); +extern rtx avr32_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, + tree type, int named); +extern void avr32_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, + rtx libname, tree fndecl); +extern void avr32_function_arg_advance (CUMULATIVE_ARGS * cum, + enum machine_mode mode, + tree type, int named); +#ifdef ARGS_SIZE_RTX +/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */ +extern enum direction avr32_function_arg_padding (enum machine_mode mode, + tree type); +#endif /* ARGS_SIZE_RTX */ +extern rtx avr32_function_value (tree valtype, tree func, bool outgoing); +extern rtx avr32_libcall_value (enum machine_mode mode); +extern int avr32_sched_use_dfa_pipeline_interface (void); +extern bool avr32_return_in_memory (tree type, tree fntype); +extern void avr32_regs_to_save (char *operand); +extern void avr32_target_asm_function_prologue (FILE * file, + HOST_WIDE_INT size); +extern void avr32_target_asm_function_epilogue (FILE * file, + HOST_WIDE_INT size); +extern void avr32_trampoline_template (FILE * file); +extern void avr32_initialize_trampoline (rtx addr, rtx fnaddr, + rtx static_chain); +extern int avr32_legitimate_address (enum machine_mode mode, rtx x, + int strict); +extern int avr32_legitimate_constant_p (rtx x); + +extern int avr32_legitimate_pic_operand_p (rtx x); + +extern rtx avr32_find_symbol (rtx x); +extern void avr32_select_section (rtx exp, int reloc, int align); +extern void avr32_encode_section_info (tree decl, rtx rtl, int first); +extern void avr32_asm_file_end (FILE * stream); +extern void avr32_asm_output_ascii (FILE * stream, char *ptr, int len); +extern void avr32_asm_output_common (FILE * stream, const char *name, + int size, int rounded); +extern void avr32_asm_output_label (FILE * stream, const char *name); +extern void avr32_asm_declare_object_name (FILE * stream, char *name, + tree decl); +extern void avr32_asm_globalize_label (FILE * stream, const char *name); +extern void avr32_asm_weaken_label (FILE * stream, const char *name); +extern void avr32_asm_output_external (FILE * stream, tree decl, + const char *name); +extern void avr32_asm_output_external_libcall (FILE * stream, rtx symref); +extern void avr32_asm_output_labelref (FILE * stream, const char *name); +extern void avr32_notice_update_cc (rtx exp, rtx insn); +extern void avr32_print_operand (FILE * stream, rtx x, int code); +extern void avr32_print_operand_address (FILE * stream, rtx x); + +extern int avr32_symbol (rtx x); + +extern void avr32_select_rtx_section (enum machine_mode mode, rtx x, + unsigned HOST_WIDE_INT align); + +extern int avr32_load_multiple_operation (rtx op, enum machine_mode mode); +extern int avr32_store_multiple_operation (rtx op, enum machine_mode mode); + +extern int avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c, + const char *str); + +extern bool avr32_cannot_force_const_mem (rtx x); + +extern void avr32_init_builtins (void); + +extern rtx avr32_expand_builtin (tree exp, rtx target, rtx subtarget, + enum machine_mode mode, int ignore); + +extern bool avr32_must_pass_in_stack (enum machine_mode mode, tree type); + +extern bool avr32_strict_argument_naming (CUMULATIVE_ARGS * ca); + +extern bool avr32_pass_by_reference (CUMULATIVE_ARGS * cum, + enum machine_mode mode, + tree type, bool named); + +extern rtx avr32_gen_load_multiple (rtx * regs, int count, rtx from, + int write_back, int in_struct_p, + int scalar_p); +extern rtx avr32_gen_store_multiple (rtx * regs, int count, rtx to, + int in_struct_p, int scalar_p); +extern int avr32_gen_movmemsi (rtx * operands); + +extern int avr32_rnd_operands (rtx add, rtx shift); +extern int avr32_adjust_insn_length (rtx insn, int length); + +extern int symbol_mentioned_p (rtx x); +extern int label_mentioned_p (rtx x); +extern rtx legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg); +extern int avr32_address_register_rtx_p (rtx x, int strict_p); +extern int avr32_legitimate_index_p (enum machine_mode mode, rtx index, + int strict_p); + +extern int avr32_const_double_immediate (rtx value); +extern void avr32_init_expanders (void); +extern rtx avr32_return_addr (int count, rtx frame); +extern bool avr32_got_mentioned_p (rtx addr); + +extern void avr32_final_prescan_insn (rtx insn, rtx * opvec, int noperands); + +extern int avr32_expand_movcc (enum machine_mode mode, rtx operands[]); +extern int avr32_expand_addcc (enum machine_mode mode, rtx operands[]); +#ifdef RTX_CODE +extern int avr32_expand_scc (RTX_CODE cond, rtx * operands); +#endif + +extern int avr32_store_bypass (rtx insn_out, rtx insn_in); +extern int avr32_mul_waw_bypass (rtx insn_out, rtx insn_in); +extern int avr32_valid_load_double_bypass (rtx insn_out, rtx insn_in); +extern int avr32_valid_load_quad_bypass (rtx insn_out, rtx insn_in); +extern rtx avr32_output_cmp (rtx cond, enum machine_mode mode, + rtx op0, rtx op1); + +rtx get_next_insn_cond (rtx cur_insn); +int set_next_insn_cond (rtx cur_insn, rtx cond); +rtx next_insn_emits_cmp (rtx cur_insn); +void avr32_override_options (void); +void avr32_load_pic_register (void); +#ifdef GCC_BASIC_BLOCK_H +rtx avr32_ifcvt_modify_insn (ce_if_block_t *ce_info, rtx pattern, rtx insn, + int *num_true_changes); +rtx avr32_ifcvt_modify_test (ce_if_block_t *ce_info, rtx test ); +void avr32_ifcvt_modify_cancel ( ce_if_block_t *ce_info, int *num_true_changes); +#endif +void avr32_optimization_options (int level, int size); +int avr32_const_ok_for_move (HOST_WIDE_INT c); + +void avr32_split_const_expr (enum machine_mode mode, + enum machine_mode new_mode, + rtx expr, + rtx *split_expr); +void avr32_get_intval (enum machine_mode mode, + rtx const_expr, + HOST_WIDE_INT *val); + +int avr32_cond_imm_clobber_splittable (rtx insn, + rtx operands[]); + +bool avr32_flashvault_call(tree decl); +extern void avr32_emit_swdivsf (rtx, rtx, rtx); + +#endif /* AVR32_PROTOS_H */ diff -Nur gcc-4.4.6.orig/gcc/config/avr32/avr32.c gcc-4.4.6/gcc/config/avr32/avr32.c --- gcc-4.4.6.orig/gcc/config/avr32/avr32.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.4.6/gcc/config/avr32/avr32.c 2011-10-22 19:23:08.516581300 +0200 @@ -0,0 +1,8087 @@ +/* + 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, *part_arch; + + /*Add backward compability*/ + if (strcmp ("uc", avr32_arch_name)== 0) + { + fprintf (stderr, "Warning: Deprecated arch `%s' specified. " + "Please use '-march=ucr1' instead. " + "Using 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]; + + /* When architecture implied by -mpart and one passed in -march are + * conflicting, issue an error message */ + part_arch = &avr32_arch_types[avr32_part->arch_type]; + if (strcmp("none",avr32_part_name) && strcmp("none", avr32_arch_name) && strcmp(avr32_arch_name,part_arch->name)) + error ("Conflicting architectures implied by -mpart and -march\n"); + + /* 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[this_regno]); + } + } + + + if (vcall_offset != 0) + { + fprintf (file, "\tld.w\tlr, %s[0]\n", reg_names[this_regno]); + fprintf (file, "\tld.w\tlr, lr[%i]\n", (int) vcall_offset); + fprintf (file, "\tadd\t%s, lr\n", reg_names[this_regno]); + } + + + if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21") + || vcall_offset) + { + fputs ("\tpopm\tlr\n", file); + } + + /* Jump to the function. We assume that we can use an rjmp since the + function to jump to is local and probably not too far away from + the thunk. If this assumption proves to be wrong we could implement + this jump by calculating the offset between the jump source and destination + and put this in the constant pool and then perform an add to pc. + This would also be legitimate PIC code. But for now we hope that an rjmp + will be sufficient... + */ + fputs ("\trjmp\t", file); + assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); + fputc ('\n', file); + } + + +/* Implements target hook vector_mode_supported. */ +bool +avr32_vector_mode_supported (enum machine_mode mode) +{ + if ((mode == V2HImode) || (mode == V4QImode)) + return true; + + return false; +} + + +#undef TARGET_INIT_LIBFUNCS +#define TARGET_INIT_LIBFUNCS avr32_init_libfuncs + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS avr32_init_builtins + +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN avr32_expand_builtin + +tree int_ftype_int, int_ftype_void, short_ftype_short, void_ftype_int_int, + void_ftype_ptr_int; +tree void_ftype_int, void_ftype_ulong, void_ftype_void, int_ftype_ptr_int; +tree short_ftype_short, int_ftype_int_short, int_ftype_short_short, + short_ftype_short_short; +tree int_ftype_int_int, longlong_ftype_int_short, longlong_ftype_short_short; +tree void_ftype_int_int_int_int_int, void_ftype_int_int_int; +tree longlong_ftype_int_int, void_ftype_int_int_longlong; +tree int_ftype_int_int_int, longlong_ftype_longlong_int_short; +tree longlong_ftype_longlong_short_short, int_ftype_int_short_short; + +#define def_builtin(NAME, TYPE, CODE) \ + add_builtin_function ((NAME), (TYPE), (CODE), \ + BUILT_IN_MD, NULL, NULL_TREE) + +#define def_mbuiltin(MASK, NAME, TYPE, CODE) \ + do \ + { \ + if ((MASK)) \ + add_builtin_function ((NAME), (TYPE), (CODE), \ + BUILT_IN_MD, NULL, NULL_TREE); \ + } \ + while (0) + +struct builtin_description +{ + const unsigned int mask; + const enum insn_code icode; + const char *const name; + const int code; + const enum rtx_code comparison; + const unsigned int flag; + const tree *ftype; +}; + +static const struct builtin_description bdesc_2arg[] = { + +#define DSP_BUILTIN(code, builtin, ftype) \ + { 1, CODE_FOR_##code, "__builtin_" #code , \ + AVR32_BUILTIN_##builtin, 0, 0, ftype } + + DSP_BUILTIN (mulsathh_h, MULSATHH_H, &short_ftype_short_short), + DSP_BUILTIN (mulsathh_w, MULSATHH_W, &int_ftype_short_short), + DSP_BUILTIN (mulsatrndhh_h, MULSATRNDHH_H, &short_ftype_short_short), + DSP_BUILTIN (mulsatrndwh_w, MULSATRNDWH_W, &int_ftype_int_short), + DSP_BUILTIN (mulsatwh_w, MULSATWH_W, &int_ftype_int_short), + DSP_BUILTIN (satadd_h, SATADD_H, &short_ftype_short_short), + DSP_BUILTIN (satsub_h, SATSUB_H, &short_ftype_short_short), + DSP_BUILTIN (satadd_w, SATADD_W, &int_ftype_int_int), + DSP_BUILTIN (satsub_w, SATSUB_W, &int_ftype_int_int), + DSP_BUILTIN (mulwh_d, MULWH_D, &longlong_ftype_int_short), + DSP_BUILTIN (mulnwh_d, MULNWH_D, &longlong_ftype_int_short) +}; + + +void +avr32_init_builtins (void) +{ + unsigned int i; + const struct builtin_description *d; + tree endlink = void_list_node; + tree int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); + tree longlong_endlink = + tree_cons (NULL_TREE, long_long_integer_type_node, endlink); + tree short_endlink = + tree_cons (NULL_TREE, short_integer_type_node, endlink); + tree void_endlink = tree_cons (NULL_TREE, void_type_node, endlink); + + /* int func (int) */ + int_ftype_int = build_function_type (integer_type_node, int_endlink); + + /* short func (short) */ + short_ftype_short + = build_function_type (short_integer_type_node, short_endlink); + + /* short func (short, short) */ + short_ftype_short_short + = build_function_type (short_integer_type_node, + tree_cons (NULL_TREE, short_integer_type_node, + short_endlink)); + + /* long long func (long long, short, short) */ + longlong_ftype_longlong_short_short + = build_function_type (long_long_integer_type_node, + tree_cons (NULL_TREE, long_long_integer_type_node, + tree_cons (NULL_TREE, + short_integer_type_node, + short_endlink))); + + /* long long func (short, short) */ + longlong_ftype_short_short + = build_function_type (long_long_integer_type_node, + tree_cons (NULL_TREE, short_integer_type_node, + short_endlink)); + + /* int func (int, int) */ + int_ftype_int_int + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + int_endlink)); + + /* long long func (int, int) */ + longlong_ftype_int_int + = build_function_type (long_long_integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + int_endlink)); + + /* long long int func (long long, int, short) */ + longlong_ftype_longlong_int_short + = build_function_type (long_long_integer_type_node, + tree_cons (NULL_TREE, long_long_integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + short_endlink))); + + /* long long int func (int, short) */ + longlong_ftype_int_short + = build_function_type (long_long_integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + short_endlink)); + + /* int func (int, short, short) */ + int_ftype_int_short_short + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, + short_integer_type_node, + short_endlink))); + + /* int func (short, short) */ + int_ftype_short_short + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, short_integer_type_node, + short_endlink)); + + /* int func (int, short) */ + int_ftype_int_short + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + short_endlink)); + + /* void func (int, int) */ + void_ftype_int_int + = build_function_type (void_type_node, + tree_cons (NULL_TREE, integer_type_node, + int_endlink)); + + /* void func (int, int, int) */ + void_ftype_int_int_int + = build_function_type (void_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + int_endlink))); + + /* void func (int, int, long long) */ + void_ftype_int_int_longlong + = build_function_type (void_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + longlong_endlink))); + + /* void func (int, int, int, int, int) */ + void_ftype_int_int_int_int_int + = build_function_type (void_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, + integer_type_node, + tree_cons + (NULL_TREE, + integer_type_node, + int_endlink))))); + + /* void func (void *, int) */ + void_ftype_ptr_int + = build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, int_endlink)); + + /* void func (int) */ + void_ftype_int = build_function_type (void_type_node, int_endlink); + + /* void func (ulong) */ + void_ftype_ulong = build_function_type_list (void_type_node, + long_unsigned_type_node, NULL_TREE); + + /* void func (void) */ + void_ftype_void = build_function_type (void_type_node, void_endlink); + + /* int func (void) */ + int_ftype_void = build_function_type (integer_type_node, void_endlink); + + /* int func (void *, int) */ + int_ftype_ptr_int + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, ptr_type_node, int_endlink)); + + /* int func (int, int, int) */ + int_ftype_int_int_int + = build_function_type (integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, integer_type_node, + int_endlink))); + + /* Initialize avr32 builtins. */ + def_builtin ("__builtin_mfsr", int_ftype_int, AVR32_BUILTIN_MFSR); + def_builtin ("__builtin_mtsr", void_ftype_int_int, AVR32_BUILTIN_MTSR); + def_builtin ("__builtin_mfdr", int_ftype_int, AVR32_BUILTIN_MFDR); + def_builtin ("__builtin_mtdr", void_ftype_int_int, AVR32_BUILTIN_MTDR); + def_builtin ("__builtin_cache", void_ftype_ptr_int, AVR32_BUILTIN_CACHE); + def_builtin ("__builtin_sync", void_ftype_int, AVR32_BUILTIN_SYNC); + def_builtin ("__builtin_ssrf", void_ftype_int, AVR32_BUILTIN_SSRF); + def_builtin ("__builtin_csrf", void_ftype_int, AVR32_BUILTIN_CSRF); + def_builtin ("__builtin_tlbr", void_ftype_void, AVR32_BUILTIN_TLBR); + def_builtin ("__builtin_tlbs", void_ftype_void, AVR32_BUILTIN_TLBS); + def_builtin ("__builtin_tlbw", void_ftype_void, AVR32_BUILTIN_TLBW); + def_builtin ("__builtin_breakpoint", void_ftype_void, + AVR32_BUILTIN_BREAKPOINT); + def_builtin ("__builtin_xchg", int_ftype_ptr_int, AVR32_BUILTIN_XCHG); + def_builtin ("__builtin_ldxi", int_ftype_ptr_int, AVR32_BUILTIN_LDXI); + def_builtin ("__builtin_bswap_16", short_ftype_short, + AVR32_BUILTIN_BSWAP16); + def_builtin ("__builtin_bswap_32", int_ftype_int, AVR32_BUILTIN_BSWAP32); + def_builtin ("__builtin_cop", void_ftype_int_int_int_int_int, + AVR32_BUILTIN_COP); + def_builtin ("__builtin_mvcr_w", int_ftype_int_int, AVR32_BUILTIN_MVCR_W); + def_builtin ("__builtin_mvrc_w", void_ftype_int_int_int, + AVR32_BUILTIN_MVRC_W); + def_builtin ("__builtin_mvcr_d", longlong_ftype_int_int, + AVR32_BUILTIN_MVCR_D); + def_builtin ("__builtin_mvrc_d", void_ftype_int_int_longlong, + AVR32_BUILTIN_MVRC_D); + def_builtin ("__builtin_sats", int_ftype_int_int_int, AVR32_BUILTIN_SATS); + def_builtin ("__builtin_satu", int_ftype_int_int_int, AVR32_BUILTIN_SATU); + def_builtin ("__builtin_satrnds", int_ftype_int_int_int, + AVR32_BUILTIN_SATRNDS); + def_builtin ("__builtin_satrndu", int_ftype_int_int_int, + AVR32_BUILTIN_SATRNDU); + def_builtin ("__builtin_musfr", void_ftype_int, AVR32_BUILTIN_MUSFR); + def_builtin ("__builtin_mustr", int_ftype_void, AVR32_BUILTIN_MUSTR); + def_builtin ("__builtin_macsathh_w", int_ftype_int_short_short, + AVR32_BUILTIN_MACSATHH_W); + def_builtin ("__builtin_macwh_d", longlong_ftype_longlong_int_short, + AVR32_BUILTIN_MACWH_D); + def_builtin ("__builtin_machh_d", longlong_ftype_longlong_short_short, + AVR32_BUILTIN_MACHH_D); + def_builtin ("__builtin_mems", void_ftype_ptr_int, AVR32_BUILTIN_MEMS); + def_builtin ("__builtin_memt", void_ftype_ptr_int, AVR32_BUILTIN_MEMT); + def_builtin ("__builtin_memc", void_ftype_ptr_int, AVR32_BUILTIN_MEMC); + def_builtin ("__builtin_sleep", void_ftype_int, AVR32_BUILTIN_SLEEP); + def_builtin ("__builtin_avr32_delay_cycles", void_ftype_int, AVR32_BUILTIN_DELAY_CYCLES); + + /* Add all builtins that are more or less simple operations on two + operands. */ + for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) + { + /* Use one of the operands; the target can have a different mode for + mask-generating compares. */ + + if (d->name == 0) + continue; + + def_mbuiltin (d->mask, d->name, *(d->ftype), d->code); + } +} + + +/* Subroutine of avr32_expand_builtin to take care of binop insns. */ +static rtx +avr32_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp,0); + tree arg1 = CALL_EXPR_ARG (exp,1); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode0 = insn_data[icode].operand[1].mode; + enum machine_mode mode1 = insn_data[icode].operand[2].mode; + + if (!target + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + /* In case the insn wants input operands in modes different from the + result, abort. */ + if (!(*insn_data[icode].operand[1].predicate) (op0, mode0)) + { + /* If op0 is already a reg we must cast it to the correct mode. */ + if (REG_P (op0)) + op0 = convert_to_mode (mode0, op0, 1); + else + op0 = copy_to_mode_reg (mode0, op0); + } + if (!(*insn_data[icode].operand[2].predicate) (op1, mode1)) + { + /* If op1 is already a reg we must cast it to the correct mode. */ + if (REG_P (op1)) + op1 = convert_to_mode (mode1, op1, 1); + else + op1 = copy_to_mode_reg (mode1, op1); + } + pat = GEN_FCN (icode) (target, op0, op1); + if (!pat) + return 0; + emit_insn (pat); + return target; +} + + +/* Expand an expression EXP that calls a built-in function, + with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ +rtx +avr32_expand_builtin (tree exp, + rtx target, + rtx subtarget ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + const struct builtin_description *d; + unsigned int i; + enum insn_code icode = 0; + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + tree arg0, arg1, arg2; + rtx op0, op1, op2, pat; + enum machine_mode tmode, mode0, mode1; + enum machine_mode arg0_mode; + int fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + default: + break; + + case AVR32_BUILTIN_SATS: + case AVR32_BUILTIN_SATU: + case AVR32_BUILTIN_SATRNDS: + case AVR32_BUILTIN_SATRNDU: + { + const char *fname; + switch (fcode) + { + default: + case AVR32_BUILTIN_SATS: + icode = CODE_FOR_sats; + fname = "sats"; + break; + case AVR32_BUILTIN_SATU: + icode = CODE_FOR_satu; + fname = "satu"; + break; + case AVR32_BUILTIN_SATRNDS: + icode = CODE_FOR_satrnds; + fname = "satrnds"; + break; + case AVR32_BUILTIN_SATRNDU: + icode = CODE_FOR_satrndu; + fname = "satrndu"; + break; + } + + arg0 = CALL_EXPR_ARG (exp,0); + arg1 = CALL_EXPR_ARG (exp,1); + arg2 = CALL_EXPR_ARG (exp,2); + op0 = expand_normal (arg0); + op1 = expand_normal (arg1); + op2 = expand_normal (arg2); + + tmode = insn_data[icode].operand[0].mode; + + + if (target == 0 + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + + if (!(*insn_data[icode].operand[0].predicate) (op0, GET_MODE (op0))) + { + op0 = copy_to_mode_reg (insn_data[icode].operand[0].mode, op0); + } + + if (!(*insn_data[icode].operand[1].predicate) (op1, SImode)) + { + error ("Parameter 2 to __builtin_%s should be a constant number.", + fname); + return NULL_RTX; + } + + if (!(*insn_data[icode].operand[1].predicate) (op2, SImode)) + { + error ("Parameter 3 to __builtin_%s should be a constant number.", + fname); + return NULL_RTX; + } + + emit_move_insn (target, op0); + pat = GEN_FCN (icode) (target, op1, op2); + if (!pat) + return 0; + emit_insn (pat); + + return target; + } + case AVR32_BUILTIN_MUSTR: + icode = CODE_FOR_mustr; + tmode = insn_data[icode].operand[0].mode; + + if (target == 0 + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + pat = GEN_FCN (icode) (target); + if (!pat) + return 0; + emit_insn (pat); + return target; + + case AVR32_BUILTIN_MFSR: + icode = CODE_FOR_mfsr; + arg0 = CALL_EXPR_ARG (exp,0); + op0 = expand_normal (arg0); + tmode = insn_data[icode].operand[0].mode; + mode0 = insn_data[icode].operand[1].mode; + + if (!(*insn_data[icode].operand[1].predicate) (op0, mode0)) + { + error ("Parameter 1 to __builtin_mfsr must be a constant number"); + } + + if (target == 0 + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + pat = GEN_FCN (icode) (target, op0); + if (!pat) + return 0; + emit_insn (pat); + return target; + case AVR32_BUILTIN_MTSR: + icode = CODE_FOR_mtsr; + arg0 = CALL_EXPR_ARG (exp,0); + arg1 = CALL_EXPR_ARG (exp,1); + op0 = expand_normal (arg0); + op1 = expand_normal (arg1); + mode0 = insn_data[icode].operand[0].mode; + mode1 = insn_data[icode].operand[1].mode; + + if (!(*insn_data[icode].operand[0].predicate) (op0, mode0)) + { + error ("Parameter 1 to __builtin_mtsr must be a constant number"); + return gen_reg_rtx (mode0); + } + if (!(*insn_data[icode].operand[1].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + pat = GEN_FCN (icode) (op0, op1); + if (!pat) + return 0; + emit_insn (pat); + return NULL_RTX; + case AVR32_BUILTIN_MFDR: + icode = CODE_FOR_mfdr; + arg